fadhilkhafiz31/oauth2-bruteforce-splunk
GitHub: fadhilkhafiz31/oauth2-bruteforce-splunk
一个集OAuth2认证服务器搭建、凭据填充攻击模拟与Splunk实时检测于一体的安全攻防实验环境。
Stars: 0 | Forks: 0
# 🔐 打造了这把锁。撬开了这把锁。然后报了警抓自己。
## 📋 事件概要
| 字段 | 详情 |
|-------|---------|
| **目标** | 自定义 Node.js OAuth2 认证服务器 |
| **攻击类型** | 凭据填充 / 暴力破解登录 |
| **使用工具** | Burp Suite Intruder |
| **检测平台** | Splunk Enterprise |
| **总攻击事件** | 137 次 LOGIN_FAILED, 4 次 LOGIN_SUCCESS |
| **攻击者 IP** | `::ffff:127.0.0.1` (模拟) |
| **目标账户** | `admin` |
| **破解密码** | `admin123` (载荷位置 27/30) |
## 🗂 项目结构
```
authentication-mock-up/
├── server.js # Node.js OAuth2 server with security logger
├── logs/
│ └── security.log # Structured JSON security events (Splunk input)
├── package.json
└── README.md
```
## 🔴 第一集 — 打造这把锁
### 构建内容
一个完整的 OAuth2 授权服务器,使用:
- **Node.js + Express** — 带有登录和令牌端点的 REST API
- **Passport.js** — LocalStrategy 和 BearerStrategy 认证
- **oauth2orize** — 授权码许可流程
- **bcrypt** — 带盐值的密码哈希 (工作因子: 10)
### 盐值问题
如果没有盐值,两个使用相同密码的用户会产生完全相同的哈希值 —— 这对攻击者来说是巨大的胜利。bcrypt 通过在哈希之前添加一个唯一的随机盐值来解决这个问题。
```
// Generating the hash
const hash = bcrypt.hashSync('admin123', 10);
// Output: $2a$10$bbc.ZA1Pca.Qxv.xmQSXSOIxHFA7STjc3KcNRwvqoTr1OZ2RZkGD.
// ^^^ work factor — hashing runs 2^10 = 1024 times
```
`$2a$10$` 前缀准确地告诉你它是如何被哈希的 —— 算法、版本和成本因子。
## 🔴 第二集 — 撬锁 (攻击模拟)
### 环境设置
- Kali Linux VM (VirtualBox)
- Burp Suite Community Edition v2025.7.4
- 运行在 `localhost:3000` 的 Node.js 服务器
### 攻击流程
1. 在 Burp Proxy 中捕获一个 `POST /login` 请求
2. 发送到 **Intruder** → Sniper 攻击模式
3. 在 `password` 字段设置载荷位置
4. 加载一个包含 30 个密码的字典:
password, 123456, password123, admin, letmein,
welcome, monkey, dragon, master, abc123,
donald, pass123, test, guest, admin123, root, toor, changeme...
5. 发起 30 个请求 — 29 个返回 `401`, 1 个返回 `200`
6. **载荷 27 — `admin123` — 破解成功**
### 安全日志输出 (样本)
```
{"timestamp":"2026-03-15T02:40:11.319Z","event_type":"LOGIN_SUCCESS","endpoint":"/login","src_ip":"::ffff:127.0.0.1","username":"admin","user_id":"1","status":200}
{"timestamp":"2026-03-15T02:40:12.630Z","event_type":"LOGIN_FAILED","endpoint":"/login","src_ip":"::ffff:127.0.0.1","username":"admin","status":401,"reason":"Wrong password"}
```
## 🔵 第二集 — 报警 (Splunk 检测)
### 数据接入设置
- Splunk Enterprise 安装在 `/opt/splunk`
- 数据输入 → Files & Directories → `logs/security.log`
- 源类型: `_json`
### 检测查询 — 暴力破解阈值
```
index=main sourcetype=_json
| spath event_type | spath src_ip
| search event_type="LOGIN_FAILED"
| bucket _time span=5m
| stats count by src_ip, _time
| where count >= 10
```
### 仪表板面板
| 面板 | 图表类型 | SPL |
|-------|-----------|-----|
| 攻击频率最高的 IP | Bar Chart | `stats count by src_ip \| sort -count` |
| 攻击时间轴 | Line Chart | `timechart span=5m count` |
| 被攻击的用户名 | Bar Chart | `stats count by username \| sort -count` |
| 失败 vs 成功 | Pie Chart | `stats count by event_type` |
| 威胁关联 | Table | `stats count by src_ip, event_type` |
### 结果
- 单个 IP 在一个会话中产生了 **137 次 LOGIN_FAILED**
- 攻击激增在时间轴上清晰可见
- `admin` 是唯一被攻击的用户名
- 所有事件类型中关联到同一个 IP
## 🛠 技术栈
| 层级 | 工具 |
|-------|------|
| 服务器 | Node.js, Express |
| 认证 | Passport.js, oauth2orize |
| 哈希 | bcrypt |
| 攻击模拟 | Burp Suite Community |
| 日志接入 | Splunk Enterprise |
| 检测 | SPL (Splunk Processing Language) |
| 实验环境 | Kali Linux, VirtualBox |
## 🚀 如何运行
### 1. 安装依赖
```
npm install
```
### 2. 启动服务器
```
node server.js
```
服务器运行在 `http://localhost:3000`
演示凭据:
- 用户名: `admin`
- 密码: `admin123`
### 3. 模拟攻击
```
for i in {1..30}; do
curl -s -X POST http://localhost:3000/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"wrongpass"}'
sleep 0.5
done
```
### 4. 接入 Splunk
- Settings → Data Inputs → Files & Directories
- 路径: `/path/to/logs/security.log`
- 源类型: `_json`
## 📎 参考资料
- [oauth2orize](https://github.com/jaredhanson/oauth2orize)
- [Passport.js](https://www.passportjs.org/)
- [Splunk SPL Reference](https://docs.splunk.com/Documentation/Splunk/latest/SearchReference)
- [Burp Suite Intruder](https://portswigger.net/burp/documentation/desktop/tools/intruder)
标签:bcrypt, Burp Suite, Express, GNU通用公共许可证, JSON日志, MITM代理, Node.js, OAuth2, Passport.js, PoC, URL发现, Web安全, 凭证填充, 后端开发, 安全检测, 安全运营, 扫描框架, 攻击模拟, 暴力破解, 红队行动, 蓝队分析, 蜜罐思维, 驱动签名利用