代码审计| DuomiCms全局过滤规则绕过

0x00 背景

在看CNVD漏洞库的时候发现有师傅发了某cms前台SQL注入漏洞,通过查阅漏洞描述可知道存在问题的参数是cardpwd,便开始尝试对该版本的cms进行审计。

源码下载地址:https://pan.baidu.com/s/1jIMhDK6

漏洞来源地址:http://www.cnvd.org.cn/flaw/show/CNVD-2017-22079

代码审计| DuomiCms全局过滤规则绕过_第1张图片

0x01 审计过程

1.下载好源码后在本地部署,然后使用seay 源代码审计系统加载源码文件,查找关键字cardpwd得到如下信息,cardpwd参数是在member/mypay.php文件中以POST的方式接收使用的。

代码审计| DuomiCms全局过滤规则绕过_第2张图片

2.进入到member/mypay.php文件(26行和38行)在接收cardpwd参数的值之前还需要进行登录,并且满足$dm=='mypay'

代码审计| DuomiCms全局过滤规则绕过_第3张图片

3.继续跟进$dm并未发现变量被创建的位置,最后在/duomiphp/common.php(52行-55行)中发现接收了GET,POST以及COOKIE中的参数和值,并且创建相应的变量赋予接收到的值,此处可能还存在变量覆盖的问题,本文咱不讨论。

代码审计| DuomiCms全局过滤规则绕过_第4张图片

•到这里我们知道需要访问这个功能需要满足两个条件:

(1)注册并登录

(2)在GET,POST或COOKIE中提交dm=mypay

4.注册会员后访问站点的/member/mypay.php文件,http://127.0.0.1/dm132/member/mypay.php

简单输入1,2 进行请求,确定可以提交cardpwd参数。

代码审计| DuomiCms全局过滤规则绕过_第5张图片

5.继续阅读/member/mypay.php在43-63行之间是对cardkey,cardpwd的处理,并使用了正则[^0-9a-z@\._-]{1,}(union|sleep|benchmark|load_file|outfile)[^0-9a-z@\.-]{1,} 对数据进行检测,分析并对这个正则进行测试,发现使用/*!50000 xxxx*/便可以绕过。

代码审计| DuomiCms全局过滤规则绕过_第6张图片
代码审计| DuomiCms全局过滤规则绕过_第7张图片

6.本以为过滤规则是如此简单,经过测试发现还有其他过滤规则,继续往下分析发现/member/mypay.php在63行要执行SQL语句的时候还使用了GetOne的函数,定位到这个函数所在的位置/doumiphp/sql.class.php的277-300行,GetOne大致做了以下的事情,先清理掉字符串最后面的,和;然后拼接上limit 0,1;使查询的结果只返回一行。

正如代码上面所注释的“//执行一个SQL语句,返回前一条记录或仅返回一条记录”。

代码审计| DuomiCms全局过滤规则绕过_第8张图片

7.拼接后在/doumiphp/sql.class.php在288行执行了SetQuery方法,290行执行了Execute方法,跟进Execute方法,在234行-269行发现了Execute方法的代码块,其中CheckSql是一个关键名称的方法,并且在上方有注释说用于SQL安全检查。

代码审计| DuomiCms全局过滤规则绕过_第9张图片

8.跟进CheckSql在/doumiphp/sql.class.php的537行-642行发现CheckSql方法的代码块,上面有提示 //SQL语句过滤程序,由80sec提供,这里作了适当的修改,经过测试这个过滤规则在598行过滤了/*而且是用硬匹配的方法,所以无法绕过,因此第5步的 /*!50000 xxxx*/的payload无法使用。

代码审计| DuomiCms全局过滤规则绕过_第10张图片

9.联合查询无法使用的情况下就想到的子查询的方法,经过测试无法绕过628行过滤的正则~\([^)]*?select~s进行子查询,无括号的子查询貌似是不存在的吧~ ?!

此时此刻已经是对这个过滤规则研究了一整天,后面也请教了几位师傅,也没有好的方法进行无括号的子查询,其实官方文档上也说了子查询必须有括号。

代码审计| DuomiCms全局过滤规则绕过_第11张图片

10.当没有思路或测试进行不下去的时候,就一定要回头看看一路走来所获得的信息,往往有小惊喜遗留在路上 By Thinking!继续看CNVD中的描述,系统未对变量进行过滤 我突然觉得我下载的是假的源码!!

代码审计| DuomiCms全局过滤规则绕过_第12张图片

这个CMS在/member/mypay.php页面提交任意充值卡号,在卡号密码处使用’or’ 1可以实现任意充值,使用报错注入可以获取user() 或version()的数据,但是无法进行子查询。

•先在后台添加了充值卡。

代码审计| DuomiCms全局过滤规则绕过_第13张图片

•在前台注册并登录后,将cardpwd的值设置为’or’ 1提交,便可以任意充值了,虽然这算一个漏洞,但是在我的观念中这种漏洞不太能说服我。

代码审计| DuomiCms全局过滤规则绕过_第14张图片

11.使用灰盒方式先测试下/member/mypay.php的cardpwd参数。

被/member/mypay.php在43-63行之间的正则过滤了。

代码审计| DuomiCms全局过滤规则绕过_第15张图片

被/doumiphp/sql.class.php的537行-642行的CheckSql方法过滤了。

代码审计| DuomiCms全局过滤规则绕过_第16张图片

未进行'的闭合导致SQL语句报错了。

代码审计| DuomiCms全局过滤规则绕过_第17张图片

12.到这里发现了一个小细节,多了一个'的导致SQL语句报错了?!,在报错信息中发现了插入的cardpwd的值,而不是先提示被过滤了,所以此处肯定有问题,经过测试是第2种情况。

根据这个现象可以推测两种可能:

SQL语句在被过滤前就执行了(×)

多了'导致注入语句被绕过(√)

0x02 确定问题位置

1.确定位我使用的方法是在关键位置使用echo 将传入的cardpwd数据在处理过程中打印出来,首先是在使用/*! 50000union */的情况下提示:Safe Alert: Request Error step 2! 找到这个关键字所在的位置,/doumiphp/sql.class.php的635行,刚好在CheckSql方法内。

代码审计| DuomiCms全局过滤规则绕过_第18张图片
代码审计| DuomiCms全局过滤规则绕过_第19张图片

2.在561-586行有个 //完整的SQL检查 之前一直都在关注过滤规则,并没有在意这个代码块,因为这个CMS都是明文传输,密码处可能会有一些关键字符会触发SQL检测的规则,为了避免这种情况,开发人员便写了这个代码块,用于将SQL语句中两个单引号包裹的数据进行替换处理。

代码审计| DuomiCms全局过滤规则绕过_第20张图片

3.直接在589行处插入echo $clean;将经过这个代码块的数据打印出来,发现确实将单引号内的字符变成了$s$

代码审计| DuomiCms全局过滤规则绕过_第21张图片
代码审计| DuomiCms全局过滤规则绕过_第22张图片

4.在640行处插入echo $db_string;将通过检测的数据打印出来。

代码审计| DuomiCms全局过滤规则绕过_第23张图片
代码审计| DuomiCms全局过滤规则绕过_第24张图片

开发人员为了避免类似密码处的关键字符被过滤,而设计的方法反而让过滤规则绕过成为了可能。

数据跟踪:cardpwd->$pwd->GetOne()->Execute()->CheckSql()->$clean->$db_string

$clean->$db_string 的过程是先经过把数据进行处理(//完整的SQL检查)再赋给$clean,然后把$clean传到各种SQL注入检测规则中,全部通过后返回原始数$db_string,幸运的是在各种过滤规则中没有过滤 `,’,” 号。

因此仅需要利用//完整的SQL检查中的被单引号包裹的字符会被替换为$s$这个功能。

0x03 构造PAYLOAD

要利用单引号将字符包裹且不影响SQL语义,单引号就必需要被转义!

转义单引号的方法:

•SQL注释法:

1./*'*/

2./*!60000'*/

•反引号方法:

1.` ’ `

•双引号方法:

1." ' "

因此可以构造如下PAYLOAD:

利用双引号和反引号:

bypass’or”‘“or extractvalue(1,(select group_concat(0x3a,name,0x3a,password) from duomi_admin`’`))or ‘1

代码审计| DuomiCms全局过滤规则绕过_第25张图片

方便阅读将处理后的结果打印出来:

代码审计| DuomiCms全局过滤规则绕过_第26张图片

利用两个双引号:

bypass’or”‘“or extractvalue(1,(select group_concat(0x3a,name,0x3a,password) from duomi_admin))or “’”=

代码审计| DuomiCms全局过滤规则绕过_第27张图片

方便阅读将处理后的结果打印出来:

代码审计| DuomiCms全局过滤规则绕过_第28张图片

0x04 小小总结

其实这个漏洞整个思路还是很清晰对的审计起来也不困难,但是因为一开始将重点放在了过滤规则的绕过上面,导致花费太多精力在分析正则上,所以当过滤规则有些时候强绕绕不过,或许可以看下代码的其他上下文相关信息,这次的较为灵活的利用//完整的SQL检查绕过了全局的SQL安全检测,本篇绕过了全局的检测,凡是使用到了CheckSql()方法的位置都存在这个问题,最后感谢师傅们的各种协助和讨论。

代码审计| DuomiCms全局过滤规则绕过_第29张图片

你可能感兴趣的:(代码审计| DuomiCms全局过滤规则绕过)