Revive Adserver | 报告 #3434156 - 用户名验证绕过 | HackerOne
执行摘要
提交记录为 d239a0845e4f64fbacd25fff2854426734d43aa2 的安全补丁不充分。
测试确认,4种攻击向量中有3种仍然可以绕过验证。
漏洞详情
受影响组件: 用户注册/创建过程中的用户名验证
文件: lib/OA/Admin/UI/UserAccess.php
行号: 116
当前模式: #[\x00-\x1F\x7F\s]#u
严重性: 中-高 (CVSS 6.5)
影响: 账户冒充、钓鱼攻击、验证绕过
概念验证 - 有效的攻击方法
攻击方法 1: 零宽空格 (U+200B) 关键
描述: 不可见的Unicode字符,可创建重复账户
载荷 (十六进制): 61646d696ee2808b
载荷 (解码后): admin + 0xE2 0x80 0x8B (UTF-8编码的 U+200B)
载荷 (字面意思): 用户名 “admin” 后跟Unicode字符 U+200B
如何复现:
1
2
3
|
$malicious_username = "admin" . "\xE2\x80\x8B"; // 十六进制字节
// 或者
$malicious_username = "admin" . mb_chr(0x200B, 'UTF-8'); // Unicode代码点
|
测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
<?php
$username = "admin" . "\xE2\x80\x8B"; // admin + 零宽空格
echo "Username: admin[U+200B]\n";
echo "Hex bytes: " . bin2hex($username) . "\n";
echo "Expected: 61646d696ee2808b\n\n";
// 测试已修补的模式
if (preg_match('#[\x00-\x1F\x7F\s]#u', $username)) {
echo "Result: BLOCKED ✓\n";
} else {
echo "Result: PASSES - VULNERABLE! ✗\n";
}
?>
|
预期输出:
1
2
3
4
5
|
Username: admin[U+200B]
Hex bytes: 61646d696ee2808b
Expected: 61646d696ee2808b
Result: PASSES - VULNERABLE! ✗
|
影响:
- 创建视觉上与"admin"完全相同的账户
- 绕过用户名唯一性约束
- 支持账户枚举攻击
- 非常适合冒充攻击
攻击方法 2: RTL 覆盖 (U+202E) 高
描述: 从右到左覆盖标记,反转文本显示方向
载荷 (十六进制): 61646d696ee280ae74657374
载荷 (解码后): admin + 0xE2 0x80 0xAE + test
载荷 (字面意思): 文本 “admin” + U+202E + “test”
如何复现:
1
2
3
|
$malicious_username = "admin" . "\xE2\x80\xAE" . "test"; // 十六进制字节
// 或者
$malicious_username = "admin" . mb_chr(0x202E, 'UTF-8') . "test"; // Unicode
|
测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
|
<?php
$username = "admin" . "\xE2\x80\xAE" . "test"; // admin + RTL覆盖 + test
echo "Username: admin[U+202E]test\n";
echo "Hex bytes: " . bin2hex($username) . "\n";
echo "Expected: 61646d696ee280ae74657374\n";
echo "Visual display: 'tset' + 'admin' (reversed!)\n\n";
// 测试已修补的模式
if (preg_match('#[\x00-\x1F\x7F\s]#u', $username)) {
echo "Result: BLOCKED ✓\n";
} else {
echo "Result: PASSES - VULNERABLE! ✗\n";
}
?>
|
预期输出:
1
2
3
4
5
6
|
Username: admin[U+202E]test
Hex bytes: 61646d696ee280ae74657374
Expected: 61646d696ee280ae74657374
Visual display: 'tset' + 'admin' (reversed!)
Result: PASSES - VULNERABLE! ✗
|
影响:
- 文本在UI中显示为反转(“testadmin"显示为不同顺序)
- 混淆审查用户账户的管理员
- 支持社会工程学攻击
- 在日志和管理面板中进行视觉欺骗
攻击方法 3: 西里尔文同形字 (U+0430) 关键
描述: 看起来与拉丁字母’a’ (U+0061)完全相同的西里尔字母’а’ (U+0430)
载荷 (十六进制): d0b0646d696e
载荷 (解码后): 0xD0 0xB0 + dmin
载荷 (字面意思): 西里尔字母’а’ (U+0430) 后跟拉丁字母 “dmin”
如何复现:
1
2
3
|
$malicious_username = "\xD0\xB0" . "dmin"; // 十六进制字节
// 或者
$malicious_username = mb_chr(0x0430, 'UTF-8') . "dmin"; // Unicode
|
测试代码:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
|
<?php
$username = "\xD0\xB0" . "dmin"; // 西里尔字母 а + 拉丁字母 dmin
echo "Username: [U+0430]dmin (looks like 'admin')\n";
echo "Hex bytes: " . bin2hex($username) . "\n";
echo "Expected: d0b0646d696e\n";
echo "Visual: Appears identical to 'admin'\n\n";
// 与真正的admin比较
$real_admin = "admin";
echo "Real 'admin' hex: " . bin2hex($real_admin) . "\n";
echo "Looks same? YES | Hex same? NO\n\n";
// 测试已修补的模式
if (preg_match('#[\x00-\x1F\x7F\s]#u', $username)) {
echo "Result: BLOCKED ✓\n";
} else {
echo "Result: PASSES - VULNERABLE! ✗\n";
}
?>
|
预期输出:
1
2
3
4
5
6
7
8
9
|
Username: [U+0430]dmin (looks like 'admin')
Hex bytes: d0b0646d696e
Expected: d0b0646d696e
Visual: Appears identical to 'admin'
Real 'admin' hex: 61646d696e
Looks same? YES | Hex same? NO
Result: PASSES - VULNERABLE! ✗
|
完整的测试脚本
将此脚本保存为 test_vulnerability.php 并用 php test_vulnerability.php 运行:
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
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
|
<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);
echo "========================================\n";
echo "Revive Adserver - Vulnerability Test\n";
echo "========================================\n\n";
// 测试 1: 零宽空格
echo "[TEST 1] Zero-Width Space (U+200B)\n";
echo "----------------------------------------\n";
$test1 = "admin" . "\xE2\x80\x8B";
echo "Payload hex: " . bin2hex($test1) . "\n";
echo "Expected: 61646d696ee2808b\n";
echo "Match: " . (bin2hex($test1) === "61646d696ee2808b" ? "YES ✓" : "NO ✗") . "\n";
$blocked1 = preg_match('#[\x00-\x1F\x7F\s]#u', $test1);
echo "Status: " . ($blocked1 ? "BLOCKED ✓" : "VULNERABLE ✗") . "\n\n";
// 测试 2: RTL 覆盖
echo "[TEST 2] RTL Override (U+202E)\n";
echo "----------------------------------------\n";
$test2 = "admin" . "\xE2\x80\xAE" . "test";
echo "Payload hex: " . bin2hex($test2) . "\n";
echo "Expected: 61646d696ee280ae74657374\n";
echo "Match: " . (bin2hex($test2) === "61646d696ee280ae74657374" ? "YES ✓" : "NO ✗") . "\n";
$blocked2 = preg_match('#[\x00-\x1F\x7F\s]#u', $test2);
echo "Status: " . ($blocked2 ? "BLOCKED ✓" : "VULNERABLE ✗") . "\n\n";
// 测试 3: 西里尔文同形字
echo "[TEST 3] Cyrillic Homograph (U+0430)\n";
echo "----------------------------------------\n";
$test3 = "\xD0\xB0" . "dmin";
echo "Payload hex: " . bin2hex($test3) . "\n";
echo "Expected: d0b0646d696e\n";
echo "Match: " . (bin2hex($test3) === "d0b0646d696e" ? "YES ✓" : "NO ✗") . "\n";
$blocked3 = preg_match('#[\x00-\x1F\x7F\s]#u', $test3);
echo "Status: " . ($blocked3 ? "BLOCKED ✓" : "VULNERABLE ✗") . "\n\n";
// 测试 4: 表意文字空格 (应该被阻止)
echo "[TEST 4] Ideographic Space (U+3000) - Control\n";
echo "----------------------------------------\n";
$test4 = "admin" . "\xE3\x80\x80" . "test";
echo "Payload hex: " . bin2hex($test4) . "\n";
echo "Expected: 61646d696ee3808074657374\n";
echo "Match: " . (bin2hex($test4) === "61646d696ee3808074657374" ? "YES ✓" : "NO ✗") . "\n";
$blocked4 = preg_match('#[\x00-\x1F\x7F\s]#u', $test4);
echo "Status: " . ($blocked4 ? "BLOCKED ✓" : "VULNERABLE ✗") . "\n\n";
// 摘要
echo "========================================\n";
echo "SUMMARY\n";
echo "========================================\n";
$vuln_count = (!$blocked1 ? 1 : 0) + (!$blocked2 ? 1 : 0) + (!$blocked3 ? 1 : 0);
echo "Vulnerabilities found: $vuln_count/3\n";
echo "Patch effectiveness: " . ((3 - $vuln_count) / 3 * 100) . "%\n\n";
if ($vuln_count > 0) {
echo " CRITICAL: Patch is INSUFFICIENT!\n";
echo "Working exploits:\n";
if (!$blocked1) echo " • Zero-Width Space\n";
if (!$blocked2) echo " • RTL Override\n";
if (!$blocked3) echo " • Cyrillic Homograph\n";
} else {
echo "✓ All exploits blocked\n";
}
echo "\n========================================\n";
?>
|
推荐修复方案
将当前的黑名单模式替换为白名单方法:
1
2
3
4
5
6
7
8
9
10
11
12
|
// 当前(有漏洞):
if (preg_match('#[\x00-\x1F\x7F\s]#u', $this->request['login'])) {
$this->aErrors = [$GLOBALS['strInvalidUsername']];
}
// 推荐(安全):
if (empty($this->request['login']) ||
strlen($this->request['login']) > 255 ||
!preg_match('/^[a-zA-Z0-9._@-]+$/D', $this->request['login']) ||
$this->request['login'] !== trim($this->request['login'])) {
$this->aErrors = [$GLOBALS['strInvalidUsername']];
}
|
额外建议:
- 验证前进行Unicode规范化 (NFC)
- 实现易混淆字符检测
- 记录可疑的用户名模式
- 在管理界面显示十六进制表示形式
给开发者的验证步骤
- 将上面的测试脚本保存为
test_vulnerability.php
- 运行:
php test_vulnerability.php
- 观察输出 - 你应该能看到3个VULNERABLE结果
- 应用推荐的修复方案
- 再次运行测试 - 所有结果都应显示BLOCKED
附件:
![[图片]](/Screenshot_20251119_230624_Termux.jpg)
参考:
联系方式
请确认收到此报告,并提供补丁开发和CVE分配的时间预估 [kassem_s94] https://x.com/kassem_s94 https://t.me/apesofficial https://hackerone.com/kassem_s94?type=user
影响
- 最危险 - 视觉上与"admin"无法区分
- 完美的钓鱼攻击载体
- 用户无法检测到虚假账户
- 凭据收集
- 管理员冒充攻击