四、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安全方面的漏洞。

Logo

火山引擎开发者社区是火山引擎打造的AI技术生态平台,聚焦Agent与大模型开发,提供豆包系列模型(图像/视频/视觉)、智能分析与会话工具,并配套评测集、动手实验室及行业案例库。社区通过技术沙龙、挑战赛等活动促进开发者成长,新用户可领50万Tokens权益,助力构建智能应用。

更多推荐