DVWA SQL Injection 过关秘籍.
LOW
1if( isset( $_REQUEST[ 'Submit' ] ) ) {
2 // Get input
3 $id = $_REQUEST[ 'id' ];
4
5 // Check database
6 $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
7 // 并没有做什么注入防护
8 // 尝试构造:
9 // select first_name, last_name from from users where user_id = '1' and 1=1;
10 // select first_name, last_name from from users where user_id = '1' and 1=2;
11 // select first_name, last_name from from users where user_id = '1' or 1=1;
12
13 $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
14
15 // Get results
16 $num = mysql_numrows( $result );
17 $i = 0;
18 while( $i < $num ) {
19 // Get values
20 $first = mysql_result( $result, $i, "first_name" );
21 $last = mysql_result( $result, $i, "last_name" );
22
23 // Feedback for end user
24 echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
25
26 // Increase loop count
27 $i++;
28 }
29
30 mysql_close();
31}
Medium
1if( isset( $_POST[ 'Submit' ] ) ) {
2 // Get input
3
4 // 换成了Post 这也太普通了
5 // 使用一些网络请求工具照样改,比如BurpSuite,PostMan,curl.
6 $id = $_POST[ 'id' ];
7 $id = mysql_real_escape_string( $id );
8 // mysql_real_escape_string 可以对以下字符进行转义
9 // \x00, \n, \r, \, ', " 和 \x1a.
10 // 值得注意的是 mysql_real_escape_string 函数所在的MYSQL扩展在
11 // PHP 5.5.0 起已废弃,并在自 PHP 7.0.0 开始被移除。
12
13 // Check database
14 $query = "SELECT first_name, last_name FROM users WHERE user_id = $id;";
15 // 尝试构造:
16 // SELECT first_name, last_name FROM users WHERE user_id = 1 or 1=1;
17
18 $result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
19
20 // Get results
21 $num = mysql_numrows( $result );
22 $i = 0;
23 while( $i < $num ) {
24 // Display values
25 $first = mysql_result( $result, $i, "first_name" );
26 $last = mysql_result( $result, $i, "last_name" );
27
28 // Feedback for end user
29 echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
30
31 // Increase loop count
32 $i++;
33 }
34
35 //mysql_close();
36}
High
1if( isset( $_SESSION [ 'id' ] ) ) {
2 // Get input
3 $id = $_SESSION[ 'id' ];
4
5 // Check database
6 // 看起来做了返回条目限制
7 $query = "SELECT first_name, last_name FROM users WHERE user_id = '$id' LIMIT 1;";
8 // 没什么套路
9 // SELECT first_name, last_name FROM users WHERE user_id = '1' or 1=1 # ' LIMIT 1;
10
11 $result = mysql_query( $query ) or die( '<pre>Something went wrong.</pre>' );
12
13 // Get results
14 $num = mysql_numrows( $result );
15 $i = 0;
16 while( $i < $num ) {
17 // Get values
18 $first = mysql_result( $result, $i, "first_name" );
19 $last = mysql_result( $result, $i, "last_name" );
20
21 // Feedback for end user
22 echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
23
24 // Increase loop count
25 $i++;
26 }
27
28 mysql_close();
29}
impossible
1if( isset( $_GET[ 'Submit' ] ) ) {
2 // Check Anti-CSRF token
3 checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );
4
5 // Get input
6 $id = $_GET[ 'id' ];
7
8 // Was a number entered?
9 if(is_numeric( $id )) {
10 // Check the database
11 // 这是!PDO!
12 // PDO 是一种PHP中比较先进的面向对象形式的数据库访问技术
13 // 不过即使是面向对象它还是事务脚本形式的。
14 // 提供了防SQL注入的功能。
15 $data = $db->prepare( 'SELECT first_name, last_name FROM users WHERE user_id = (:id) LIMIT 1;' );
16 // 无法注入
17
18 $data->bindParam( ':id', $id, PDO::PARAM_INT );
19 $data->execute();
20 $row = $data->fetch();
21
22 // Make sure only 1 result is returned
23 if( $data->rowCount() == 1 ) {
24 // Get values
25 $first = $row[ 'first_name' ];
26 $last = $row[ 'last_name' ];
27
28 // Feedback for end user
29 echo "<pre>ID: {$id}<br />First name: {$first}<br />Surname: {$last}</pre>";
30 }
31 }
32}
33
34// Generate Anti-CSRF tsoken
35generateSessionToken();
Extension
二次注入:
网站有管理员admin.
一位恶意用户注册了admin'#用户.
恶意用户更新了自己的密码.
更新SQL:
update from users set password = ‘$password’ where username = ‘$username’ and password ‘$password’
替换为恶意用户写入的数据:
update from users set password = #{password} where username = ‘admin’#’ and password = ‘$password’
注意# 后面的语句被注释掉了, 所以真正被执行的只有.
update from users set password = #{password} where username = ‘admin’
恶意用户可以无视管理员admin的密码验证,直接修改密码。