1、这个缺陷使得curl在SOCKS5代理握手时导致一个基于堆的缓冲区溢出。
2、当 curl 被要求将主机名传递给 SOCKS5 代理以允许代理解析地址而不是由 curl 本身完成时,主机名的最大长度可以是 255 字节。
3、如果检测到主机名长度超过 255 字节,则 curl 将切换到本地名称解析,并将解析的地址传递给代理。由于一个错误,”让主机解析名称“的局部变量可能会在缓慢的 SOCKS5 握手过程中获得错误的值,将太长的主机名复制到目标缓冲区,而不是在复制已解析的地址。
2.1 影响范围
受影响的版本:libcurl 7.69.0 至 8.3.0(含 8.3.0)2.2 官方更新
从 curl 8.4.0 开始,如果名称太长,curl 不再切换到本地解析模式,而是正确地返回错误。补丁下载地址:https://curl.se/docs/CVE-2023-38545_patches.zip
根据补丁分析,成因在于hostname长度大于255时,memcpy拷贝主机名的时候,那么我们找到对应的代码:1、主机名hostname长度大于255时,会进行本地解析3、本地解析失败后,会进行远程解析,当主机名超长时,memcpy拷贝时超过socksreq的大小,造成堆溢出。
4.1 系统环境
系统为Ubuntu 20.04 64位系统,安装需要的依赖
sudo apt install make gdb gcc git checksec
|
4.2 运行代理服务
参考hatboy师傅的python版本的socks5服务端代码,保存其中“不需要认证的socks5服务器“代码为socks.py,端口这里设置为1080:
from socketserver import StreamRequestHandler, ThreadingTCPServerclass SocksProxy(StreamRequestHandler): print('Accepting connection from {}'.format(self.client_address)) header = self.connection.recv(2) version, nmethods = struct.unpack("!BB", header) # 设置socks5协议,METHODS字段的数目大于0 assert version == SOCKS_VERSION methods = self.get_available_methods(nmethods) if 0 not in set(methods): self.server.close_request(self.request) self.connection.sendall(struct.pack("!BB", SOCKS_VERSION, 0)) version, cmd, _, address_type = struct.
|