Payload: /product/nextProduct?path=http://192.168.0.12:8080/admin/delete?username=carlos


利用开放重定向漏洞绕过过滤器的 SSRF 攻击
—— PortSwigger“SSRF with filter bypass via open redirection vulnerability”完整通关指南
🎯 靶场速览
目标:该实验室的库存检查功能会从内部系统获取数据。需要利用 SSRF 漏洞访问位于 http://192.168.0.12:8080/admin 的管理员界面,并删除用户 carlos。
难点:库存检查功能被限制为只能访问本地应用程序(即 stockApi 参数必须以 / 开头的相对路径),无法直接请求内网其他主机。
核心思路:利用网站本身存在的开放重定向漏洞作为跳板。让 SSRF 先请求本地的重定向接口,通过主机限制检查,再利用该接口的 Location 跳转到内网管理地址。
🚀 分步攻击链
第1步:确认 SSRF 的主机限制
访问任意产品页面,点击 “Check stock”,用 Burp Suite 拦截 POST 请求。
观察 stockApi 参数的值——它是一个相对路径(例如 /product/stock/check?productId=1&storeId=2),而不是完整 URL。
在 Burp Repeater 中尝试直接修改 stockApi 为内网管理地址:
stockApi=http://192.168.0.12:8080/admin
发送后服务器返回拦截信息,提示只能访问本地应用程序——证实了 SSRF 的主机过滤存在。
第2步:发现开放重定向漏洞
点击产品页面右下角的 “Next product” 按钮,拦截该请求。
请求 URL 格式为:
GET /product/nextProduct?currentProductId=1&path=/product?productId=2
其中 path 参数控制重定向目标。
将 path 参数修改为任意外部地址,例如:
/product/nextProduct?path=http://example.com
发送请求后,观察响应头中的 Location 字段,发现返回了 http://example.com。
结论:path 参数存在开放重定向漏洞,其值被直接作为 302 响应的 Location 目标,未做任何验证。
第3步:组合利用——用重定向绕过 SSRF 限制
将开放重定向和 SSRF 组合起来。
构造 stockApi 的值为本地重定向接口,并通过 path 参数指向内网管理地址:
/product/nextProduct?path=http://192.168.0.12:8080/admin
💡 可省略
currentProductId参数,不影响重定向逻辑。
攻击流程:
- 库存检查工具收到
stockApi=/product/nextProduct?path=http://192.168.0.12:8080/admin - 由于这是本地路径(以
/开头),成功通过了 SSRF 的主机限制检查 - 服务器向
/product/nextProduct发起请求 - 该接口返回
302状态码,Location: http://192.168.0.12:8080/admin - 库存检查工具的 HTTP 客户端自动跟随重定向,成功访问内网管理界面
在 Repeater 中发送该请求,返回的管理界面 HTML 内容证实绕过成功。
第4步:删除目标用户
将重定向的目标路径改为删除用户的接口。
构造最终 stockApi:
/product/nextProduct?path=http://192.168.0.12:8080/admin/delete?username=carlos
发送请求,库存检查工具跟随重定向执行删除操作,实验完成。
💡 核心原理
主机限制的实现方式
目标应用对 stockApi 做了简单的前缀检查:
if (!stockApi.startsWith("/")) {
// 拒绝非本地请求
return error("Only local application access allowed");
}
// 发起请求
URL url = new URL("http://localhost:8080" + stockApi);
只要 stockApi 以 / 开头,就放行,并在前面拼接本地域名。
为什么重定向能绕过限制?
| 阶段 | 操作 | 是否经过过滤器 | 结果 |
|---|---|---|---|
| ① | 检查 stockApi 原始值 | ✅ 过滤器生效 | /product/nextProduct 以 / 开头,放行 |
| ② | 请求 /product/nextProduct | ❌ 已进入内网请求逻辑 | 返回 Location: http://192.168.0.12:8080/admin |
| ③ | HTTP 客户端跟随重定向 | ❌ 不再重新检查 | 直接请求内网管理地址,获取内容 |
核心原因:大多数 HTTP 客户端库(如 Java HttpURLConnection、Python requests)默认自动处理重定向,但重定向后的目标 URL 不会再经过发起请求前的安全检查。这相当于用本地路径“骗过”门卫进入大楼,然后在大楼内部随意跳转到任何房间。
为什么重定向能传递完整路径?
/product/nextProduct 接口的重定向逻辑是直接拼接 path 参数的值,不校验其域名合法性。因此 path 中携带的完整 URL(含路径和参数)会被原样放入 Location 头:
HTTP/1.1 302 Found
Location: http://192.168.0.12:8080/admin/delete?username=carlos
🔧 同类技巧拓展
| 技巧 | 说明 | 适用场景 |
|---|---|---|
| 利用现有重定向接口 | 寻找 redirect、next、returnTo、path、goto 等参数 | 应用存在开放重定向漏洞时 |
| 利用外部开放重定向服务 | 使用 http://example.com/redirect?url=... 等公开服务 | 应用内无重定向漏洞时 |
| 链式重定向 | 多个重定向串联,每层通过不同过滤器 | 单层重定向被部分限制时 |
利用 @ 符号混淆 | http://expected.com@192.168.0.12/admin | 基于域名白名单的过滤 |
利用 # 符号截断 | http://192.168.0.12/admin#@expected.com | 后端解析差异绕过 |
✅ 排障自检清单
| 问题 | 原因 | 解决方案 |
|---|---|---|
直接修改 stockApi 为 http://192.168.0.12:8080/admin 被拦截 | SSRF 主机限制生效 | 这是预期行为,证明需要重定向跳板 |
修改 path 参数后返回 404 | 路径错误或参数名不对 | 确认接口为 /product/nextProduct?path=... |
| 组合 payload 返回 400 或报错 | stockApi 中带了域名 | 必须以 /product/nextProduct 开头,不能包含 http://localhost |
| 返回管理界面但删除失败 | 删除路径写错 | 确认完整路径为 /admin/delete?username=carlos |
| HTTP 客户端未跟随重定向 | 某些库默认不跟随 | 靶场默认跟随,若使用自定义工具需开启 follow_redirects=True |
| 重定向目标被二次过滤 | 后端对 Location 也做了检查 | 尝试链式重定向或多重编码 |
📌 总结
本关的核心在于组合利用两个漏洞:
- SSRF 的主机限制仅做前缀检查,允许所有本地路径
- 开放重定向漏洞允许将任意 URL 放入
Location头
通过让 SSRF 客户端先请求合法的本地重定向接口,再自动跟随重定向到达内网管理地址,成功绕过了“只能访问本地”的限制。
这条利用路径揭示了一个常见的安全设计缺陷:访问控制检查仅在请求入口执行,而忽略了对自动重定向目标的二次校验。在实际渗透测试中,寻找应用内的开放重定向接口,并将其作为 SSRF 的“跳板”,是突破主机限制最有效的手段之一。

360

被折叠的 条评论
为什么被折叠?



