BAOCMS 漏洞分析

任意文件读取漏洞,Thinkphp 3.2.x SQL注入,鸡肋ssrf

Posted by SEVENTEEN on June 18, 2021

前言

   强网杯Hard_Penetration题目内网中的cms,当时跟队友在最后一个小时回来看的时候才发现这个cms, 审计到最后也没什么时间了,算是比较可惜。看了几个wp,是搭配着shell写入同名文件来绕过拼接。 不过这个BAOCMS不开源,漏洞应该很多,复现完顺便玩玩。

配置环境

   首先到GitHub下载源码,我用的是搜到的(https://github.com/IsCrazyCat/demo-baocms-v17.1/)。

任意文件读取漏洞

   拿到源码留一眼控制器路由。

   正常安装流程下来,打开主页,发现这里是wap目录为主页。

   定位到wap下到common控制器,可以看到这里有show(),功能大概是解析模版, 这个功能点一般都有文件包含漏洞。

   跟随一下变量流向,调用display()方法。

   从注释中也可以看出来,这里获取传入的文件名并进行解析。

   来到解析流程,可以看到有ob_start(),来观察一下它与ob_get_clean()之间的代码段。 (上面的$templateFile不过是规范下路径格式,盲猜tag()对传入的文件名进行了解析,跟进一下)

   看一眼上面的$templateFile,果然只是规范路径,直接去看tag()。

   重点利用的点来了,这里看到准备加载模版文件了。

   跟进一下,发现这里有个include()来包含模版缓存文件,来看一下缓存文件怎么生成的。

   可以看到这里用了file_get_contents()来获取文件内容, 然后又在if中用file_put_contents()生成了缓存文件。

   构造payload读取文件成功,但上面的file_get_contents()跟include()这个搭配在很多写shell的漏洞中可以看到。 一般实战这种cms也是放在公网上的,那么是否可以尝试获取vps上的内容来include呢。

   答案是不可以的,因为这里的利用点先经过了is_file()的判断。

前台ThinkPHP3.X where() sql注入

   这里可以得到这个cms基于TP3框架开发,翻了翻笔记发现这个版本有几个sql注入。

   果然,这里两个接口都有一样的问题,拿其中一个灰盒测试一下。

   构造cid[0]=exp&cid[1]==1 and sleep(5) -- a,确认是个注入点。

   常规闭合测列数。

   可以得出列数有13。

   一套常规流程拿到后台管理员密码。

   md5解密是123456。

   也可以读文件啦!

   sql最高权限。

   查询secure_file_priv也符合写shell的条件,并且没有目录限制。

   现在来分析一下TP3的where()注入源码。(之前我是觉得TP3的sql注入挺鸡肋的,只是大概看了下就没有去细致分析)

   跑了一段,跟随变量来到可疑的parseWhere()方法。 可以看到这里的foreach将payload数组中的内容作为数组,传入parseWhereItem()方法。

   跟进一下parseWhereItem()方法,取第一个元素作为表达式(这里表达式即为exp), 如果你输入别的内容页面是会回显表达式错误的。然后进入elseif分支,将数组第二个元素拼接进sql语句。

   从这里也可以看到拼接成利用的sql语句。

   分析到这里,还是不知道为什么要以数组的形式传payload,从而达到sql注入。 所以,我传了一个cid=1))-- a,康康这个数组到底是绕过哪个地方。

   对比了一下代码执行流程,很快发现了问题所在。 这里用is_scalar()函数判断是否进入_parseType()方法。

   查了一下手册,当传入的是数组的时候,这个函数返回为false, 所以payload不会进入_parseType()方法。那么肯定在_parseType()方法里有过滤payload的地方。

   进入这个函数跑一跑,可以看到这里有个intval()函数来过滤payload。 所以当payload不是数组的时候,构造的恶意语句会被intval()函数变为数字。

文件包含漏洞

   从前台的show()方法跟display()方法,再到后台的settings()方法, 都可以进行文件包含。

   不过需要注意的是只有前台的show()方法没有经过$this->parseTemplate()方法检查, 才可以任意读取文件,因为其它的几个方法都会被$this->parseTemplate()方法拼接.html后缀导致读取文件失败, 需要搭配一个同名的html文件才能利用。

鸡肋ssrf

   这里有个curl_exec()来ssrf攻击,但可惜的是没有回显。 构造payload:/api/user/httpRequest?url=。 这里能打的可能性不是很大,除非是很熟悉目标内网应用架构,或者目标满足php-fpm未授权访问的利用点。

失败的xxe注入

   审计了一个xxe的点,很可惜第三个参数为LIBXML_NOCDATA,输出的是对象,也没有对实体进行解析。 (第三个参数是LIBXML_NOENT的话,可以利用)

There Is Nothing Below

   

Turn at the next intersection.