复活Navex:使用图查询进行代码分析

访客 423 0
本文来源:斗象智能安全平台

从了解到修复 

dvwa/vulnerabilities/brute/source/low.php

?php

if( isset( $_GET[ 'Login' ] ) ) {
    // Get username
    $user = $_GET[ 'username' ];

    // Get password
    $pass = $_GET[ 'password' ];
    $pass = md5( $pass );

    // Check the database
    $query  = "SELECT * FROM `users` WHERE user = '$user' AND password = '$pass';";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( 'pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '/pre>' );

    if( $result 
        $avatar = $row["avatar"];

        // Login successful
        $html .= "p>Welcome to the password protected area {$user}/p>";
        $html .= "img src=\"{$avatar}\" />";
    }
    else {
        // Login failed
        $html .= "pre>br />Username and/or password incorrect./pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

虽说存在一些误报, 但是基本实现了漏洞分析查询的功能

漏报原因分析

  1. dvwa/vulnerabilities/sqli/source/medium.php
?php

?php

if( isset( $_POST[ 'Submit' ] ) ) {
    // Get input
    $id = $_POST[ 'id' ];

    $id = mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id);

    $query  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query) or die( 'pre>' . mysqli_error($GLOBALS["___mysqli_ston"]) . '/pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Display values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        $html .= "pre>ID: {$id}br />First name: {$first}br />Surname: {$last}/pre>";
    }

}

// This is used later on in the index.php page
// Setting it here so we can close the database connection in here like in the rest of the source scripts
$query  = "SELECT COUNT(*) FROM users;";
$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( 'pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '/pre>' );
$number_of_rows = mysqli_fetch_row( $result )[0];

mysqli_close($GLOBALS["___mysqli_ston"]);
?>

Medium级别的代码利用mysql_real_escape_string函数对以下特殊符号进行转义

但是此处为数字型注入不需要单引号, 可以绕过

$query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";

所以这里还有优化空间, 比如多一步判断注入类型, 然后忽略无效的过滤

  1. dvwa/vulnerabilities/sqli/source/high.php
?php

if( isset( $_SESSION [ 'id' ] ) ) {
    // Get input
    $id = $_SESSION[ 'id' ];

    // Check database
    $query  = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"], $query ) or die( 'pre>Something went wrong./pre>' );

    // Get results
    while( $row = mysqli_fetch_assoc( $result ) ) {
        // Get values
        $first = $row["first_name"];
        $last  = $row["last_name"];

        // Feedback for end user
        $html .= "pre>ID: {$id}br />First name: {$first}br />Surname: {$last}/pre>";
    }

    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);        
}

?>

这里使用的是$_SESSION [ 'id' ]注入, 通过访问

dvwa/vulnerabilities/sqli/session-input.php

其实该点可控 $_SESSION[ 'id' ] = $_POST[ 'id' ];

?php

define( 'DVWA_WEB_PAGE_TO_ROOT', '../../' );
require_once DVWA_WEB_PAGE_TO_ROOT . 'dvwa/includes/dvwaPage.inc.php';

dvwaPageStartup( array( 'authenticated', 'phpids' ) );

$page = dvwaPageNewGrab();
$page[ 'title' ] = 'SQL Injection Session Input' . $page[ 'title_separator' ].$page[ 'title' ];

if( isset( $_POST[ 'id' ] ) ) {
    $_SESSION[ 'id' ] =  $_POST[ 'id' ];
    //$page[ 'body' ] .= "Session ID set!br />br />br />";
    $page[ 'body' ] .= "Session ID: {$_SESSION[ 'id' ]}br />br />br />";
    $page[ 'body' ] .= "script>window.opener.location.reload(true);/script>";
}

$page[ 'body' ] .= "
form action=\"#\" method=\"POST\">
    input type=\"text\" size=\"15\" name=\"id\">
    input type=\"submit\" name=\"Submit\" value=\"Submit\">
/form>
hr />
br />

button onclick=\"self.close();\">Close/button>";

dvwaSourceHtmlEcho( $page );

?>

但是从单文件来看, 该输入点不可控, 所以产生了漏报, 如果优化需要解析 include等节点进行跨文件判断

  1. dvwa/vulnerabilities/sqli_blind/source/medium.php
?php

if( isset( $_POST[ 'Submit' ]  ) ) {
    // Get input
    $id = $_POST[ 'id' ];
    $id = ((isset($GLOBALS["___mysqli_ston"]) 

    // Check database
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // Get results
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors
    if( $num > 0 ) {
        // Feedback for end user
        $html .= 'pre>User ID exists in the database./pre>';
    }
    else {
        // Feedback for end user
        $html .= 'pre>User ID is MISSING from the database./pre>';
    }

    //mysql_close();
}

?>

这里也是数字型注入的问题, 不再赘述

总结

本文重点在于静态分析部分的修复, 动态分析部分其实相对简单一些, 也就是剪枝的过程, 后续也可以实现.

我的想法是:

  1. 静态分析使用JoernCodeql等工具来实现, 然后生成导航图
  2. exp使用固定poc+ 动态变异 fuzzing 的思想
  3. 动态爬虫使用论文中所使用的crawler4j 或者最近比较火的crawlergo
  4. 然后后端使用Baidu Raspprvd来实现监控是否执行成功

PS.也可以实现一种类似动态跃点的标记, 比如挖掘反序列化的利用链, 具有某些特性的的节点,

比如 $a=$this->$ppp; $a->arr($b);

那么这个点只是L1级别的信息, 但是配合unserialize, 配合其他的类的__call,

将这些L1的标记组合起来,就能组合成存在风险的L2级别的安全风险.

最近对自动化审计AEG这方面比较感兴趣, 欢迎讨论.

参考

https://github.com/UUUUnotfound/Navex_fixed

标签: 代码分析 Navex 图查询

发表评论 (已有0条评论)

还木有评论哦,快来抢沙发吧~