记录一次lmxcms审计sql注入到rce审计全过程

欢迎各位师傅关注我的个人公众号: Gat4by

前言:马上过年了就要忙起来了,后面大年初一初二可能没时间玩电脑了,趁着这几天手感火热,审一审比较著名的梦想cms。

项目源码: http://www.lmxcms.com/down/

安装好了这个cms后台进去长这样,看着这界面写的挺糙的,一眼满是漏洞的感觉,今天来审计练习一下RCE漏洞。

我审计PHP的CMS的RCE的思路就是先去找是否有eval()函数的存在,先来一手全局查找eval()函数,接着我们锁定eval()函数中是变量而不是预定义常量的。

于是来到一处eval()函数处,这里很奇怪eval函数是根据$temdata的data字段取值出来,也就是说他是根据传入变量的data列取出参数,开发人员还是比较谨慎,data都是提前写好放进数据库里的,那么我们跟进一下数据库看看。

$temdata是调用model模型类的caijiDataOne()方法获取的,并且GET请求获取到的参数cid作为传入参数。

接着让我们跟进一下caijiDataOne()方法,发现做了一个sql查询。

因为我本地环境这里没有预设该表所以为空表,但是正常的业务逻辑也不会使得data列中有诸如whoami什么的语句,那不送洞给黑客嘛。

此时再观察一下我们的cms的url不难发现,其实管理员admin.php为其后台管理入口路由,通过m和a来进行调用程序。

这是管理员登录进入后的页面admin.php?m=Index&a=index。

管理员登录页面 admin.php?m=Login&a=index。

其实此时便可以猜测该cms的管理员路由其实是由m和a两个参数来进行索引,m表示加载的controller文件。

回到我们刚刚存在eval()函数的php文件中,先来看项目架构,这里我审计的是后台漏洞,就主要看以下几个部分,c目录应该就是controller层,controller下还有admin、index、install这些目录,重点我们关注admin目录。

然后发现刚刚登录调用的是LoginAction.class.php所以路由中m=Login,那么我们要寻找AcquisiAction.class.php的路由自然是m=Acquisi。

接着还有个发现,发现该路由中存在许多方法比如index(),login()这些的,然后index()是判定登录状态的,没有登录则会跳转到登录页面,我这里猜测了一下a传参应该就是调用路由中的方法,那么我们再登录抓包验证一下。

好家伙!到这里我们代码审计的路由寻找问题解决了,此时已经知道m是路由对应的是c/admin下的action控制文件,a代表调用其文件中的方法。

回到我们要审计的文件开始进行审计,路由就是m=Acquisi&a=showCjData。

阿巴阿巴......一来就直接sql报错,不道怎么回事0.o?

打上断点开始调试咯,开始给lid,id,cid这几个参数进行传参。

单步调试,先给lid进行传参,从mysql监控器中发现是一点都没过滤啊。

但是页面出现报错,意思是咱们字段不匹配,union查询后跟的字段数应该和前一个select查询字段数语句相同,前面那个select语句是查询全部字段,查的是lmx_cj_list表。

那个表居然有29个字段!!!

那么试试新的payload,我这里为了防止字段类型不匹配导致报错,所以全设置的为null,接着奇怪的地方来了,payload在web报错了,但是查看sql监控后带入数据库管理工具又能成功执行,说明便不是该字段的问题,想起还有两个字段没有尝试,都尝试尝试下

lid=1 union select null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null --+

新添加字段id=1和cid=1,web报错后此时看sql监控,发现其他两个参数lid和cid压根没有带入,但是根据前面我们成功用payload带入到sql查询语句,说明lid字段是可控的,很大概率存在sql注入,剩下的应该看如何构造sql语句了。

因为cid是通过get方式获取的,所以cid以get方式传参,另外两个参数我们尝试丢postdata中传参,三个参数此时都带入sql语句中了。

我们对另外两个字段尝试使用union select拼接看看,同样的报错因为union前后select查询的字段数应该相同。

不得不说sql监控工具yyds!此时知道了id参数查询的表为lmx_cj,另一个参数cid貌似没带入sql语句中执行,先解决lmx_cj表的字段匹配问题。

4个字段,postdata更改payload。

lid=1 union select null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null,null --&id=1 union select null,null,null,null --

此时又发现了报错,同样是字段不匹配的问题。

我们查看sql监控工具,一切豁然开朗!我之前id=select 1,2,3和cid=select 4,5,6就是为了区别不同表的相同参数id,因为sql报错只报错一个所以先解决第一个带入查询的id对应的lmx_cj表的字段id,接着发现get请求的cid对应的是lmx_cj_data的id,那么继续解决union的字段匹配问题。

cid对应数据表有七个字段 。

完整payload如下。

此时三个参数的sql构造问题得到完美解决,三个参数可控且成功将payload带入执行!

以下这两行代码很关键,我们逆推eval()函数执行$data是从$temdata的data字段获取的,$temdata又是通过cid进行查询的,再看sql监控,当我们带入cid查询时是查询的lmx_cj_data表。

这里跟进一下 caijiDataOne()函数同样可以证明是lmx_cj_data表,其表第三个字段即是要取的data列数据。

那么思路就明确了,我这里本地演示的是空表,但是实际情况下别人不可能是空表,此时就要利用select union select 的特性来构造无中生有,当前面的select查询的数据无效,则会判定union后的select语句来进行查询结果带入回显,我们使得cid对应的payload的第三个null改为phpinfo();即可,但是此时依然报错,且sql监控没我们的关于lmx_cj_data表的执行语句。

判断应该是构造闭合的问题,我们接着打上引号闭合好phpinfo();

看看cid=1 union select null,null,'phpinfo();',null,null,null,null

发现成功执行phpinfo(),rce到手!

Sql监控跟踪发现成功带入phpinfo();

总结: 在代码审计过程中,发现存在sql语句交互且eval()函数执行参数是从sql语句查询出来的,这时候先查看是否存在sql注入,可以先利用union select查询空字段去判断sql语句是否成功带入payload,带入后我们再进一步去尝试rce。

  • 17
    点赞
  • 25
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值