熟悉情况

照例先简单看看目录首页文件配置文件过滤函数等。
首页就引用了两个php文件和首页html文件

include/common.inc.php
include/index.fun.php
/index.html

(粗略过了几个php文件,都引用了common.inc.php,如果有全局过滤,那么十有八九就在这里)
在common.inc.php文件的get_magic_quotes_gpc()中,发现对$_POST$_GET$_COOKIES$_REQUEST统一进行了过滤,使用addslashes()函数:

不过挖洞这件事,它妙就妙在总能找到一条活路,比如它的数据库使用gb2312编码:

后记:在搞明白这个程序的全局过滤的方法和缺点后,粗略定下绕过方向:

  1. 数字型注入
  2. 宽字节注入
  3. 非请求方法输入点

搞懂路由

搭建好后,新建个新闻分类和新闻内容,首先想看看前台有没有注入,这款bluecms的路由非常简单明了,就是php文件对应功能,参数也是在这个文件中select对应的数据内容,而不是什么参数对应什么目录什么文件。
http://cms:8811/news.php?id=1

功能点方式审计

评论处SQLi
从程序的功能点作为审计方向,优点是速度快,缺点是功能点触及不到的漏洞会被忽视掉。
这里我选择新闻评论功能进行审计;
路径:/comment.php?act=send
data: mood=6&comment=33&id=1&type=1&submit=%CC%E1%BD%BB%C6%C0%C2%DB

直接打开bluecms/comment.php文件,代码中变量moodtypeid使用了intval()函数只认数字类型值,变量comment则使用了htmlspecialchars()函数,将特殊字符HTML实体化,还有对各个请求方法的统一过滤(common.inc.php文件的get_magic_quotes_gpc()):

不懂的函数方法就去php.net查询:

看下来参数都被过滤了,其他几个变量也不是可控变量(不是POST/REQUEST),再仔细看看里面还有个getip(),是个获取用户IP的函数,有获取就一定有输入,重要的是输入可不可控
getip()不走$_POST/$_REQUEST,也没有其他过滤

看了getip()函数里的内容就大概知道是怎么回事了,请求信息头客户端IP字段
构造payload:X-Forwarded-For: 127.0.0.1'
sqlmap直接能跑,但懒得贴出来占篇幅

搜索处与登录处SQLi
首先是搜索处,搜索URL直接是search.php,5个data参数cid、aid、keywords、x、y:

打开search.php文件查看源码,前面定义其中三个参数时,cidaid直接使用了intval()处理函数只接受数字类型值,不过keywords没有做什么处理,这里就是我们的机会,尝试宽字节绕全局过滤:


构建好请求包漏洞点后发给sqlmap直接跑:
因为是搜索型,不在后面加个百分号它不会跑出来,但其实监测数据库是可以看到它语句执行了的,还有个奇怪的就是,trim()函数按理说需要绕过空格,但在这里没起作用。

会员登录处,就不跑了,也是能直接宽字节绕过,构建万能密码会提示“系统用户组不能从前台登录”,那说明后台可以直接用万能密码登录`b%df' or 1=1#

危险函数方式审计

在这里其实是搜索代码中的sql语句拼接,严格意义上不能叫危险函数,不过管他呢。
VSCode正则搜索:(update|select|insert|delete|).*?where.*=|INSERT INTO .*?

ok,直接打开ad_js.php文件看一下,$ad_id直接拼接在sql语句里,不带引号,数字型注入,绕全局过滤的单引号过滤都免了,按照前面所知晓的路由方式,直接GET请求访问:
手注延时验证一下:

总结

这是写给自己看的一篇文章,代码审计的学习一直拖拖拖,到现在终于打算捡起来,找了个审起来特别简单的CMS,主要还是找一找感觉,尽量详细,为之后的代码审计学习打个好头,做什么事都要找方向,学习、工作、哪怕是破案,找对找好方向才能事半功倍。
其实还是得把环境弄起来,什么断点然后debug一步一步的看,其他的洞估摸着要这么搞,不然显得不专业不是。

2025年元旦发出,也是希望能开个好年,后面能多发一发博文,卷起来。