HexBrain

Revive Adserver · Report #3434156

Username Validation Bypass

Validstatus
mediumseverity
64upvotes
26 Nov 2025disclosed

How it was found

Cricetinae

Executive Summary

The security patch in commit d239a0845e4f64fbacd25fff2854426734d43aa2 is INSUFFICIENT. Testing confirms that 3 out of 4 exploit vectors still bypass validation.


Vulnerability Details

Affected Component: Username validation in user registration/creation File: lib/OA/Admin/UI/UserAccess.php Line: 116 Current Pattern: #[\x00-\x1F\x7F\s]#u

Severity: Medium-High (CVSS 6.5) Impact: Account impersonation, phishing, validation bypass


Proof of Concept - Working Exploits

Exploit 1: Zero-Width Space (U+200B) CRITICAL

Description: Invisible Unicode character that creates duplicate accounts

Payload (Hex): 61646d696ee2808b Payload (Decoded): admin + 0xE2 0x80 0x8B (UTF-8 for U+200B) Payload (Literal): The username "admin" followed by Unicode character U+200B

How to reproduce:

$malicious_username = "admin" . "\xE2\x80\x8B";  // Hex bytes
// OR
$malicious_username = "admin" . mb_chr(0x200B, 'UTF-8');  // Unicode codepoint

Test code:

<?php
$username = "admin" . "\xE2\x80\x8B";  // admin + Zero-Width Space

echo "Username: admin[U+200B]\n";
echo "Hex bytes: " . bin2hex($username) . "\n";
echo "Expected: 61646d696ee2808b\n\n";

// Test against patched pattern
if (preg_match('#[\x00-\x1F\x7F\s]#u', $username)) {
    echo "Result: BLOCKED ✓\n";
} else {
    echo "Result: PASSES - VULNERABLE! ✗\n";
}
?>

Expected output:

Username: admin[U+200B]
Hex bytes: 61646d696ee2808b
Expected: 61646d696ee2808b

Result: PASSES - VULNERABLE! ✗

Impact:

  • Creates account that looks identical to "admin" visually
  • Bypasses username uniqueness constraints
  • Enables account enumeration attacks
  • Perfect for impersonation attacks

Exploit 2: RTL Override (U+202E) HIGH

Description: Right-to-Left Override mark that reverses text display direction

Payload (Hex): 61646d696ee280ae74657374 Payload (Decoded): admin + 0xE2 0x80 0xAE + test Payload (Literal): The text "admin" + U+202E + "test"

How to reproduce:

$malicious_username = "admin" . "\xE2\x80\xAE" . "test";  // Hex bytes
// OR
$malicious_username = "admin" . mb_chr(0x202E, 'UTF-8') . "test";  // Unicode

Test code:

<?php
$username = "admin" . "\xE2\x80\xAE" . "test";  // admin + RTL Override + 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";

// Test against patched pattern
if (preg_match('#[\x00-\x1F\x7F\s]#u', $username)) {
    echo "Result: BLOCKED ✓\n";
} else {
    echo "Result: PASSES - VULNERABLE! ✗\n";
}
?>

Expected output:

Username: admin[U+202E]test
Hex bytes: 61646d696ee280ae74657374
Expected: 61646d696ee280ae74657374
Visual display: 'tset' + 'admin' (reversed!)

Result: PASSES - VULNERABLE! ✗

Impact:

  • Text appears reversed in UI ("testadmin" displays as different order)
  • Confuses administrators reviewing user accounts
  • Enables social engineering attacks
  • Visual spoofing in logs and admin panels

Exploit 3: Cyrillic Homograph (U+0430) CRITICAL

Description: Cyrillic letter 'а' (U+0430) that looks identical to Latin 'a' (U+0061)

Payload (Hex): d0b0646d696e Payload (Decoded): 0xD0 0xB0 + dmin Payload (Literal): Cyrillic 'а' (U+0430) followed by Latin "dmin"

How to reproduce:

$malicious_username = "\xD0\xB0" . "dmin";  // Hex bytes
// OR
$malicious_username = mb_chr(0x0430, 'UTF-8') . "dmin";  // Unicode

Test code:

<?php
$username = "\xD0\xB0" . "dmin";  // Cyrillic а + Latin 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";

// Compare with real admin
$real_admin = "admin";
echo "Real 'admin' hex: " . bin2hex($real_admin) . "\n";
echo "Looks same? YES | Hex same? NO\n\n";

// Test against patched pattern
if (preg_match('#[\x00-\x1F\x7F\s]#u', $username)) {
    echo "Result: BLOCKED ✓\n";
} else {
    echo "Result: PASSES - VULNERABLE! ✗\n";
}
?>

Expected output:

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! ✗

Complete Test Script

Save this as test_vulnerability.php and run with php test_vulnerability.php:

<?php
error_reporting(E_ALL);
ini_set('display_errors', 1);

echo "========================================\n";
echo "Revive Adserver - Vulnerability Test\n";
echo "========================================\n\n";

// Test 1: Zero-Width Space
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";

// Test 2: RTL Override
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";

// Test 3: Cyrillic Homograph
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";

// Test 4: Ideographic Space (should be blocked)
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";

// Summary
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";
?>

Recommended Fix

Replace the current blacklist pattern with a whitelist approach:

// Current (VULNERABLE):
if (preg_match('#[\x00-\x1F\x7F\s]#u', $this->request['login'])) {
    $this->aErrors = [$GLOBALS['strInvalidUsername']];
}

// Recommended (SECURE):
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']];
}

Additional recommendations:

  1. Unicode normalization (NFC) before validation
  2. Implement confusables detection
  3. Log suspicious username patterns
  4. Display hex representation in admin UI

Verification Steps for Developers

  1. Save the test script above as test_vulnerability.php
  2. Run: php test_vulnerability.php
  3. Observe output - you should see 3 VULNERABLE results
  4. Apply the recommended fix
  5. Run the test again - all should show BLOCKED

POC:

{F5026461}

References


Contact

Please acknowledge receipt of this report and provide an estimated timeline for patch development and CVE Assignment [kassem_s94] https://x.com/kassem_s94 https://t.me/apesofficial https://hackerone.com/kassem_s94?type=user

Impact

  • MOST DANGEROUS - Visually indistinguishable from "admin"
  • Perfect phishing vector
  • Users cannot detect the fake account
  • Credential harvesting
  • Admin impersonation attacks

This report was disclosed publicly on HackerOne and belongs to its author and the program. See the original