Web安全篇——SQL注入漏洞(下)
摘要:本文通过Pikachu靶场实验详细讲解SQL注入技术,重点分析了请求头注入(UA和Cookie注入)、布尔盲注(基于布尔和时间的盲注)以及暴力破解表名等方法。实验演示了如何利用报错回显、ASCII码判断和时间延迟等技术获取数据库信息,并介绍了防范措施,强调参数化查询(如PDO预处理)、输入验证和权限控制的重要性。文中指出SQL注入的核心问题是用户输入直接参与SQL拼接,开发者需严格防范才能确
四、pikachu靶场SQL注入漏洞实践
8、请求头注入
1 or updatexml(1,concat(0x7e,version()),0)

我们拿delete注入的题目做示范,直接将我们预设好的payload注入请求中,就可以得到以下反馈:

通过报错来回显出我们需要的数据库版本——MYSQL8.0.12
当然请求头中的注入点非常之多,只要我们输入的变量会嵌入到SQL语句中,我们就可以实现SQL注入攻击,下面展示一下User-Agent(UA注入)以及cookie注入:
在注入之前,我们如何在不借助工具的情况下找到注入点呢?

思路当然和之前一样,就是尝试修改一些参数,重放请求,观察它的报错类型。如上图,我们通过修改UA,发现返回的报错是SQL语法报错,这不就说明UA后的输入参数会拼接进入SQL语句当中。我们直接把预设的payload注入该点。

响应得到数据库版本的报错回显。
同理,我们来对Cookie进行尝试:

确定注入点,注入payload:

结果不出意外,得到了我们需要的数据。
9、布尔盲注
1)base on boolian
首先很多人疑问,为什么会把这种注入类型称为“盲注”,其实就是因为盲注不同于上述任何一种类型,我们得不到网站后台直接回显的任何直接信息,包括我们之前对此情况进行的报错型注入也无能为力,因此我们只能一步步通过真假判断,揭开数据上的面纱,才所谓“盲注”。
为了直观看出其与其它注入的区别,下面的图片就可以说明问题:

这里我们运用字符型注入的手段,发现得不到任何有效信息。

我们把or改成and,迫使语句为真,确定该点确为注入点(成功嵌入到SQL语句)。

我们将 1=1 改为 1=2 使语句为假,发现有回显,但是没有任何信息。
因此,我们要摒弃以往的SQL注入思路,在我们只能判断该语句真假性的情况下,如何能得到确切的信息呢?
其实可以考虑改变一下payload,之前的payload都是索取信息,这时转换成判断信息就好。但问题是我们如何在不知道对方任何信息的情况下,去通过构造判断语句来实现盲注呢?这里就牵扯到一些经验和运气的问题了,对数据库各版本了解多的人,一些默认的表名、列名都烂熟于心,这样他们通过对这些名的ASCII码判断真假,一个字符一个字符地得到信息。关于这里为什么会用到ASCII码,当然是因为每个字符ASCII码的唯一性,而SQL语句中恰好有返回字符ASCII码对应的函数:
ASCII(character_expression)
我们仿照报错注入的语句,把函数换成ascii()函数,构成条件判断语句进行嵌入:
kobe ' and ascii(substr(datebase(),1,1))>113
这样我们新的payload就构造好了,该payload表达的就是datebase的第一个字符对应的ASCII码是否大于113,如果返回了kobe的邮箱信息,说明该语句为真,也就是datebase的第一个字符对应的ASCII码大于113,反之,小于等于113。


通过这样的方式,我们一个个字符收集数据库的信息,因为效率较低,我们需要提高自己payload的精度,尽可能地提高效率,我们将之前提高精度用的select语句嵌套:
(select table_name from information_schema.tables where table_schema=datebase() limit 0,1)
kobe ' and ascii(substr((select table_name from information_schema.tables where table_schema=datebase() limit 0,1),1,1))><=112#
这样就可以最大限度地查找我们需要的信息,最后我对基于boolian的盲注进行总结:
基于boolian的盲注有几个主要表现的症状:
A、没有报错信息(没有回显);
B、不管是正确的输入,还是错误的输入,都只有两种情况(0 or 1);
C、在正确的输入下,输入and 1=1 and 1=2 发现可以进行判断。
2)base on time
基于time的布尔盲注和基于boolian的布尔盲注有着相同的思路,但是基于时间的盲注是在只有一种回显情况的基础上判断真假的。这里很多人也会产生疑问,只有一种回显怎么判断真假?正像这种盲注的名字,通过发送请求后得到响应所需的时间来判断真和假,如果返回时间变慢说明结果为真。而这里我们不再使用先前的函数类型,只需要通过if条件判断,将条件为真的回显方式设置为一段时间以后就可以了。
kobe' and if((substr(datebase(),1,1))='a' ,sleep(5),null)#

输入我们的payload,会立即获得回显。

更改条件参数后,等待5秒后返回,说明我们尝试的数据匹配结果为真。这就是基于时间的盲注,有着和一般盲注相同的思路,只需要稍微改变函数即可。
10、暴力破解表名
这个类型我们将结合之前所提到的暴力破解去完成,原理很简单,其实就是通过子查询(exists)来完成该表名的查询,将payload针对的爆破对象注释在from之后,具体的代码如下:
kobe' and exists(select * from aa)#
然后我们直接发送请求可以得到如下的一个响应:

查询失败,说明没有一个表名是aa,但是我们可以通过burpsuite的爆破模块来将aa表名和我们字典中的所有表名进行替换,不断发送请求去匹配,最后会爆破出真实的表名:

为了进一步确定该users是否确为表名,我们可以再次提交一下查询:
kobe' and exists(select id from users)#
这样就可以验证我们的爆破结果了。
五、SQL注入漏洞的防范
防范 SQL 注入的核心是杜绝用户输入直接参与 SQL 语句的拼接,参数化查询是最有效的手段,配合输入验证、权限控制等措施可大幅降低风险。任何时候都不要依赖 “用户输入是安全的” 这一假设,必须从代码层面强制防护。
这里分享一下最推荐的PHP防范措施-PDO预处理(预处理+参数化)
$username=$_GET['username'];
$password=$_GET['password'];
try{
$pdo=new PDO('mysql:host=localhost;dbname=ant','root','root');
$sql="select * from admin where username=? and password=?";
$stmt=$pdo->prepare($sql);//先不传参数,先预处理
// var_dump($atmt);
$stmt->execute(array($username,$password));
//这个时候把参数传进去,以索引数组的方式传进去,而不是拼接,就成功防止了注入
}catch (PDOException $e){
echo $e->getMessage();
}
?>
SQL注入作为后端漏洞,问题自然出在后端,只有开发者认真对待,不存在侥幸心理,才可以真正做好网站的后端配置,让漏洞越来越少,让用户信息越来越安全。
Web安全的第二篇文章——关于SQL注入的介绍就要画上句号了,后续的web安全篇还会继续分享更多web安全方面的漏洞。
火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。
更多推荐
所有评论(0)