Every CVE Search/ Get API key

CVE-2026-40935

WWBN/AVideo has CAPTCHA Bypass via Attacker-Controlled Length Parameter and Missing Token Invalidation on Failure

5.3 Medium

WWBN AVideo is an open source video platform. In versions 29.0 and prior, objects/getCaptcha.php accepts the CAPTCHA length (ql) directly from the query string with no clamping or sanitization, letting any unauthenticated client force the server to generate a 1-character CAPTCHA word. Combined with a case-insensitive strcasecmp comparison over a ~33-character alphabet and the fact that failed validations do NOT consume the stored session token, an attacker can trivially brute-force the CAPTCHA on any endpoint that relies on Captcha::validation() (user registration, password recovery, contact form, etc.) in at most ~33 requests per session. Commit bf1c76989e6a9054be4f0eb009d68f0f2464b453 contains a fix.

Attack profile

How easy it is to exploit

Attack vector
Network
Complexity
Low
Privileges needed
None
User interaction
None

What an attacker can affect

Confidentiality
None
Integrity
Low
Availability
None

Exploit likelihood

0.22%Up 0.2 points since Apr 22, 2026
90%50%10%1%

What each source reports

CVE List Score used 5.3

WWBN/AVideo has CAPTCHA Bypass via Attacker-Controlled Length Parameter and Missing Token Invalidation on Failure

WWBN AVideo is an open source video platform. In versions 29.0 and prior, objects/getCaptcha.php accepts the CAPTCHA length (ql) directly from the query string with no clamping or sanitization, letting any unauthenticated client force the server to generate a 1-character CAPTCHA word. Combined with a case-insensitive strcasecmp comparison over a ~33-character alphabet and the fact that failed validations do NOT consume the stored session token, an attacker can trivially brute-force the CAPTCHA on any endpoint that relies on Captcha::validation() (user registration, password recovery, contact form, etc.) in at most ~33 requests per session. Commit bf1c76989e6a9054be4f0eb009d68f0f2464b453 contains a fix.

Record
CVE-2026-40935
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-804
Updated
2026-11-02
EUVDEUVD-2026-24527 5.3

WWBN AVideo is an open source video platform. In versions 29.0 and prior, objects/getCaptcha.php accepts the CAPTCHA length (ql) directly from the query string with no clamping or sanitization, letting any unauthenticated client force the server to generate a 1-character CAPTCHA word. Combined with a case-insensitive strcasecmp comparison over a ~33-character alphabet and the fact that failed validations do NOT consume the stored session token, an attacker can trivially brute-force the CAPTCHA on any endpoint that relies on Captcha::validation() (user registration, password recovery, contact form, etc.) in at most ~33 requests per session. Commit bf1c76989e6a9054be4f0eb009d68f0f2464b453 contains a fix.

Record
EUVD-2026-24527
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Updated
2026-11-02
GitHub AdvisoriesGHSA-hg7g-56h5-5pqr 5.3

CAPTCHA Bypass in WWBN/AVideo via Attacker-Controlled Length Parameter and Missing Token Invalidation on Failure

Summary

objects/getCaptcha.php accepts the CAPTCHA length (ql) directly from the query string with no clamping or sanitization, letting any unauthenticated client force the server to generate a 1-character CAPTCHA word. Combined with a case-insensitive strcasecmp comparison over a ~33-character alphabet and the fact that failed validations do NOT consume the stored session token, an attacker can trivially brute-force the CAPTCHA on any endpoint that relies on Captcha::validation() (user registration, password recovery, contact form, etc.) in at most ~33 requests per session.

Details

Three cooperating flaws in objects/getCaptcha.php and objects/captcha.php reduce CAPTCHA protection to a deterministic bypass.

1. External control of CAPTCHA strength (objects/getCaptcha.php:7)

$largura        = empty($_GET['l'])  ? 120 : $_GET['l'];
$altura         = empty($_GET['a'])  ? 40  : $_GET['a'];
$tamanho_fonte  = empty($_GET['tf']) ? 18  : $_GET['tf'];
$quantidade_letras = empty($_GET['ql']) ? 5 : $_GET['ql']; // attacker-controlled

$capcha = new Captcha($largura, $altura, $tamanho_fonte, $quantidade_letras);
$capcha->getCaptchaImage();

There is no minimum, no type-check, and no clamping. Requesting /objects/getCaptcha.php?ql=1 causes the server to generate a single-character word and save it to the attacker's own PHP session.

2. Small alphabet stored in the session (objects/captcha.php:33-39)

$letters = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnPpQqRrSsTtUuVvYyXxWwZz23456789';
$palavra = substr(str_shuffle($letters), 0, ($this->quantidade_letras));
if (User::isAdmin() && empty($_REQUEST['forceCaptcha'])) {
    $palavra = "admin";
}
_session_start();
$_SESSION["palavra"] = $palavra;

After case-folding the alphabet is 25 letters (A–Z minus O) plus digits 2-9, i.e. 33 unique values. For an unauthenticated attacker the admin branch at line 35 is unreachable, so the value is purely random over that 33-symbol set.

3. Weak comparison and token NOT invalidated on failure (objects/captcha.php:58-75)

public static function validation($word)
{
    if (User::isAdmin() && $_SESSION["palavra"] === 'admin') {
        return true;
    }
    _session_start();
    if (empty($_SESSION["palavra"])) {
        _error_log("Captcha validation Error: you type ({$word}) and session is empty ...");
        return false;
    }
    $validation = (strcasecmp($word, $_SESSION["palavra"]) == 0);
    if (!$validation) {
        _error_log("Captcha validation Error: you type ({$word}) and session is ({$_SESSION["palavra"]}) ...");
    } else {
        unset($_SESSION["palavra"]); // Consume the captcha token to prevent reuse
    }
    return $validation;
}

Two problems here:

  • strcasecmp is case-insensitive, collapsing the alphabet to ~33 distinct values.
  • unset($_SESSION["palavra"]) only runs in the success branch. Every failed guess leaves the stored word intact, so the same session can be retried against the same stored answer until it matches.

Reachability

Captcha::validation() is invoked from unauthenticated entry points including:

  • objects/userCreate.json.php:38 — user registration (Captcha::validation($_POST['captcha']))
  • objects/userRecoverPass.php:31 — password recovery
  • objects/sendEmail.json.php:10 — public contact email
  • plugin/API/API.php:4243 and :5684 — public API endpoints
  • plugin/CustomizeUser/donate.json.php:62, confirmDeleteUser.json.php:15
  • plugin/YPTWallet/view/transferFunds.json.php:25

None of these require authentication for the CAPTCHA check to matter — they rely on it exactly because they're exposed to anonymous or lightly-authenticated callers.

PoC

Attacker flow against an unauthenticated signup/recovery endpoint:

Step 1 — Weaken the CAPTCHA to one character and install it in the attacker's own PHP session:

curl -c jar -s 'https://target/objects/getCaptcha.php?ql=1' -o /dev/null

Step 2 —…

Record
GHSA-hg7g-56h5-5pqr
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-804
Updated
2026-11-02
NVD 5.3

WWBN AVideo is an open source video platform. In versions 29.0 and prior, objects/getCaptcha.php accepts the CAPTCHA length (ql) directly from the query string with no clamping or sanitization, letting any unauthenticated client force the server to generate a 1-character CAPTCHA word. Combined with a case-insensitive strcasecmp comparison over a ~33-character alphabet and the fact that failed validations do NOT consume the stored session token, an attacker can trivially brute-force the CAPTCHA on any endpoint that relies on Captcha::validation() (user registration, password recovery, contact form, etc.) in at most ~33 requests per session. Commit bf1c76989e6a9054be4f0eb009d68f0f2464b453 contains a fix.

Record
CVE-2026-40935
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-804
Updated
2026-11-02
OSV 5.3

WWBN/AVideo has CAPTCHA Bypass via Attacker-Controlled Length Parameter and Missing Token Invalidation on Failure

WWBN AVideo is an open source video platform. In versions 29.0 and prior, objects/getCaptcha.php accepts the CAPTCHA length (ql) directly from the query string with no clamping or sanitization, letting any unauthenticated client force the server to generate a 1-character CAPTCHA word. Combined with a case-insensitive strcasecmp comparison over a ~33-character alphabet and the fact that failed validations do NOT consume the stored session token, an attacker can trivially brute-force the CAPTCHA on any endpoint that relies on Captcha::validation() (user registration, password recovery, contact form, etc.) in at most ~33 requests per session. Commit bf1c76989e6a9054be4f0eb009d68f0f2464b453 contains a fix.

Record
CVE-2026-40935
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-804
Updated
2026-11-02
OSVGHSA-hg7g-56h5-5pqr 5.3

CAPTCHA Bypass in WWBN/AVideo via Attacker-Controlled Length Parameter and Missing Token Invalidation on Failure

Summary

objects/getCaptcha.php accepts the CAPTCHA length (ql) directly from the query string with no clamping or sanitization, letting any unauthenticated client force the server to generate a 1-character CAPTCHA word. Combined with a case-insensitive strcasecmp comparison over a ~33-character alphabet and the fact that failed validations do NOT consume the stored session token, an attacker can trivially brute-force the CAPTCHA on any endpoint that relies on Captcha::validation() (user registration, password recovery, contact form, etc.) in at most ~33 requests per session.

Details

Three cooperating flaws in objects/getCaptcha.php and objects/captcha.php reduce CAPTCHA protection to a deterministic bypass.

1. External control of CAPTCHA strength (objects/getCaptcha.php:7)

$largura        = empty($_GET['l'])  ? 120 : $_GET['l'];
$altura         = empty($_GET['a'])  ? 40  : $_GET['a'];
$tamanho_fonte  = empty($_GET['tf']) ? 18  : $_GET['tf'];
$quantidade_letras = empty($_GET['ql']) ? 5 : $_GET['ql']; // attacker-controlled

$capcha = new Captcha($largura, $altura, $tamanho_fonte, $quantidade_letras);
$capcha->getCaptchaImage();

There is no minimum, no type-check, and no clamping. Requesting /objects/getCaptcha.php?ql=1 causes the server to generate a single-character word and save it to the attacker's own PHP session.

2. Small alphabet stored in the session (objects/captcha.php:33-39)

$letters = 'AaBbCcDdEeFfGgHhIiJjKkLlMmNnPpQqRrSsTtUuVvYyXxWwZz23456789';
$palavra = substr(str_shuffle($letters), 0, ($this->quantidade_letras));
if (User::isAdmin() && empty($_REQUEST['forceCaptcha'])) {
    $palavra = "admin";
}
_session_start();
$_SESSION["palavra"] = $palavra;

After case-folding the alphabet is 25 letters (A–Z minus O) plus digits 2-9, i.e. 33 unique values. For an unauthenticated attacker the admin branch at line 35 is unreachable, so the value is purely random over that 33-symbol set.

3. Weak comparison and token NOT invalidated on failure (objects/captcha.php:58-75)

public static function validation($word)
{
    if (User::isAdmin() && $_SESSION["palavra"] === 'admin') {
        return true;
    }
    _session_start();
    if (empty($_SESSION["palavra"])) {
        _error_log("Captcha validation Error: you type ({$word}) and session is empty ...");
        return false;
    }
    $validation = (strcasecmp($word, $_SESSION["palavra"]) == 0);
    if (!$validation) {
        _error_log("Captcha validation Error: you type ({$word}) and session is ({$_SESSION["palavra"]}) ...");
    } else {
        unset($_SESSION["palavra"]); // Consume the captcha token to prevent reuse
    }
    return $validation;
}

Two problems here:

  • strcasecmp is case-insensitive, collapsing the alphabet to ~33 distinct values.
  • unset($_SESSION["palavra"]) only runs in the success branch. Every failed guess leaves the stored word intact, so the same session can be retried against the same stored answer until it matches.

Reachability

Captcha::validation() is invoked from unauthenticated entry points including:

  • objects/userCreate.json.php:38 — user registration (Captcha::validation($_POST['captcha']))
  • objects/userRecoverPass.php:31 — password recovery
  • objects/sendEmail.json.php:10 — public contact email
  • plugin/API/API.php:4243 and :5684 — public API endpoints
  • plugin/CustomizeUser/donate.json.php:62, confirmDeleteUser.json.php:15
  • plugin/YPTWallet/view/transferFunds.json.php:25

None of these require authentication for the CAPTCHA check to matter — they rely on it exactly because they're exposed to anonymous or lightly-authenticated callers.

PoC

Attacker flow against an unauthenticated signup/recovery endpoint:

Step 1 — Weaken the CAPTCHA to one character and install it in the attacker's own PHP session:

curl -c jar -s 'https://target/objects/getCaptcha.php?ql=1' -o /dev/null

Step 2 —…

Record
GHSA-hg7g-56h5-5pqr
CVSS 3.1
5.3 MediumCVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:L/A:N
Weakness
CWE-804
Updated
2026-11-02

Affected products

Affected packages

Affected packages
PackageAffectedFixed
wwbn/avideo
Packagist
through 29.0 None known
wwbn/avideo
Packagist
through 29.0, plus listed versions
10.410.81111.111.1.1
Show 12 moreShow less
11.511.612.414.314.3.114.418.021.022.024.025.026.0
None known

History

History
RecordedChangedSources
first indexedCVE List, EUVD, GitHub Advisories, NVD, OSV

Dates are when Every CVE recorded each change. Upstream dates may differ.

In short

CVE-2026-40935 is a medium vulnerability (CVSS 5.3) in Wwbn Avideo, published April 14, 2026. No source lists public exploit code. EPSS puts the chance of exploitation in the next 30 days at 0.22%, the 12th percentile. No source names a fixed version.

References

This page doesn't list everything

Left out here: the rest of 2 source descriptions. The JSON record has them.

MoveEnter Open