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); } ?>
虽说存在一些误报, 但是基本实现了漏洞分析查询的功能
漏报原因分析
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;";
所以这里还有优化空间, 比如多一步判断注入类型
, 然后忽略无效的过滤
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
等节点进行跨文件判断
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(); } ?>
这里也是数字型注入的问题, 不再赘述
总结
本文重点在于静态分析部分的修复, 动态分析部分其实相对简单一些, 也就是剪枝的过程, 后续也可以实现.
我的想法是:
- 静态分析使用
Joern
, Codeql
等工具来实现, 然后生成导航图 - exp使用固定
poc
+ 动态变异 fuzzing 的思想 - 动态爬虫使用论文中所使用的
crawler4j
或者最近比较火的crawlergo
- 然后后端使用
Baidu Rasp
, prvd
来实现监控是否执行成功
PS.也可以实现一种类似动态跃点的标记, 比如挖掘反序列化的利用链, 具有某些特性的的节点,
比如 $a=$this->$ppp; $a->arr($b);
那么这个点只是L1级别
的信息, 但是配合unserialize
, 配合其他的类的__call
,
将这些L1
的标记组合起来,就能组合成存在风险的L2级别
的安全风险.
最近对自动化审计
, AEG
这方面比较感兴趣, 欢迎讨论.
参考
https://github.com/UUUUnotfound/Navex_fixed