0x01 框架结构
![图片[1]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092530.png)
![图片[2]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092535.png)
采用thinkphp5作为框架,版本为5.0.2,默认开启debug模式,数据库默认使用PDO连接
打了补丁,修复了RCE通用漏洞
![图片[3]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092608.png)
如图,增加了白名单,不能任意调用其他方法进行利用
0x02 Admin.php
任意修改管理员用户名及密码
漏洞点:
admin/controller/Admin.php
![图片[4]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092633.png)
_initialize()方法:在任何方法执行之前,都要执行此方法,包括_construct构造函数。
跟进一下父类的_initialize()方法
![图片[5]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092648.png)
方法为空,无语住了
所以该方法相当于只获取了Session而没有进行判断,可以未授权调用管理员方法
接下来跟进一下doUpdate方法
![图片[6]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092708-1024x520.png)
可以看到$user_id
和$data['username']
都是通过用户输入获取而没有使用Session,字段都可控,并且存在sql注入
POC:
![图片[7]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092724-1024x374.png)
SQL注入
还是doUpdate方法
![图片[8]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092736-1024x520.png)
重点看这一条:
$is_have = Db::name('admin')->where("id != $user_id AND username = '".$data['username']."'")->value('id');
该sql语句直接将字符串进行拼接而没有使用PDO绑定,并且$user_id
也没有用引号包裹
看下input方法
![图片[9]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092748-1024x749.png)
作用是从某个指定的来源中获取数据,但默认过滤器为空
![图片[10]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092805.png)
回到之前,$user_id
和$data['username']
获取数据时都没有使用过滤器,所以两个字段都是注入点
POC:
懒得手注了,直接sqlmap一把梭
![图片[11]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092818-1024x182.png)
![图片[12]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092824-1024x138.png)
0x03 Index.php 用户留言处存储型XSS
漏洞点:
api/Index.php
![图片[13]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092839.png)
可以看到$data
没有进行过滤,也没有限制列名,但下面会将一些特定字段进行覆盖
![图片[14]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092854.png)
可控的有id
、username
、telephone
、acreage
字段,但真正可利用的只有username
和acreage
POC:
![图片[15]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092909.png)
![图片[16]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092921-1024x454.png)
0x04 Controller.php
任意增删改查数据表内容
漏洞点:
admin/controller/Admin.php
admin/traits/controller/Controller.php
![图片[17]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092941.png)
根据上文已经了解到Admin.php未进行鉴权,并且引入了一个公共控制器Controller.php
,我们来跟进一下
先看下index方法
![图片[18]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd092956-1024x394.png)
首先用$controller = $this->request->controller()
获取当前请求的控制器名称,然后通过$m = model($controller)
返回模型对象。后续的数据库操作是以模型对象来进行的,而数据库的表名默认是模型名,所以这两行代码可以理解为由哪个控制器调用就操作与哪个控制器同名的表。
跟进下search方法
![图片[19]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093009.png)
作用相当于将$param
里的数组添加到where['map']
;所以get请求不要添加参数,让$param
置空,返回全部数据
![图片[20]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093023-1024x357.png)
接下来看edit方法
![图片[21]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093034.png)
同样的没有任何限制,跟进下isAjax方法
![图片[22]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093049.png)
可以看到只要var_ajax的伪装变量在参数中存在,就返回true
var_ajax的默认伪装名为_ajax
![图片[23]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093100.png)
所以只要在POST请求中添加参数_ajax=1
就能进入判断
继续
![图片[24]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093115.png)
allowField用于检验请求的列名是否存在
![图片[25]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093130.png)
如果不是Ajax请求,则将id作为筛选条件,返回查询数据
配合上文的index方法获取的id,即可进行修改和查询
POC:
查询:
![图片[26]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093141.png)
修改:
![图片[27]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093154-1024x490.png)
增加和删除的代码和上面的几乎一样,所以就不分析了
增加:
![图片[28]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093202-1024x410.png)
删除:
![图片[29]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093209-1024x353.png)
任意文件上传
![图片[30]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093223.png)
可以看到什么过滤都没,还贴心的返回路径给你
POC:
![图片[31]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093230-1024x378.png)
![图片[32]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093238-1024x565.png)
0x05 一些XSS
上文已知只要控制器没做好鉴权,就可以调用Controller.php里的方法;我们可以利用这点,添加带有XSS的文本到数据库里
首先看下Base控制器
![图片[33]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093250.png)
代码很简单,但也能做到基本的鉴权
接下来看Page.php
控制器
![图片[34]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093304.png)
把父类继承的鉴权方法重写置空,不知道作者为什么要这样写,跟故意留个后门一样
其他控制器如Product.php
、Service.php
、Xcxaccount.php
都像Page.php
一样无效鉴权,这里只挑两个进行演示
![图片[35]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093350.png)
![图片[36]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093405.png)
![图片[37]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093444.png)
![图片[38]-某后台管理系统的审计-NGC660 安全实验室](http://ngc660.cn/wp-content/uploads/2022/09/d2b5ca33bd093524.png)
结语
这个cms审起来比较轻松,漏洞都比较简单且典型,属于有手就行系列。
第一次写审计类的文章,没办法做到详略得当,还请各位师傅多多包涵。
本文作者:John
本文转载于先知社区,如有侵权请联系删除
昶之琴![资深玩家 徽章-资深玩家-NGC660 安全实验室](http://ngc660.cn/wp-content/themes/zibll/img/thumbnail-null.svg)
2年前0
我以为只要提交就行了好想告诉你![备受喜爱 徽章-备受喜爱-NGC660 安全实验室](http://ngc660.cn/wp-content/themes/zibll/img/thumbnail-null.svg)
2年前0
花巨资看一下