CFR-410 study materials
CFR-410 study resources

Invoice Portal: Did the SQL Injection Actually Land?

CFR-410 · Put your knowledge to work in context.

All case studies

Invoice Portal: Did the SQL Injection Actually Land?

Northline Retail runs a PHP/MySQL invoice portal on two Apache 2.4 nodes behind an F5 load balancer. The WAF was moved to detect-only mode during a checkout redesign three weeks ago and never returned to blocking. At 02:14 UTC Tuesday, Apache access logs show 38 requests from 203.0.113.44 to /invoice/view.php?id= carrying UNION SELECT payloads. Request 39 returned HTTP 200 with a 4,912-byte body, versus 1,180 bytes for the portal's normal error page. At 02:31 the same IP requested /uploads/inv_20240612.php and received 200; the uploads directory still has PHP execution enabled for a legacy feature. At 02:33 the web node opened outbound TCP to 198.51.100.9:4444 that stayed up 41 minutes. No malware alert fired on the endpoint agent installed on the web nodes. A change freeze blocks production patching until Friday 22:00. Cardholder data lives in a separate database that the web tier can reach.

1. Determine whether the attacker achieved code execution, and justify the conclusion using only the evidence in the setup.

Read the worked answer

Yes - treat this as probable code execution, though it is not yet confirmed on disk. Three independent signals converge:

  • The 200 response with a 4,912-byte body to a UNION SELECT request matches a query returning attacker-selected data; error pages were 1,180 bytes, so this is not a generic failure.
  • The later request for /uploads/inv_20240612.php returning 200 proves a file existed there and was served, and that directory executes PHP - the combination is a webshell.
  • The outbound :4444 session began two minutes after the upload; that port is a textbook reverse-shell handler.

Alternative explanations are weak. No legitimate user requests a .php file in uploads at 02:31 from the same address that just attempted injection. The silent endpoint agent is not exculpatory: a webshell is a script, not an executable, so signature scanning commonly misses it.

Confirmation steps: read and hash the file from disk, compare against known webshell patterns, and tie the Apache child PID to the outbound socket through netstat, lsof, or EDR network telemetry.

2. Rank your containment actions for the next 60 minutes, given the change freeze and PCI scope.

Read the worked answer

Rank by 'stops the adversary' first, 'preserves evidence' second, 'restores compliance' last.

  1. Kill the command channel without destroying state. Push an emergency egress block for 198.51.100.9:4444 and 203.0.113.44 at the perimeter and deny outbound from the web tier except to the database and package mirrors. This is a firewall rule, not an application change, so the freeze does not apply.
  2. Capture before shutdown. Acquire memory and a disk snapshot of the affected web node before anyone reboots it; a reboot erases the only record of the running webshell's parent process.
  3. Virtual-patch at the WAF. Re-enable blocking with a signature for the id parameter. This contains the injection vector without touching code, buying time until Friday.
  4. Drain and isolate. Remove the node from the load-balancer pool only after the snapshot; keeping one node serving degraded service is preferable to a full outage if scope is still unproven.
  5. Rotate last. Reset database credentials and API keys only after you know what the webshell read; rotating too early destroys session evidence and can tip off the operator.

The full Friday patch is the permanent fix, not the containment step.

3. Which artifacts would you collect to scope the breach, and what would each tell you?

Read the worked answer
  • Apache access and error logs (both nodes, plus F5 logs): every request from 203.0.113.44 and any other address that touched inv_20240612.php, including user agents and referrers. The F5 view reveals whether the attacker hit node 2 as well.
  • Uploads directory listing with timestamps and hashes: other dropped files and the exact upload technique used, which distinguishes a PHP file-upload flaw from a webshell written by SQL INTO OUTFILE.
  • MySQL general query log and audit plugin output: whether the injected SELECT read cardholder tables, row counts, and any file-write functions called.
  • NetFlow/pcap for the web tier: all outbound sessions in the 02:14-04:00 window, to find secondary C2 or data staging beyond the one :4444 session.
  • Web node memory and process tree: which httpd child spawned the shell, and whether the attacker moved to the internal database host.
  • Database-side authentication logs: new or unusual logins from the web tier in the same window.

Sequence the database audit review before the Friday patch, because the query log rotates and is the only proof of what data was touched for PCI notification decisions.