1.SQLi
代码分析
session-input.php:
<?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' ] .= "
echo $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 );
?>
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);
}
?>
一图胜千言:
漏洞利用
查询页面URL: http://127.0.0.1/DVWA-master/vulnerabilities/sqli/session-input.php
回显页面URL: http://127.0.0.1/DVWA-master/security.php
注意查询页面和回显页面不同,所以需要使用second-order参数进行二阶注入。
将POST请求的数据包保存至/home/e.txt,使用sqlmap进行注入如下图:
2. SQL Blind Injection
代码分析
cookie-input.php:
<?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' ] = 'Blind SQL Injection Cookie Input' . $page[ 'title_separator' ].$page[ 'title' ];
if( isset( $_POST[ 'id' ] ) ) {
setcookie( 'id', $_POST[ 'id' ]);
$page[ 'body' ] .= "Cookie ID set!<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 );
?>
high.php:
<?php
if( isset( $_COOKIE[ 'id' ] ) ) {
// Get input
$id = $_COOKIE[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
$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 {
// Might sleep a random amount
if( rand( 0, 5 ) == 3 ) {
sleep( rand( 2, 4 ) );
}
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
$html .= '<pre>User ID is MISSING from the database.</pre>';
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
setcookie()定义了 Cookie,会和剩下的 HTTP 头一起发送给客户端。 和其他 HTTP 头一样,必须在脚本产生任意输出之前发送 Cookie(由于协议的限制)。 请在产生任何输出之前(包括 <html> 和 <head> 或者空格)调用本函数。
sql blind的查询页面与回显页面URL相同,因此直接使用burpsuite抓取时序图中最后一次GET请求的数据包保存为a.txt,最后使用Sqlmap进行注入即可,如下图:
部分Sqlmap参数介绍:
1.--second-order(二阶sql注入)
有些时候注入点输入的数据看返回结果的时候并不是当前的页面,而是另外的一个页面,这时候就需要你指定到哪个页面获取响应判断真假。–second-order后面跟一个判断页面的URL地址。
2.-r
sqlmap可以从一个文本文件中获取HTTP请求,这样就可以跳过设置一些其他参数(比如cookie,POST数据,等等)。当请求是HTTPS的时候你需要配合这个--force-ssl参数来使用,或者你可以在Host头后面加上:443
3.–batch
用此参数,不需要用户输入,将会使用sqlmap提示的默认值一直运行下去
4--level
共有五个等级,默认为1,最大为5,sqlmap使用的payload可以在xml/payloads.xml中看到,你也可以根据相应的格式添加自己的payload。
这个参数不仅影响使用哪些payload同时也会影响测试的注入点,GET和POST的数据都会测试,HTTP Cookie在level为2的时候就会测试,HTTP User-Agent/Referer头在level为3的时候就会测试。
总之在你不确定哪个payload或者参数为注入点的时候,为了保证全面性,建议使用高的level值。
5.--risk
共有四个风险等级,默认是1会测试大部分的测试语句,2会增加基于事件的测试语句,3会增加OR语句的SQL注入测试。
在有些时候,例如在UPDATE的语句中,注入一个OR的测试语句,可能导致更新的整个表,可能造成很大的风险。
测试的语句同样可以在xml/payloads.xml中找到,你也可以自行添加payload。
6.-p
sqlmap默认测试所有的GET和POST参数,当--level的值大于等于2的时候也会测试HTTP Cookie头的值,当大于等于3的时候也会测试User-Agent和HTTP Referer头的值。但是你可以手动用-p参数设置想要测试的参数 。例如: -p "id,user-anget"
当你使用--level的值很大但是有个别参数不想测试的时候可以使用--skip参数。例如:--skip="user-angent.referer"
在有些时候web服务器使用了URL重写,导致无法直接使用sqlmap测试参数,可以在想测试的参数后面加*。