KODOK:面向漏洞赏金猎人的高级JavaScript安全扫描器
引言
在现代Web应用程序中,JavaScript文件是敏感信息的宝库。API端点、认证令牌、数据库凭据和内部服务URL通常隐藏在客户端代码中。传统工具由于模式匹配有限或缺乏深度递归能力,可能会错过这些发现。
KODOK是一款基于Go的高性能扫描器,专门设计用于通过以下方式从JavaScript文件中提取最大价值:
- 使用7种不同检测方法的多层路径提取
- 具有可配置深度的递归发现,用于跟踪JS依赖关系
- 30多种具有基于熵验证的密钥模式
- SSRF保护获取,防止内部网络暴露
- 带有通配符的域范围控制,实现精确目标控制
与简单的基于正则表达式的工具不同,KODOK结合了并发处理、智能去重和全面的模式匹配,以发现其他人遗漏的隐藏资产。
为什么选择KODOK?
问题
漏洞赏金猎人和安全研究人员面临共同挑战:
- 数量:现代Web应用程序加载数十个JavaScript文件
- 混淆:路径隐藏在连接、模板文字和对象属性中
- 递归:JS文件导入其他JS文件创建深度依赖链
- 时间:手动分析无法扩展
- 误报:通用正则表达式产生噪音
解决方案
KODOK通过以下方式解决这些问题:
1
2
3
|
输入URL → 并发工作器 → 深度提取 → 密钥检测 → 结构化输出
↓ ↓ ↓
去重处理 7种模式类型 熵验证
|
安装
1
2
3
4
5
|
git clone https://github.com/rhyru9/kodok.git
cd kodok
go build -o kodok cmd/kodok/main.go
chmod +x kodok
sudo mv kodok /usr/local/bin/
|
核心功能
1. 多方法路径提取
KODOK使用7种互补的提取技术:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
// 方法1:字符串字面量
const api = '/api/v1/users';
// 方法2:模板文字
const url = `/graphql/${query}`;
// 方法3:对象属性
const config = { apiUrl: '/api/data', endpoint: '/v2/users' };
// 方法4:函数调用
fetch('/api/posts');
axios.get('https://api.example.com/data');
// 方法5:路由器配置
router.push({ pathname: '/dashboard' });
// 方法6:启发式模式
// 自动检测:/api/*, /v[0-9]+/*, /graphql/*, /oauth/* 等
// 方法7:连接字符串
const base = 'https://api.example.com';
const endpoint = base + '/users' + '?limit=10';
|
结果:提取其他人遗漏的路径,保留查询参数和片段。
2. 递归深度扫描
1
|
kodok -u https://target.com/app.js -deep -depth 3
|
行为:
1
2
3
4
5
6
7
|
深度0:app.js(输入)
↓ 发现:vendor.js, utils.js
深度1:vendor.js, utils.js
↓ 发现:api-client.js, auth.js
深度2:api-client.js, auth.js
↓ 发现:config.js
深度3:config.js
|
每个级别指数级增加覆盖范围,同时智能缓存防止重新扫描。
3. 带验证的密钥检测
30多种模式覆盖:
- 云提供商:AWS (AKIA*, ASIA*), Google (AIza*), Azure
- 支付:Stripe (sk_live_), Midtrans, Square
- 版本控制系统:GitHub (ghp_, gho_), GitLab (glpat-), NPM
- 通信:Slack, Discord, Telegram, SendGrid
- 通用:JWT, Bearer令牌, Basic Auth, 数据库URL
熵过滤:
1
2
3
4
|
// 拒绝低熵误报
if calculateEntropy(value) < 2.5 {
return false // 跳过 "password123", "test1234" 等
}
|
示例输出:
1
2
3
4
5
6
|
{
"type": "AWS Access Key ID",
"value": "AKIA****MPLE",
"context": "const key = 'AKIAIOSFODNN7EXAMPLE'",
"line": 42
}
|
4. 带通配符的域范围控制
1
2
3
4
5
6
7
8
9
10
|
# 精确匹配
kodok -f urls.txt -ad "target.com"
# 子域通配符(包括基础域)
kodok -f urls.txt -ad "*.target.com"
# 匹配:target.com, api.target.com, cdn.api.target.com
# 多个模式
kodok -f urls.txt -ad "*.target.com,*.cdn.target.com,partner.com"
|
实现:
1
2
3
4
5
6
7
|
if strings.HasPrefix(pattern, "*.") {
suffix := pattern[2:] // "example.com"
// 匹配 "example.com" 和 "sub.example.com"
if host == suffix || strings.HasSuffix(host, "."+suffix) {
return true
}
}
|
5. SSRF保护
自动阻止危险目标:
1
2
3
4
5
6
7
|
// 自动阻止
http://localhost/ // 环回地址
http://127.0.0.1/ // 环回地址
http://192.168.1.1/ // 私有网络 (RFC 1918)
http://169.254.169.254/ // AWS元数据
http://metadata.google.internal/ // GCP元数据
http://kubernetes.default.svc/ // K8s API
|
实际工作流程
工作流程1:独立发现
1
2
3
4
5
6
7
8
|
# 基本扫描
kodok -u https://target.com/app.js
# 深度扫描与域范围
kodok -u https://target.com/app.js \
-deep -depth 5 \
-ad "*.target.com" \
-workers 15
|
工作流程2:与侦察工具集成
KODOK在与URL发现工具结合时表现出色:
使用Waymore(Wayback Machine)
1
2
3
4
5
6
7
8
9
10
11
|
# 发现历史JS文件
waymore -i target.com -mode U -oU waymore_urls.txt
# 过滤JS文件
grep "\.js" waymore_urls.txt > js_files.txt
# 使用KODOK扫描
kodok -f js_files.txt \
-deep -depth 3 \
-ad "*.target.com" \
-o waymore_results
|
为什么有效:Wayback Machine捕获具有不同端点、凭据和调试代码的旧版本。
使用Katana(爬虫)
1
2
3
4
5
6
7
8
9
|
# 爬取目标并提取JS
katana -u https://target.com -d 5 -jc -jsl -o katana_urls.txt
# 扫描发现的JS文件
kodok -f katana_urls.txt \
-deep -depth 2 \
-ad "*.target.com" \
-workers 20 \
-o katana_results
|
为什么有效:Katana找到具有当前端点和活动令牌的实时JS文件。
使用GAU(获取所有URL)
1
2
3
4
5
6
7
8
|
# 从多个来源聚合URL
gau target.com | grep "\.js" | sort -u > gau_js.txt
# 全面扫描
kodok -f gau_js.txt \
-deep -depth 4 \
-ad "*.target.com,*.cdn.target.com" \
-o gau_results
|
组合管道
1
2
3
4
5
6
7
8
9
10
11
12
|
# 完整侦察管道
echo "target.com" | \
gau | grep "\.js" | \
sort -u | \
kodok -deep -depth 3 -ad "*.target.com" -o comprehensive_scan
# 或组合多个来源
cat <(gau target.com) \
<(waybackurls target.com) \
<(katana -u https://target.com -jc -silent) | \
grep "\.js" | sort -u | \
kodok -deep -depth 3 -ad "*.target.com" -workers 25 -o final_results
|
工作流程3:认证扫描
1
2
3
4
5
6
7
8
9
10
|
# 带认证头
kodok -f urls.txt \
-H "Authorization:Bearer eyJhbGc..." \
-deep -depth 3 \
-ad "*.target.com"
# 多个头
kodok -f urls.txt \
-H "Authorization:Bearer token,X-API-Key:key123" \
-ad "*.target.com"
|
工作流程4:大规模狩猎
1
2
3
4
5
6
7
8
9
10
11
12
|
# 高效处理1000+ URL
cat massive_js_list.txt | \
kodok \
-workers 30 \
-cache 50000 \
-timeout 45 \
-deep -depth 2 \
-ad "*.target.com" \
-o large_scale_results
# 监控进度
kodok -f massive_js_list.txt -v -workers 30
|
理解输出
JSON输出结构
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
|
{
"summary": {
"total_urls": 150,
"success_count": 145,
"failed_count": 5,
"total_paths": 1247,
"total_secrets": 8,
"total_time": "3m45s"
},
"results": [
{
"url": "https://target.com/app.js",
"paths": [
"/api/v1/users",
"/api/v1/posts",
"/graphql/query",
"https://internal-api.target.com/data"
],
"secrets": [
{
"type": "AWS Access Key ID",
"value": "AKIA****WXYZ",
"context": "const AWS_KEY = 'AKIAIOSFODNN7EXAMPLE'",
"line": 127
}
],
"path_count": 4,
"secret_count": 1,
"depth": 0,
"status_code": 200,
"duration": "1.2s"
}
]
}
|
TXT输出(用于管道)
1
2
3
4
5
6
|
https://target.com/api/v1/users
https://target.com/api/v1/posts
https://target.com/graphql/query
https://internal-api.target.com/data
https://target.com/oauth/token
...
|
用法:
1
2
3
4
5
6
7
8
|
# 验证发现的端点
cat kodok_results.txt | httpx -status-code -title
# 探测漏洞
cat kodok_results.txt | nuclei -t exposures/
# 检查状态码
cat kodok_results.txt | parallel -j 20 'curl -I -s {} | head -1'
|
高级用法
速率限制和隐身
1
2
3
4
5
6
|
# 对速率限制目标的慢速扫描
kodok -f urls.txt \
-workers 3 \
-timeout 90 \
-retries 5 \
-deep -depth 2
|
内存受限环境
1
2
3
4
5
|
# 减少内存占用
kodok -f huge_list.txt \
-workers 5 \
-cache 5000 \
-depth 1
|
批处理
1
2
3
4
5
6
7
8
9
10
11
|
# 分割大输入
split -l 100 js_urls.txt batch_
# 并行处理
for batch in batch_*; do
kodok -f $batch -o results_$(basename $batch) &
done
wait
# 合并结果
cat results_*.txt | sort -u > final_urls.txt
|
真实世界漏洞赏金场景
场景1:查找隐藏的管理面板
1
2
3
4
5
6
7
|
# 扫描主应用程序
kodok -u https://target.com/app.js -deep -depth 3 -v
# 输出包括:
# /admin/dashboard
# /internal/users/manage
# /debug/config
|
场景2:发现暂存/开发环境
1
2
3
4
5
6
7
8
9
10
|
// KODOK从以下提取:
const environments = {
prod: 'https://api.target.com',
staging: 'https://staging-api.target.com',
dev: 'https://dev-internal.target.com'
};
// 结果:
// https://staging-api.target.com(可能安全性较低)
// https://dev-internal.target.com(可能暴露调试信息)
|
场景3:泄露的API密钥
1
2
3
4
5
6
7
8
|
# 扫描并查找:
# - 废弃文件中的旧API密钥
# - 供应商捆绑包中的硬编码令牌
# - 配置文件中的数据库凭据
kodok -f wayback_js.txt -deep -o findings
# 在findings.json中检查"secrets"数组
jq '.results[].secrets[] | select(.type | contains("API"))' findings.json
|
场景4:子域发现
1
2
3
4
5
6
7
8
|
# 从JS提取内部子域
kodok -f js_files.txt -deep -depth 3 -o results
# 解析发现的域
cat results.txt | grep -oP 'https?://[^/]+' | sort -u > discovered_domains.txt
# 验证子域
cat discovered_domains.txt | httpx -probe
|
常见陷阱和解决方案
问题:结果太多
1
2
3
4
5
|
# 解决方案:使用域过滤
kodok -f urls.txt -ad "*.target.com" -deep
# 或限制深度
kodok -f urls.txt -depth 1
|
问题:缺少端点
1
2
3
4
5
|
# 解决方案:增加深度并使用详细模式
kodok -f urls.txt -deep -depth 5 -v
# 检查文件是否被获取
# 在JSON输出中查找"status_code": 200
|
问题:速率限制
1
2
|
# 解决方案:减少工作器并添加延迟
kodok -f urls.txt -workers 3 -timeout 90 -retries 5
|
问题:误报密钥
KODOK已经过滤常见误报:
- “example”, “test”, “demo”, “placeholder”
- 低熵字符串
- 顺序模式 (123456, abcdef)
额外手动过滤:
1
|
jq '.results[].secrets[] | select(.value | contains("example") | not)' results.json
|
最大影响提示
1. 组合多个来源
1
2
3
4
5
6
7
8
|
# 获取全面的URL列表
{
waybackurls target.com
gau target.com
katana -u https://target.com -jc -silent
gospider -s https://target.com -c 10 -d 3
} | grep "\.js" | sort -u | \
kodok -deep -depth 3 -ad "*.target.com" -o comprehensive
|
2. 关注旧文件
Wayback Machine通常有:
- 未压缩的源代码
- 带注释的调试构建
- 硬编码凭据
- 废弃端点
1
2
|
waymore -i target.com -mode U | grep "\.js" | \
kodok -deep -depth 2 -o wayback_gold
|
3. 检查供应商/第三方JS
供应商通常包括:
1
2
|
cat urls.txt | grep -E "(vendor|third-party|lib|plugins)" | \
kodok -deep -depth 1 -o vendor_findings
|
4. 优先处理高价值文件
1
2
3
|
# 关注可能有密钥的文件
cat urls.txt | grep -E "(config|admin|auth|api|internal|private)" | \
kodok -deep -depth 4 -v -o high_value
|
5. 后处理
1
2
3
4
5
6
7
8
|
# 仅提取高置信度密钥
jq '.results[].secrets[] | select(.type | contains("AWS") or contains("Stripe"))' results.json
# 查找所有数据库URL
grep -oP 'mongodb://[^"]+' results.json
# 获取唯一域
cat results.txt | grep -oP 'https?://[^/]+' | sort -u | httprobe
|
参考和相关工具
KODOK建立并补充了JavaScript安全分析生态系统:
- LinkFinder — 基于Python的端点发现工具,使用正则表达式模式
- JSScanner — 多个JS分析工具的Bash包装器
- Subdomainizer — 从JavaScript文件提取子域的Python工具
KODOK通过以下方式区分自己:
- 原生Go实现以获得更好性能
- 具有可配置深度的递归深度扫描
- 具有熵验证的全面密钥检测
- 用于大规模操作的并发工作器池
- 具有通配符支持的域过滤
- 用于安全扫描的SSRF保护
结论
KODOK将JavaScript侦察从手动、耗时的过程转变为自动化、可扩展的操作。通过将其与Waymore、Katana和GAU等工具结合,漏洞赏金猎人可以:
- 在历史和实时文件中发现隐藏端点
- 提取简单正则表达式工具遗漏的密钥
- 将分析扩展到数千个JavaScript文件
- 通过域范围控制专注于高价值目标
无论您是在单个目标上进行狩猎还是管理大范围,KODOK都为现代JavaScript安全分析提供了所需的深度和精度。
开始使用:kodok -u https://target.com/app.js -deep -depth 3 -v
仓库:https://github.com/rhyru9/kodok
KODOK是开源且积极维护的。欢迎贡献、错误报告和功能请求。