PHPDedeCmsv5.6Parse_str隐式URL解码与变量覆盖引发的SQL注入"

admin 2026-10-16 03:56:16 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

PHP DedeCmsv5.6 Parse\_str 隐式URL解码与变量覆盖 引发的SQL注入

原创

Shelter1234
Shelter1234

安全研究员

2026年10月7日 13:42
浙江

在小说阅读器读本章

去阅读

在公众号小说中沉浸阅读

关键代码

关键行

parse\_str(mchStrCode($pd\_encode, 'DECODE'), $mch\_Post);

foreach ($mch\_Post as $k => $v) $$k = $v;

漏洞详解

parse\_str()函数引发的 SQL 注入和过滤绕过,是 PHP 代码审计中非常经典且高级的漏洞类型。在以 DedeCMS 为代表的早期 PHP 开源程序中,这个漏洞曾多次导致大规模的安全事件。

这个漏洞的本质,是\\“隐式 URL 解码”与“变量覆盖”\\两个危险特性叠加,从而将攻击者的恶意代码“偷运”过了系统的全局防注入检测。

要理解这个漏洞,首先要摸透parse\_str(string $string, array &$result)函数在 PHP 中的机制。

•自动 URL 解码(隐式解码): 当parse\_str()处理字符串时,它不仅会根据&和=来切割键值对,还会对切割出来的键和值自动进行一次urldecode()。

•全局变量覆盖(Variable Overwrite):如果在调用parse\_str($str)时没有传入第二个参数($result数组),PHP 会把解析出的变量直接注册到当前的代码作用域中。这会覆盖掉程序中原本已经存在的同名变量。

早期的 PHP 系统(如 DedeCMS、Discuz! 等)通常会在系统的最入口处(如common.inc.php)写一个全局防注入过滤器。它会遍历$\_GET、$\_POST,如果遇到单引号',就会使用addslashes()将其转义为\'。如果开发者后续在业务代码中使用了parse\_str()处理用户输入,攻击者就可以利用双重 URL 编码完美绕过这个入口防御。

攻防沙盘推演

假设系统的过滤代码和业务代码如下:

正常攻击尝试(被拦截):

•攻击者传入 URL:

?info=order\_id=1'

•PHP 将其接收为

$\_GET['info'] = \"order\_id=1'\"

•全局防注入触发:发现

',转义为\'。此时$str = \"order\_id=1\'\"

•parse\_str($str)

执行后,变量$order\_id = \"1\'\"。

•拼接入 SQL 后为

'1\'',单引号被闭合,注入失败,系统安全。

利用 parse\_str 绕过(攻击成功):

•攻击者知道

parse\_str会自动解码,于是对单引号%27再进行一次 URL 编码,变成%2527。

•攻击者传入 URL:

?info=order\_id=1%2527

•PHP 接收时会自动解码一层:

$\_GET['info'] = \"order\_id=1%27\"

•全局防注入触发:

检查字符串\"order\_id=1%27\"。因为此时字符串里没有真实的单引号,只有%、2、7三个字符,所以addslashes毫无反应直接放行!

•业务代码

$str = \"order\_id=1%27\"

•致命一击:

parse\_str($str)执行,以=拆分后,将1%27 自动进行 URL 解码,变成了1'。并在当前作用域生成变量$order\_id = \"1'\"。

•拼接入 SQL 后为

'1''。单引号未经任何转义进入了 SQL 语句,防线被突破,SQL 注入成功!

现在把视角转回到 DedeCmsv5.6 触发sql注入的关键代码行

看关键代码 parse\_str  16 17行的逻辑,这里虽然使用&result第二个参数,但是下面的行 foreach($mch\_Post as $k => $v) $$k = $v 和不加&result的效果是一样的,都可以创建且覆盖当前变量。顺利的话是可以 ,制造出新的mid 变量的,而mid 变量在下方的sql语句中是使用了拼接的。

这里的逻辑背景是:一个php文件 访问可进入,$pd\_encode 与$pd\_verify 是用户输入的变量。

在进入parse\_str前先要经过verify的验证 ,有验证verify 必有生成verify ,有decode 必有encode ,找到相关的反逻辑

$cfg\_cookie\_encode 是程序的硬编码 ,为NeQLg8853J  ,而pr\_encode 是来自我我们的请求参数,mchStrCode的逻辑就不用看了,这里de en的逻辑是刚好可以反推出来的。

还有主要点GetOne 函数再执行sql语句前会检查sql语句,CheckSql函数调用栈如下

漏洞复现

第一步构造 query 参数 并计算pd\_enccode

第二步进行sql注入

附: CheckSql函数 绕过思路

绕过方法一 不使用 Select 的报错注入

CheckSql的正则重兵把守的是union和(select ...)。但是,如果我们的目的仅仅是验证漏洞或获取当前数据库基础信息(如当前用户、数据库名、版本号),我们完全不需要使用select。

在 MySQL 中,报错注入函数可以直接调用系统函数,不产生子查询。Payload 构造:1' AND updatexml(1,concat(0x7e,user()),1) AND '1'='1

绕过方法二:“解析器差异(Desync)”

如果攻击者必须要用select子查询去提取管理员表(如dede\_admin)里的密码,就必须绕过\([^)]\*?select这个正则。

这里有一个极其高级的绕过技巧,叫做“解析器差异(Parser Desync)绕过”。核心思想是:利用 MySQL 特有的语法,让 PHP 认为危险代码被包含在字符串里从而删掉它,但让 MySQL 正常执行它。

在 MySQL 中,反引号可以用来包裹变量名或字段名。我们可以定义一个名为'(单引号)的用户变量,语法为:@'

终极实战 Payload:

1' AND @' OR updatexml(1,concat(0x7e,(select pwd from dede\_admin limit 1)),1) OR @' AND '1'='1

代入后的完整 SQL:

SELECT \* FROM dede\_member\_operation WHERE mid='1' AND @' OR updatexml(1,concat(0x7e,(select pwd from dede\_admin limit 1)),1) OR @' AND '1'='1' And sta=0 AND product='card' limit 0,1;

CheckSql的while循环只会无脑寻找单引号'来提取字符串,它根本不懂反引号的作用。它在扫描上面的 SQL 语句时,会这样成对匹配单引号:

•第 1 队单引号:

mid='1'(剥离替换为$s$)

•第 2 对单引号:

第一个@'里面的单引号,和第二个@'里面的单引号,被匹配成了一对!

于是,CheckSql会把这两者之间的所有内容当作一段普通的文本字符串,无情地删掉并替换成$s$。最终它生成的$clean字符串变成了这样:

SELECT \* FROM dede\_member\_operation WHERE mid=$s$ AND @$s$ AND $s$=$s$ And sta=0 AND product=$s$ limit 0,1;

结果:在CheckSql眼里,那段极度危险的(select pwd from ...)凭空消失了!所有的关键字检测全部失效,直接放行!语句来到 MySQL 引擎。MySQL 是认识反引号的 AND @'` ,判断变量名为单引号的变量,值为 null,不成立 执行后面的or

纠正网络一些payload的一些错误——主流是给的cfg\_dbprefix 做变量替换

http://127.0.0.1/dede/member/buy\_action.php?product=card&pid=1&a=1%26cfg\_dbprefix=dede\_member\_operation WHERE 1=@'/!12345union/ select 1,2,3,4,5,6,7,8,9,10 FROM (SELECT COUNT(),CONCAT( (SELECT pwd FROM dede\_member LIMIT 0,1),FLOOR(RAND(0)2))x FROM INFORMATION\_SCHEMA.CHARACTER\_SETS GROUP BY x)a %23

cfg\_dbprefix 是DedeSql对象中的成员变量,在初始化的时候就已经被赋值

不确定parse\_str能不能改变对象成员变量,但上面的payload是绝对不行的,不知道作者是怎么复现出来的,

附上dedecms 5.6的下载地址

https://github.com/leixyou/dedecms-version-list-collect/tree/master


PHPDedeCmsv5.6Parse_str隐式URL解码与变量覆盖引发的SQL注入" 网络安全文章

PHPDedeCmsv5.6Parse_str隐式URL解码与变量覆盖引发的SQL注入"

本文分析DedeCMSv5.6中parse_str函数引发的SQL注入漏洞,核心在于隐式URL解码与变量覆盖特性叠加,可绕过全局防注入过滤器。文章详述漏洞原理、复现步骤及CheckSql函数绕过技巧,包括报错注入与解析器差异绕过方法,并给出实战Payload。建议开发者避免直接使用parse_str处理用户输入,并升级安全防护措施。
漏洞预警|知名项目管理软件AtlassianJira曝CVE-2026-21589未授权任意文件读取漏洞,CVSS:9.3大家抓紧修复" 网络安全文章

漏洞预警|知名项目管理软件AtlassianJira曝CVE-2026-21589未授权任意文件读取漏洞,CVSS:9.3大家抓紧修复"

Atlassian旗下Jira等多款自托管产品曝出CVE-2026-21589未授权任意文件读取漏洞,CVSS评分9.3,攻击者无需身份验证即可远程读取敏感文件。官方云端不受影响。建议立即升级至官方安全修复版本,无法立即升级时可通过访问控制、WAF拦截路径遍历字符等临时缓解措施,并排查异常访问日志。
评论:0   参与:  0