在PHP⼀句话⽊马使⽤过程中的种种坑点分析
前⾔
在平时的学习和练习过程中,经常会遇到上传的⼀句话⽊马⽆法执⾏我们的命令或者说能执⾏命令但是不能连接菜⼑蚁剑等webshell管理⼯具,以及各个版本PHP所限制的⼀些⼀句话⽊马的写法,不同版本webshell管理⼯具⽆法连接⼀句话⽊马的情况,所以打算仔细的了解⼀下其中的缘由。
什么是webshell
简单来说,webshell就是⼀个以⽹页形式存在的webshell,或者叫做⽹页后门。⼀句话⽊马,⼩马,⼤马这些都可以叫做webshell。⼀句话⽊马就是只需要⼀⾏代码的⽊马,虽然⼀句话⽊马为了绕过waf的检测,出现了很多的变形,但是本质是不变的:⽊马执⾏了我们发送的命令。
⼀句话⽊马中eval和assert的区别
eval 是⼀个语⾔构造器⽽不是⼀个函数
PHP eval() 把字符串按照 PHP 代码来计算。该字符串必须是合法的 PHP 代码,且必须以分号结尾。
如果没有在代码字符串中调⽤ return 语句,则返回 NULL。如果代码中存在解析错误,则 eval() 函数返回 false。
在⼀个php⽂件中,eval执⾏完就会结束,所以当同⼀个php⽂件中有多个eval的时候,只会执⾏第⼀个。
assert 是⼀个函数,assert 这个函数在 php 语⾔中是⽤来判断⼀个表达式是否成⽴。返回 true or false;assert 函数的参数会被执⾏,这跟 eval() 类似。
assert函数在不同php版本中的限制
在php 7.2的版本说明中,我们发现,对assert()函数传⼊字符串参数已经被禁⽤,在8.0版本的时候会被彻底删除。
但是,在这种情况下
<?php
assert($_GET['pass'])
>
我们通过pass传⼊的phpinfo(),system('whoami')不是字符串,所以这种情况下是没有php的版本限制的。
那么什么时候会被这个版本所限制呢?
先说结论:call_user_func 与 assert连⽤时会受到此版本限制
call_user_func 这个函数可以调⽤其它函数,被调⽤的函数是 call_user_func 的第⼀个函数,其余函数作为第⼀个回调函数的参数。通过这种⽅法,可以实现过waf的⼀些操作。
使⽤回调函数写成的⼀句话⽊马对不同php版本进⾏测试
可以看到在php5.4和php7.0版本,这样不受限制正常传参进⾏命令执⾏是没有问题的。
但是在php7.3中,没有回先显。
可以看到,在php7.1版本也没有回显
当我们修改⼀句话中的内容得时候
<?php
@call_user_func(assert,system(dir));
>
命令重新执⾏成功了。
这个原因就是,通过超全局变量$_GET['']获取的攻击者输⼊是字符串,这样传⼊assert函数就触发了禁⽤。但是直接assert(phpinfo())传⼊的参数是函数,所以就不会触发函数禁⽤,可以正常回显。
得到结论:
这个禁⽤特性经过我的测试是从 php 7.1 版本开始的,并不是 7.2 版本才开始(在我本机是这样,师傅们可以在测试⼀下,但是道理是⼀样的)。所以 call_user_func + assert 构造的⼀句话⽊马在 php 7.0 版本及以下可以使⽤。在php7.0以上就不要使⽤这个组合了,以免出现问题。
说到call_user_func这个函数,在这⾥多提⼀点,call_user_func是不能调⽤eval的,这是什么原因呢?
在这⾥,再把上⾯的话重复⼀边
使⽤call_user_func,他的第⼀个参数是要求是函数,⽽ eval 是⼀个语⾔构造器⽽不是⼀个函数,不能被可变函数调⽤。
如何构造WebShell
⽊马的构成⽆⾮就是两部分:
1. 接收攻击者输⼊的参数
2. 命令执⾏函数
在对⼀个webshell进⾏调试的过程中,⼀般采⽤下⾯的⽅法,逐步进⾏
1. 把函数写在 php ⽂件中,看能否执⾏
2. 写成$_GET['']⽅式传⼊命令,看能否执⾏
3. 写成$_POST['']⽅式传⼊命令,能能否执⾏命令
当然2、3步可以合成通过$_REQUEST['']⽅法传⼊命令。通过这样逐步调试的⽅法,虽然有些笨重,但是效果还是⽐较好的,可以清晰的知道,是因为传参问题还是因为本⾝命令执⾏函数的问题导致⽊马失效。
在这⾥补充⼀个坑点
有些版本的中国菜⼑连接php⼀句话不⽀持assert,⽼版本可以
既然⽼版本菜⼑可以连上php的⼀句话⽊马,新的版本连不上。那么,就会想到可能是在菜⼑连接⼀句话⽊马的时候,中间会由于编码问题导致连接失败。当然在后边的操作中证明这个猜想是错误的。
在使⽤wireshark对不同版本的连⼑进⾏抓包的过程中,会发现post发送的三个变量中,只有第⼀个变量是不同的。其余两个变量都相同。那么,很显然,问题就出在第⼀个变量中。在新的版本的第⼀个变量中,存在多条语句,⽽⽼版本的变量⼀⾥⾯只有⼀条语句。
考虑到,既然eval的⼀句话可以使⽤,⽽assert的⼀句话不能使⽤,那应该是eval和assert⽤法不同造成这个问题。通过⽂档可以发现assert 是判断⼀条语句是否为FALSE(注意只是⼀条),⽽eval是把当前字符串作为代码执⾏(可以是多条)。
得出结论:
由于assert的单个语句的限制和新版菜⼑第⼀个变量是多条语句导致assert的⼀句话新版菜⼑不能使⽤。
它所造成的影响是所有assert的⼀句话在新版本的菜⼑中都不能⽤,但可以使⽤⽼版本。
(这⾥的新版本指的是20141213,⽼版本测试的时候⽤的是菜⼑1.0)
bypass WAF
WAF 通常以关键字判断是否为⼀句话⽊马,但是可以通过对⼀句话⽊马的变形,动态调⽤,隐藏或者替换关键字,达到绕过WAF的⽬的。所以想要绕过 WAF,就需要掌握各种 PHP ⼩技巧,掌握的技巧多了,把技巧结合起来,才可以设计出符合当时环境的⼀句话⽊马。
有关具体可以bypass的⼀句话在这⾥就不做罗列了,⽹上有⼤量的学习资源,社区以前的⽂章也有过专门分析如何绕过waf的⽂章。()
好多朋友在学习过程中常会收集⼀些tips,通过这些tips可以让⾃⼰的渗透和挖洞更⾼效。但是攻防始终是动态的,不可能死吃以前的tips,本着学习的态度万变不离其宗,不断地收获⼩技巧⼜不断地消化⼩技巧,才能写出⾃⼰的⼀套⾼质量tips。
关于bypass的思想和⽅法,在这⾥我贴上P神的⽂章()其中讲了⼀类名为回调后门的⼀句话⽊马。其中的思想⾄今仍然是可⽤的,⾮常值得学习。
在写⼀句话⽊马时候,建议⼤家在eval,assert前⾯加上@,虽然对执⾏结果本质上没有什么区别,但是@的作⽤是忽略可能出现的错误。这个⼩细节可以更便于⽊马的隐藏。
⼀句话⽊马在连接webshell管理⼯具的时候常出现的坑点
对于webshell管理⼯具,常见的有以下⼗类:
1.中国菜⼑
使⽤⽅便,⼩巧实⽤,凡是⽀持动态脚本的⽹站,都可以使⽤中国菜⼑进⾏管理。UNICOODE⽅式编译,⽀持多国语⾔输⼊显⽰。
2.蚁剑
开源,跨平台的⽹站管理⼯具,插件很丰富,平常使⽤最多的webshell管理⼯具。
3.C⼑
跨平台基于配置⽂件的中国菜⼑,所有操作由⽤户来定义
4.冰蝎
动态⼆进制加密⽹站管理客户端
5.Xise
6.Altman
7.Weevely
8.QuasiBot
9.Webshell-Snipe
10.WeManager
上边的⼯具,仁者见仁智者见智,适合⾃⼰的就是最好的。我平时⽤的最多的是蚁剑,其次是菜⼑。这⾥分享⼀下我在使⽤菜⼑和蚁剑遇到的坑点。
新版本菜⼑:
上⽂提到过,在新版本的菜⼑不要连接assert的⼀句话。由于assert的单个语句的限制和新版菜⼑第⼀个变量是多条语句导致assert的⼀句话新版菜⼑不能使⽤。
蚁剑:
⾸先是蚁剑的安装,下载后在对蚁剑进⾏初始化的时候要注意两点:
1.安装路径必须是全英⽂路径
2.使⽤管理员⾝份打开并进⾏初始化,否则会遇到下载失败以及代码解压失败等bug。
字符串函数php在蚁剑连接⼀句话⽊马的时候
尽量不要使⽤default和random编码器。使⽤default有些时候会连不上马,使⽤random则可能导致连马失败或者连马的等待时间过长。可以使⽤base64等其他编码。
举例:
<?=1;assert($_POST['a']);?>
default编码:
base64编码:
总结:
本⽂所涉及的内容包括:
⼀句话⽊马中eval和assert的区别
assert函数在不同php版本中的限制
call_user_func + assert组合的使⽤条件
如何构造WebShell
bypass WAF的思路
新⽼版本连接菜⼑出现的问题
⼀句话⽊马在连接webshell管理⼯具的时候常出现的坑点

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。