sql注入1-4
本文档是基于pikachu 靶场全关卡讲解(含代码审计)编写的 sql 注入学习笔记
因为队友太拉胯,而不得不努力,舍弃暑假快乐时光去学习 web 的密码手
还要搞逆向,这下真成全能手了 😅
数字型注入
- 观察网页,发现是下拉列表选择数字,进行查询

- Burp Suite抓包发现post提交数据位置,存在注入点

- 将数据包发送到Repeater 模块,进行下一步处理
接下来的事情就是瞎猜
随便输入一个数字进行查询,返回结果如下:
hello,vince
your email is: vince@pikachu.com
返回了用户名 vince和邮箱vince@pikachu.com,说明有两个字段
对于数字型,后台的代码应该是以下的形式:
SELECT 字段1,字段2 from 表名 where id = $id;
现在尝试构建 payload,原理是拼接
将 id 的值设置为1 or 1=1,后台运行的代码就会变成:
SELECT 字段1,字段2 from 表名 where id = 1 or 1=1;
注意id = 1 or 1=1,用or将条件分为两部分,后面的1=1使得这一整个判断为真(所以id = 1 or true也行)
相当于后台代码变成了:
SELECT 字段1,字段2 from 表名 where true;
where后面的过滤条件永远为真,输出表内所有数据
介绍一个小技巧,在查看响应结果时,返回的代码实在太丑陋了
我们点一下Render(汉化后是页面渲染)
这样就能很直观的看到结果
贴一下原代码,位置在pikachu-master\vul\sqli\sqli_id.php24 行:
if(isset($_POST['submit']) && $_POST['id']!=null){
//这里没有做任何处理,直接拼到select里面去了,形成Sql注入
$id=$_POST['id'];
$query="select username,email from member where id=$id";
$result=execute($link, $query);
//这里如果用==1,会严格一点
if(mysqli_num_rows($result)>=1){
while($data=mysqli_fetch_assoc($result)){
$username=$data['username'];
$email=$data['email'];
$html.="<p class='notice'>hello,{$username} <br />your email is: {$email}</p>";
}
}else{
$html.="<p class='notice'>您输入的user id不存在,请重新输入!</p>";
}
}
字符型注入
- 观察网页,发现是输入框输入字符串,进行查询

- 抓包发现get提交数据位置,存在注入点

- 将数据包发送到Repeater,进行下一步处理
输入kobe进行查询,返回结果如下:
your uid:3
your email is: kobe@pikachu.com
返回了uid:3和邮箱kobe@pikachu.com,说明有两个字段
对于字符型,后台的代码大概是以下的形式:
SELECT 字段1,字段2 from 表名 where name = '$name';
注意我们输入的变量$name被引号包裹,后台代码会将其视为字符串
可能是单引号或双引号,需要进行测试
- 输入双引号
"进行查询,返回结果
您输入的username不存在,请重新输入!
我们输入的双引号"处于中间,与前后引号不同,所以双引号"被视为字符串进行查询
说明不是双引号包裹 - 输入单引号
'进行查询,返回结果
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''''' at line 1
意思是出现语法错误,我们输入的单引号使它构成了'''三个单引号,前两个单引号配对,第三个单引号没有配对
说明是单引号包裹'$name'
现在我们确认了,后台代码应该是以下的形式:
SELECT 字段1,字段2 from 表名 where name = '$name';
现在尝试构建 payload,原理是闭合
输入kobe' or 1=1 #或者kobe' or 1=1 -- (注意–后面有一个空格),后台代码会变成:
SELECT 字段1,字段2 from 表名 where name = 'kobe' or 1=1 -- '
SELECT 字段1,字段2 from 表名 where name = 'kobe' or 1=1 #'
- 前面的
kobe'中的单引号被闭合(有没有kobe无所谓,主要是与第一个引号配对闭合) - 中间的
or 1=1构造过滤条件真 - 后面的
-- '(注意空格)或#将以后的语句注释掉(重点是注释掉原来第二个引号)
相当于后台代码变成了:
SELECT 字段1,字段2 from 表名 where true;
和前面的数字型注入一样,where后面的过滤条件永远为真,输出表内所有数据

贴一下原代码,位置在pikachu-master\vul\sqli\sqli_str.php24 行:
if(isset($_GET['submit']) && $_GET['name']!=null){
//这里没有做任何处理,直接拼到select里面去了
$name=$_GET['name'];
//这里的变量是字符型,需要考虑闭合
$query="select id,email from member where username='$name'";
$result=execute($link, $query);
if(mysqli_num_rows($result)>=1){
while($data=mysqli_fetch_assoc($result)){
$id=$data['id'];
$email=$data['email'];
$html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
}
}else{
$html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";
}
}
搜索型注入
提示输入用户名的一部分搜索的试试看 数据库中对表里的内容进行匹配性查询时,使用的语句如下:
select * from 表名 where 字段 like '%关键词%';
我们输入的关键词被百分号和引号包裹,后台代码会将其视为字符串,进行模糊查询,返回匹配的结果。
我们尝试构建 payload,原理和字符型注入一样,只是多了一个百分号
输入%' or 1=1 #或者%' or 1=1 -- (注意–后面有一个空格),后台代码会变成:
select * from 表名 where 字段 like '%%' or 1=1 #%';
select * from 表名 where 字段 like '%%' or 1=1 -- %';
- 前面的
%'中的单引号被闭合(主要是与第一个引号和百分号配对闭合) - 中间的
or 1=1构造过滤条件真 - 后面的
-- '(注意空格)或#将以后的语句注释掉(重点是注释掉原来第二个引号和百分号)
相当于后台代码变成了:
select * from 表名 where 字段 过滤条件 true;
和前面的数字型注入一样,后面的过滤条件永远为真,输出表内所有数据

原码位置在pikachu-master\vul\sqli\sqli_search.php24 行
xx 型注入(总结)
总而言之,就是对 SQL 中的各种类型的输入进行闭合测试,构造合法 SOL 语句,欺骗后台执行
- 配对闭合
- 构造过滤条件真
- 注释掉原来第二个包裹符号
对于这道题,后台语句是
select id,email from member where username=('$name');
慢慢试出来引用符吧,或者过几天学一下 sqlmap 能不能搞 定界符或引用符主要包括以下几种:
- 单引号’:用于定义字符串字面量,在 SQL 语句中常用于包裹字符串值。
- 双引号“:在某些编程语言中用于定义字符串字面量,或者在 SQL 中(特别是在某些数据库系统如 PostgreSQL 中)用于标识保留字或标识符。
- 反引号`:(在键盘的 tab 键上方)在 SQL 中用于标识 MySQL、MariaDB 和其他一些数据库系统中的标识符。
- 小括号():用于分组表达式或函数参数,以及在 SQL 中用于定义子查询。
- 大括号{}:在某些编程语言中用于代码块,或者在 SQL 中用于标识分区名或表名(特别是在 SQL Server 中)。
- 方括号[]:在某些编程语言中用于数组索引,或者在 SQL 中用于标识 SQL Server 中的保留字或标识符。
以下是这些包裹符号的一些常见用途:
单引号和双引号在SQL中用于包裹字符串值:
SELECT * FROM users WHERE name = 'John Doe';
SELECT * FROM users WHERE name = "John Doe";
反引号用于MySQL中的标识符:
SELECT `column` FROM `table`;
小括号用于分组或函数参数:
SELECT (column1 + column2) FROM table;
SELECT MAX(column) FROM table;
大括号用于标识SQL Server中的对象名称:
SELECT * FROM {table_name};
方括号用于SQL Server中的保留字或标识符:
SELECT [column] FROM [table];