- 從0到1:CTFer成長(zhǎng)之路
- Nu1L戰(zhàn)隊(duì)
- 4092字
- 2021-01-07 17:31:56
2.2 命令執(zhí)行漏洞
通常情況下,在開(kāi)發(fā)者使用一些執(zhí)行命令函數(shù)且未對(duì)用戶輸入的數(shù)據(jù)進(jìn)行安全檢查時(shí),可以注入惡意的命令,使整臺(tái)服務(wù)器處于危險(xiǎn)中。作為一名CTFer,命令執(zhí)行的用途如下:①技巧型直接獲取flag;②進(jìn)行反彈Shell,然后進(jìn)入內(nèi)網(wǎng)的大門;③利用出題人對(duì)權(quán)限的控制不嚴(yán)格,對(duì)題目環(huán)境擁有控制權(quán),導(dǎo)致其他隊(duì)伍選手無(wú)法解題,這樣在時(shí)間上會(huì)占一定優(yōu)勢(shì)。
在CTF中,命令執(zhí)行一般發(fā)生在遠(yuǎn)程,故被稱為遠(yuǎn)程命令執(zhí)行,即RCE(Remote Command Exec),也被稱為RCE(Remote Code Exec)。本節(jié)的RCE皆為遠(yuǎn)程命令執(zhí)行。
本節(jié)將闡述常見(jiàn)的RCE漏洞和繞過(guò)WAF的方案,再通過(guò)一些經(jīng)典題目讓讀者對(duì)CTF中的RCE題目有所了解。
2.2.1 命令執(zhí)行的原理和測(cè)試方法
下面介紹命令注入的基本原理,包括cmd.exe、bash程序在解析命令的時(shí)候會(huì)存在哪些問(wèn)題、在不同的操作系統(tǒng)中執(zhí)行命令會(huì)存在哪些異同點(diǎn)等,以及在CTF題目中應(yīng)該如何進(jìn)行測(cè)試,直到最終獲取flag。
2.2.1.1 命令執(zhí)行原理
在各類編程語(yǔ)言中,為了方便程序處理,通常會(huì)存在各種執(zhí)行外部程序的函數(shù),當(dāng)調(diào)用函數(shù)執(zhí)行命令且未對(duì)輸入做過(guò)濾時(shí),通過(guò)注入惡意命令,會(huì)造成巨大的危害。
下面以PHP中的system()函數(shù)舉例:

該代碼的正常功能是調(diào)用操作系統(tǒng)的echo程序,將從d參數(shù)接收的字符串作為echo程序的輸入,最終system()函數(shù)將echo程序執(zhí)行的結(jié)果返回在網(wǎng)頁(yè)中,其在操作系統(tǒng)執(zhí)行的命令為“echo for test”,最終在網(wǎng)頁(yè)顯示為“for test”,見(jiàn)圖2-2-1。

圖2-2-1
當(dāng)改變d參數(shù)為“for test%26%26 whoami”時(shí),網(wǎng)頁(yè)會(huì)多出whoami程序的執(zhí)行結(jié)果,這是因?yàn)楫?dāng)前在系統(tǒng)執(zhí)行的命令為“echo for test&&whoami”,見(jiàn)圖2-2-2。

圖2-2-2
通常為了解決URL中的歧義表達(dá),會(huì)將一些特殊字符進(jìn)行URL編碼,“%26”便是“&”的URL編碼。為什么注入“&&”字符就可以造成命令注入呢?類似的還有其他什么字符嗎?
在各類編程語(yǔ)言中,“&&”是and語(yǔ)法的表達(dá),一般通過(guò)如下格式進(jìn)行調(diào)用:

當(dāng)兩邊的表達(dá)式都為真時(shí),才會(huì)返回真。類似的語(yǔ)法還有or,通常用“||”表示。注意,它們存在惰性,在and語(yǔ)法中,若第一個(gè)表達(dá)式的結(jié)果為假,則第二個(gè)表達(dá)式不會(huì)執(zhí)行,因?yàn)樗銥榧佟Ecor語(yǔ)法類比,若第一個(gè)表達(dá)式為真,則第二個(gè)表達(dá)式也不會(huì)執(zhí)行,因?yàn)樗銥檎妗?/p>
所以,命令注入就是通過(guò)注入一些特殊字符,改變?cè)镜膱?zhí)行意圖,從而執(zhí)行攻擊者指定的命令。
2.2.1.2 命令執(zhí)行基礎(chǔ)
在測(cè)試前,我們需要了解cmd.exe、bash程序在解析命令時(shí)的規(guī)則,掌握Windows、Linux的異同點(diǎn)。
1.轉(zhuǎn)義字符
系統(tǒng)中的cmd.exe、bash程序執(zhí)行命令能夠解析很多特殊字符,它們的存在讓BAT批處理和bash腳本處理工作更加便捷,但是如果想去掉特殊字符的特殊意義,就需要進(jìn)行轉(zhuǎn)義,所以轉(zhuǎn)義字符即為取消字符的特殊意義。
Windows的轉(zhuǎn)義字符為“^”,Linux的轉(zhuǎn)義字符為“\”,分別見(jiàn)圖2-2-3和圖2-2-4。可以看到,原本存在特殊意義的“&”被取消意義,從而在終端中輸出。

圖2-2-3

圖2-2-4
2.多條命令執(zhí)行
在命令注入中通常需要注入多條命令來(lái)擴(kuò)大危害,下面是一些能夠構(gòu)成多條命令執(zhí)行的字符串:Windows下,&&、||、%0a;Linux下,&&、||、;、$()、``、%0a、%0d。圖2-2-5、圖2-2-6分別為Windows和Linux下的多條命令執(zhí)行。圖2-2-5中顯示了“noexist||echo pwnpwnpwn”,noexist程序本身不存在,所以報(bào)錯(cuò),但是通過(guò)注入“||”字符,即使前面報(bào)錯(cuò),還會(huì)執(zhí)行后面的“echo pwnpwnpwn”命令。
在上面的例子中,“&&”和“||”利用條件執(zhí)進(jìn)行多條命令執(zhí)行,“%0a”和“%0d”則是由于換行而可以執(zhí)行新的命令。另外,在Linux中需要注意,雙引號(hào)包裹的字符串“$()”或“``”中的內(nèi)容被當(dāng)作命令執(zhí)行,但是單引號(hào)包括的字符串就是純字符串,不會(huì)進(jìn)行任何解析,見(jiàn)圖2-2-7。

圖2-2-5

圖2-2-6

圖2-2-7
3.注釋符號(hào)
與代碼注釋一樣,當(dāng)合理利用時(shí),命令執(zhí)行能夠使命令后面的其他字符成為注釋內(nèi)容,這樣可以降低程序執(zhí)行的錯(cuò)誤。
Windows的注釋符號(hào)為“::”,在BAT批處理腳本中用得較多;Linux的注釋符號(hào)為“#”,在bash腳本中用得較多。
2.2.1.3 命令執(zhí)行的基本測(cè)試
在面對(duì)未知的命令注入時(shí),最好通過(guò)各種Fuzz來(lái)確認(rèn)命令注入點(diǎn)和黑名單規(guī)則。一般命令的格式如下:

下面以ping-nc 1 www.baidu.com為例構(gòu)建Fuzz列表。
? 程序名:ping。
? 參數(shù):-nc。
? 參數(shù)值:1和www.baidu.com。
? 程序名與參數(shù)值之間的字符串:空格。
? 整個(gè)命令。
參數(shù)值有時(shí)較為復(fù)雜,可能是部分可控的,被雙引號(hào)、單引號(hào)包裹,這時(shí)需要注入額外的引號(hào)來(lái)逃逸。比如,構(gòu)造Fuzz列表:

再通過(guò)將Fuzz列表插入命令點(diǎn)后,通過(guò)查看自己服務(wù)器的Web日志來(lái)觀察是否存在漏洞。
2.2.2 命令執(zhí)行的繞過(guò)和技巧
本節(jié)介紹在CTF中解答命令執(zhí)行題目的技巧,命令執(zhí)行的題目需要把控的因素比較多,如權(quán)限的控制、題目接下來(lái)的銜接。但是命令執(zhí)行比較簡(jiǎn)單、粗暴,經(jīng)常存在技巧性繞過(guò)的考點(diǎn)。
2.2.2.1 缺少空格
在一些代碼審計(jì)中經(jīng)常會(huì)禁止空格的出現(xiàn)或者會(huì)將空格過(guò)濾為空,下面將講解如何突破。例如,對(duì)于如下PHP代碼:

將cmd參數(shù)中的空格過(guò)濾為空,導(dǎo)致執(zhí)行“echo pwnpwn”命令失敗,見(jiàn)圖2-2-8。

圖2-2-8
但是在命令中間隔的字符可以不只是空格(URL編碼為“%20”),還可以利用burp suite對(duì)%00~%ff區(qū)間的字符串進(jìn)行測(cè)試,可以發(fā)現(xiàn)還能用其他字符進(jìn)行繞過(guò),如“%09”“%0b”“%0c”等。
利用burp suite進(jìn)行Fuzz,見(jiàn)圖2-2-9。再次輸入“%09”字符,即“echo%09pwnpwnpwn”,就能發(fā)現(xiàn)可以繞過(guò)空格的限制,見(jiàn)圖2-2-10。

圖2-2-9

圖2-2-10
以上只是其中一種通用去Fuzz未知情況的方式。若將“%0a”“%0d”等不可見(jiàn)字符都禁止,還可以通過(guò)字符串截取的方式獲取空格。
1.Windows下
例如,命令如下:

其中,“~”相當(dāng)于截取符,表示獲取環(huán)境變量%ProgramFiles%的值,一般為C:\Program Files。所以,以上命令表示,從第10個(gè)開(kāi)始且獲取一個(gè)字符串,也就是空格,見(jiàn)圖2-2-11。

圖2-2-11
2.Linux下
Linux中也有一些繞過(guò)空格執(zhí)行的方式:

bash有效,zsh、dash無(wú)效:

讀取文件時(shí):

$IFS$9:Linux存在IFS(Internal Field Separator)環(huán)境變量,即內(nèi)部字段分隔符,定義了bash shell的命令間隔字符,一般為空格。注意,當(dāng)只注入$IFS時(shí),即執(zhí)行的命令結(jié)果為echo$IFSaaa,可以發(fā)現(xiàn)解析后的$IFSaaa變量是不存在的,所以需要間隔符來(lái)避免,通常使用“$9”。“$9”表示為當(dāng)前系統(tǒng)Shell進(jìn)程的第9個(gè)參數(shù),通常是一個(gè)空字符串,即最終能成功執(zhí)行的命令為“echo$IFS$9aaa”。
當(dāng)然,還可以使用“${IFS}”進(jìn)行注入,或者在某些平臺(tái)下通過(guò)修改IFS變量為逗號(hào)來(lái)進(jìn)行注入,即“;IFS=,;”,見(jiàn)圖2-2-12。

圖2-2-12
2.2.2.2 黑名單關(guān)鍵字
在CTF比賽中,有時(shí)會(huì)遇上黑名單關(guān)鍵字,如對(duì)cat、flag等字符串進(jìn)行攔截,這時(shí)可以用下面的方式繞過(guò)。
1.利用變量拼接

其中,a變量為c,b變量為at,最終$a$b是cat。c變量為he,d變量為llo,最終${c}$w1jcj8o為hello,所以在這里執(zhí)行的命令是“cat hello”。
2.使用通配符
在通配符中,“?”代表任意一個(gè)字符串,“*”則代表任意個(gè)字符串。

可以看到,上面通過(guò)cat、type命令,結(jié)合通配符,實(shí)現(xiàn)了對(duì)黑名單字符串的繞過(guò)。
3.借用已有字符串
若是禁用“<>?”等字符串,則可以借用其他文件中的字符串,利用substr()函數(shù)截取出某個(gè)具體字符。繞過(guò)執(zhí)行結(jié)果見(jiàn)圖2-2-13。

圖2-2-13
2.2.2.3 執(zhí)行無(wú)回顯
在CTF中,我們經(jīng)常遇到命令執(zhí)行的結(jié)果不在網(wǎng)頁(yè)上顯示的情況,這時(shí)可以通過(guò)以下幾種方式獲取執(zhí)行結(jié)果。
在開(kāi)始前,推薦搭建一個(gè)VTest平臺(tái)https://github.com/opensec-cn/vtest,以便測(cè)試。搭建完成后,開(kāi)始測(cè)試,測(cè)試代碼如下:

1.HTTP通道
假設(shè)自己的域名為example.com,下面以獲取當(dāng)前用戶權(quán)限為例。
在Windows下,目前只能通過(guò)相對(duì)復(fù)雜的命令進(jìn)行外帶(如果未來(lái)Windows支持Linux命令,將更加方便數(shù)據(jù)外帶):

通過(guò)for命令,將echo hello執(zhí)行的結(jié)果保存在%x變量中,然后拼接到URL后。
以上命令執(zhí)行后,默認(rèn)瀏覽器會(huì)被系統(tǒng)調(diào)用打開(kāi)并訪問(wèn)指定的網(wǎng)站,最終可以在平臺(tái)上面獲取echo hello命令的執(zhí)行結(jié)果,見(jiàn)圖2-2-14。

圖2-2-14
但是其缺陷是調(diào)用瀏覽器后并不會(huì)關(guān)閉,并且遇上特殊字符、空格時(shí)會(huì)存在截?cái)鄦?wèn)題,所以可以借用powershell進(jìn)行外帶數(shù)據(jù)。在Powershell 2.0下,執(zhí)行如下命令:

這里是對(duì)echo hello的執(zhí)行結(jié)果進(jìn)行Base64編碼,然后通過(guò)Web請(qǐng)求將結(jié)果發(fā)送出去。
在Linux下,由于存在管道等,因此極其方便數(shù)據(jù)的傳輸,通常利用curl、wget等程序進(jìn)行外帶數(shù)據(jù)。例如:

上面便是利用多條命令執(zhí)行中的“`”和“$()”進(jìn)行字符串拼接,最終通過(guò)curl、wget等命令向外進(jìn)行請(qǐng)求,從而實(shí)現(xiàn)了數(shù)據(jù)外帶,見(jiàn)圖2-2-15。

圖2-2-15
2.DNS通道
經(jīng)常我們會(huì)以ping來(lái)測(cè)試DNS外帶數(shù)據(jù),ping的參數(shù)在Windows與Linux下有些不同。如限制ping的個(gè)數(shù),在Windows下是“-n”,而在Linux下是“-c”。為了兼容性處理,可以聯(lián)合使用,即“ping-nc 1 test.example.com”。
在Linux下:

在Windows下相對(duì)復(fù)雜,主要利用delims命令進(jìn)行分割處理,最終拼接到域名前綴上,再利用ping程序進(jìn)行外帶。
<1>獲取計(jì)算機(jī)名:

<2>獲取用戶名:

3.時(shí)間盲注
網(wǎng)絡(luò)不通時(shí),可以通過(guò)時(shí)間盲注將數(shù)據(jù)跑出來(lái),主要借用“&&”和“||”的惰性;在Linux下可使用sleep函數(shù),在Windows下則可以選擇一些耗時(shí)命令,如ping-n 5 127.0.0.1。
4.寫入文件,二次返回
有時(shí)會(huì)遇上網(wǎng)絡(luò)隔離的情況,time型讀數(shù)據(jù)將會(huì)極其緩慢,可以考慮將執(zhí)行命令結(jié)果寫入到Web目錄下,再次通過(guò)Web訪問(wèn)文件從而達(dá)到回顯目的。例如,通過(guò)“>”重定向,將結(jié)果導(dǎo)出到Web目錄http://www.nu1l.com/exec/3.php?cmd=whoami>test下,再次訪問(wèn)導(dǎo)出文件http://www.nu1l.com/exec/test,便可以得到結(jié)果,見(jiàn)圖2-2-16。

圖2-2-16
2.2.3 命令執(zhí)行真題講解
CTF比賽中單純考查命令注入的題目較為少見(jiàn),一般會(huì)將其組合到其他類型的題目,更多的考點(diǎn)偏向技巧性,如黑名單繞過(guò)、Linux通配符等,下面介紹一些經(jīng)典題目。
2.2.3.1 2015 HITCON BabyFirst
PHP代碼如下:

題目為每人創(chuàng)建一個(gè)沙盒目錄,然后通過(guò)正則“^\w+$”進(jìn)行字符串限制,難點(diǎn)在于正則的繞過(guò)。因?yàn)檎齽t“/^\w+$/”沒(méi)有開(kāi)啟多行匹配,所以可以通過(guò)“\n”(%0a)換行執(zhí)行其他命令。這樣便可以單獨(dú)執(zhí)行touch abc命令:

再新建文件1,內(nèi)容設(shè)置為bash反彈shell的內(nèi)容,其中192.168.0.9為VPS服務(wù)器的IP,23333為反彈端口。然后利用Python的pyftpdlib模塊搭建一個(gè)匿名的FTP服務(wù),見(jiàn)圖2-2-17。

圖2-2-17
最后使用busybox中的ftp命令獲取文件:

將IP轉(zhuǎn)換為十進(jìn)制,即192.168.0.9的十進(jìn)制為3232235529,可以通過(guò)ping驗(yàn)證最終請(qǐng)求的IP是否正確的。
轉(zhuǎn)換腳本如下:

服務(wù)器監(jiān)聽(tīng)端口情況見(jiàn)圖2-2-18。

圖2-2-18
最終整個(gè)解題過(guò)程如下。利用FTP下載反彈Shell腳本:

然后執(zhí)行Shell腳本:

2.2.3.2 2017 HITCON BabyFirst Revenge
PHP代碼如下:

上面的代碼中最關(guān)鍵的限制便是命令長(zhǎng)度限制,strlen($_GET['cmd'])<=5意味著每次執(zhí)行的命令長(zhǎng)度只能小于等于5。
解決方法是利用文件名按照時(shí)間排序,最后使用“ls-t”將其拼接。當(dāng)然,在拼接的過(guò)程中,可以利用“\”接下一行字符串,即將touch程序用“\”分開(kāi),見(jiàn)圖2-2-19。
最終,整個(gè)解題過(guò)程如下:寫入ls-t>g到_文件;寫入payload;執(zhí)行_,生成g文件;最后執(zhí)行g(shù)文件,從而反彈Shell。利用腳本如下:

圖2-2-19

其中生成g文件的內(nèi)容見(jiàn)圖2-2-20。

圖2-2-20

圖2-2-20
2.2.3.3 2017 HITCON BabyFirst Revenge v2
PHP代碼如下:

這就是之前BabyFirst Revenge的升級(jí)版本,限制命令長(zhǎng)度只能小于等于4。其中,ls>>_不能使用。
在Linux下,“*”的執(zhí)行效果類似“$(dir*)”,即dir出來(lái)的文件名會(huì)被當(dāng)成命令執(zhí)行。

t的順序是比s靠后,所以可以找到h并加在t前面,以提高這個(gè)文件名最后排序的優(yōu)先級(jí)。所以,在“*”執(zhí)行時(shí),其實(shí)執(zhí)行的命令為:

最終,v文件的內(nèi)容是:

接下來(lái)寫入一個(gè)rev文件,然后使用“*v”命令,因?yàn)橹挥衦ev、v兩個(gè)帶v的文件,所以其執(zhí)行的命令是“rev v”,再將逆轉(zhuǎn)的v文件內(nèi)容放入x文件。
最終,x文件的內(nèi)容是:

后面寫payload的方式與v1解題一樣。
- 白話網(wǎng)絡(luò)安全2:網(wǎng)安戰(zhàn)略篇
- Web漏洞分析與防范實(shí)戰(zhàn):卷1
- 為你護(hù)航:網(wǎng)絡(luò)空間安全科普讀本(第2版)
- 網(wǎng)絡(luò)空間安全:管理者讀物
- 電子支付的規(guī)制結(jié)構(gòu)配置研究
- 暗戰(zhàn)亮劍:黑客滲透與防御全程實(shí)錄
- Getting Started with FortiGate
- Kali Linux Wireless Penetration Testing Cookbook
- 網(wǎng)絡(luò)安全與攻防入門很輕松(實(shí)戰(zhàn)超值版)
- 隱私計(jì)算:推進(jìn)數(shù)據(jù)“可用不可見(jiàn)”的關(guān)鍵技術(shù)
- Mastering Malware Analysis
- 黑客攻防從入門到精通:命令版
- 網(wǎng)絡(luò)空間安全實(shí)戰(zhàn)基礎(chǔ)
- 黑客攻防從入門到精通:絕招版(第2版)
- INSTANT Microsoft Forefront UAG Mobile Configuration Starter