webshell 介绍
webshell
是以常见的编程语言(PHP
,JAVA
,ASP
,ASPX
或者cgi
)编写的网页文件,最初的目的是为了方便网站管理、服务器管理、权限管理等,使用方法简单,只需写短短几行代码,并且通过网址访问就可进行日常操作,极大的方便了使用者对网站和服务器的管理。因为其方便小巧的特性,如今转变成恶意后门来使用,已达控制网站服务器的目的.
webshell 种类
p牛在19年kcon大会上的议题PHP动态特性的捕捉与逃逸
中,把webshell分成了如下几类:
PHP动态特性的捕捉与逃逸
直接型
直接型言简意赅,直接通过http请求传递要执行的代码
回调型
利用回调函数如call_user_func
、array_map
等,这里就体现了php
的灵活,一段不确定功能的代码,变量值的改变可以导致这段代码发生功能上的变化。
变形型
对webshell中的一些变量名
、恶意代码
,进行混淆、加密、压缩等操作,以达到被查杀的目的。
命令型
也很好理解,直接通过popen和系统进程通信执行命令,常见的如system
、shell_exec
、反引号
等等
包含型
包含型可能是最不容易被查杀的手段,至少静态查杀没有有效的方法,通过包含恶意代码执行的方式将结果带出,日常开发中也有很多地方用到包含的函数如require
、include_once
等等,从开发的角度看,包含型的webshell没有什么明显的特征,只能从流量侧进行查杀。
技巧型
利用对php的一些特性执行恶意代码,如preg_replace \e
执行任意代码、或者利用php的base64_decode
函数的容错性。
针对回调型webshell的检测
针对回调型后门,一般可以用遍历AST Tree
、判断回调参数是否是变量、分析FuncCall Node
,判断是否调用了含有回调参数的函数。
php是一个很神奇的语言,若检测引擎对函数名进行黑名单检测,大部分编程语言的关键字都是大小写敏感,但php可以对函数进行大小写绕过而不改变函数的用法如
uSoRt($_POST[1],$_POST[2]);
当然大部分检测引擎不会犯这么低级的错误。
别名函数
一些函数在php
官方文档搜不到,但实际上是一些函数的别名如 mb_ereg_replace
、mb_eregi_replace
的别名函数,mbereg_replace
、mbereg_ireplace
,他们的作用和preg_replace
一样,在/e
模式下可以执行任意代码,在PHP7
删除了preg_replace
的/e
模式之后,mb_ereg_replace
的/e
模式依然能用,因此可以构造含有别名函数的webshell
以达到绕过的目的
mbereg_replace(‘.*’, ‘\0’, $_REQUEST[2333], ‘mer’);
不过,mbereg_replace
这个别名在PHP7.3
被移除了,所以上述代码只能在7.2及以下的PHP
中使用。
重命名函数
PHP5.6
开始引用函数名的命名空间,可以用
use function A as B
的形式导入A函数,实际写webshell的效果如下:
1 |
|
匿名类与类的继承
类似重命名函数,类的继承也可以理解为一种”重命名”。子类拥有父类的所有方法,也可以做所有父类支持的操作。具体的代码实现如下
1 | class test extends ReflectionFunction {} |
变长参数
变长参数是PHP5.6
引入的新特性,即在PHP
中可以使用func(...$arr)
这样的方式,将$arr
数组展开成多个参数传入func
函数。配合回调后门可变形如下
1 |
|
请求的时候/test.php?1[]=test&1[]=var_dump($_SERVER);&2=assert
即可
控制字符
对于一些PHP
的AST
解释引擎如PHP-Parser
和正常的PHP
的引擎有一些区别,正常的PHP引擎会忽略控制字符,正确执行PHP函数,而PHP-Parser无法正确解析包含控制字符的函数。
控制字符范围
1 | [\x00-\x20] |
所有可以构造带有控制字符的webshell可以绕过一些具有语法解析的webshell检测引擎
1 |
|
PHP标签
打CTF的经常遇到,如果过滤了<?php
,可以用<script languagt="php">
构造webshell
上传绕过限制。
技巧型拓展
利用php扩展库
1 |
|
无字母数字的webshell
1 |
|
利用base64_decode特性
前阵子在代码审计星球,P喵呜
师傅分享了个trick
,php
的base64_decode
函数的容错性很高,即使在一段标准的base64
字符串中乱加内容(一些特殊字符),该函数依然能正确解析,因此可以衍生出包含垃圾字符的webshell
1 |
|
对base64_decode特性的思考
因为打CTF打多了,对base64
比较熟悉,突然想到,能否把base64
和misc
中常见的base64隐写
结合起来,把代码隐藏在base64
加密的后4位字符中。理论是可行的,但经过实验,发现一些难点,首先,base64隐写容错性太低,一段简单的话,需要生成大量的base64字符串表示,如果像蚁剑一样,每次将要执行的代码经过base64隐写再发送到服务器,数据内容会过于臃肿,若再执行一些上传操作或浏览数据库数据的功能,恐怕服务器后端会处理不了大量数据而将数据包舍弃。