Unsafe OS Command Execution Without File Upload (PHP)
Written by Aryan Giri
๐ฅ Overview
When people think about getting code execution on a server, they usually think about file upload vulnerabilities (uploading a webshell, etc.).
But thereโs a quieter and often more dangerous path:
๐ Unsafe OS command execution via existing functionality
This is NOT PHP code injection โ itโs the server passing user input into a system shell.
No file upload. No shell file. Just abusing whatโs already there.
โ ๏ธ The Core Vulnerability
This attack happens when user input is passed directly into system-level functions like:
system()
exec()
shell_exec()
passthru()
Vulnerable Code Example
<?php
$name = $_GET['name'];
system("ping " . $name);
?>
๐ Important:
- The shell executes the final string
- User input becomes part of a shell command, not PHP code
This leads to command/argument injection, not PHP code execution.
๐ฃ The Payload
';system("ipconfig");//
Example Exploit URL
http://AttackTest.com?file=';system("ipconfig");//
๐ If the backend uses the file parameter inside a shell call, this will execute ipconfig and return the output directly in the web response.
Breakdown
| Component | What It Does | Why It Matters |
|---|---|---|
' |
Breaks out of the original string | Escapes developer-controlled context so you can inject your own code |
; |
Terminates the current command | Lets you chain a new command after the original one |
system("ipconfig") |
Executes OS-level command | Gives you direct command execution on the server |
// |
Comments out the rest of the line | Prevents syntax errors and ignores remaining backend code |
๐ง How the Exploit Works
Backend builds a shell command like:
system("ping " . $_GET['name']);
If input is not sanitized, it becomes:
ping example.com; dir
Shell interprets:
- Run
ping example.com - Then run
dir
๐ The shell executes both because of command chaining (;)
โ ๏ธ Note: This is shell-level injection, not execution of injected PHP code.
Boom โ command execution achieved.
๐ฏ Why This Is Powerful
- No file upload needed
- Works on minimal input fields (search, ping tools, diagnostics panels)
- Often overlooked in legacy PHP apps
- Can lead to full system compromise
๐งช Real Demo (Intentionally Vulnerable Site)
You can safely test this technique on the following intentionally vulnerable lab:
http://php.testinvicti.com/hello.php?name=%27;system(%22dir%22);//
Also works without URL encoding
http://php.testinvicti.com/hello.php?name=';system("dir");//
๐ Same payload, just not URL-encoded. Depending on the server and filters, this may work directly in the browser.
Whatโs happening here?
%27โ'(breaks out of string);โ command separatorsystem("dir")โ executes a Windows command//โ comments rest of the line
About the dir command
dirlists files and directories in the current folder (Windows equivalent oflsin Linux)- When executed, its output is reflected directly in the web response
๐ So instead of just seeing โHello userโ, youโll see server directory contents in the page.
โ ๏ธ Responsible Testing Note
This site is intentionally vulnerable for learning
It resets automatically (typically after midnight)
Do NOT attempt:
- Destructive commands
- Service disruption (DoS)
- Anything beyond demonstration of the vulnerability
๐ซ About DoS (Reality Check)
Youโll see a lot of forums hyping DoS as โhigh bountyโ.
Reality:
- Most DoS attempts are just traffic flooding, not real vulnerabilities
- Big companies already test their infra against DoS internally
- Random flooding โ valid security bug in most programs
๐ Instead of wasting time on DoS, focus on:
- Information Disclosure
- Command Injection / RCE
- Authentication Bypass
- Access Control Issues
These are the bugs that actually pay and matter.
๐ Real-World Scenarios
Youโll commonly find this in:
- Network diagnostic tools (ping, traceroute)
- Admin panels
- Debug endpoints left in production
- IoT device interfaces
๐ก๏ธ Mitigation
โ Donโt do this
system("ping " . $_GET['name']);
โ Do this instead
- Use
escapeshellarg():
system("ping " . escapeshellarg($_GET['name']));
- Validate input strictly (allow only domains/IPs)
- Avoid shell calls entirely if possible
- Run services with least privilege
๐ Detection Tips
Look for:
- User input inside system commands
- Special characters (
;,&&,|, backticks) - Unexpected command output in responses
โก Advanced Notes
If output is not visible:
- Use blind techniques (time delays)
- Use out-of-band channels (DNS, HTTP callbacks)
๐งจ When & Why This Vulnerability Happens
When it appears
- User input is directly passed into system-level functions
- Developers build shell commands dynamically using concatenation
- Features like ping, traceroute, file handling, or diagnostics are exposed to users
- Legacy PHP apps or quick prototypes go into production without proper sanitization
Why it happens
- Trust boundary violation โ User input is treated as safe
- String concatenation โ Input becomes part of a shell command
- Shell metacharacters (
;,&&,|, backticks) get interpreted as control operators - Lack of input validation or output encoding
๐ The backend cannot distinguish between intended command and injected command
๐ก๏ธ Mitigation (Deep Dive)
1. Avoid Shell Calls Completely
Instead of:
system("ping " . $_GET['name']);
Use native functions or APIs wherever possible.
2. Escape User Input Properly
system("ping " . escapeshellarg($_GET['name']));
This ensures input is treated as a single argument, not executable code.
3. Strict Input Validation (Allowlist)
Allow only:
- Valid IP addresses
- Valid domain names
Reject everything else.
4. Drop Privileges
- Run web server as low-privileged user
- Restrict system command capabilities
Even if exploited โ limited impact
5. Disable Dangerous Functions (if possible)
In php.ini:
disable_functions = system, exec, shell_exec, passthru
6. Use Sandboxing / Containers
- Isolate execution environment
- Prevent lateral movement
7. Logging & Monitoring
- Detect unusual command patterns
- Alert on metacharacters in inputs
๐งฉ Key Takeaway
If user input reaches a shell โ assume command injection is possible.
This technique proves you donโt need file upload to get RCE โ sometimes the system hands it to you.