今日,针对Curl爆出的两个高危漏洞(CVE-2023- 38545、 CVE-2023-38546),安天攻防实验室对其进行分析跟进,提供检测方法和加固方法,安天将持续对该漏洞进行利用监测,提取相关特征,进行研究和监测。
今日,针对Curl爆出的两个高危漏洞(CVE-2023- 38545、 CVE-2023-38546),安天攻防实验室对其进行分析跟进,提供检测方法和加固方法,安天将持续对该漏洞进行利用监测,提取相关特征,进行研究和监测。
Curl是一个网络数据传输项目,通常说Curl是指Curl命令行工具,它支持DICT、FILE、FTP、FTPS、Gopher、HTTP、HTTPS、IMAP、IMAPS、LDAP、LDAPS、POP3、POP3S、RTMP、RTSP、SCP、SFTP、SMB、SMBS、SMTP、SMTPS、Telnet与TFTP等协议,而Curl的底层使用的是libcurl库,libcurl与Curl 组成了 cURL 项目。
Curl被广泛应用于应用功能组件和RPM依赖,Git、Rust、pycurl等均受此次高危漏洞影响,大多数操作系统同样集成libcurl,包括但不限于:Android、Chrome OS、Cisco IOS、iOS、ipadOS、Linux、macOS。
图片引用自github https://github.com/curl/curl/discussions/12026
Curl命令行工具作者bagder于10月11日06:00UTC发布8.4.0版本Curl,该版本Curl修复CVE-2023-38545、CVE-2023-38546两漏洞,由于该漏洞基于libcurl存在,影响范围巨大。同时发布者也确认,依赖libcurl的pycurl等同样受到影响。
图片引用自github https://github.com/curl/curl/discussions/12026
依据Curl发布的公告,本次漏洞主要源于SOCKS5的缓冲区溢出,在调用库的应用设置修改了较小的缓冲区大小或因服务器延迟原因都可能触发此漏洞。
1.1 影响范围
名称 |
版本号 |
libcurl |
7.69.0 <= libcurl < 8.4.0 |
1.2 漏洞成因
该漏洞主要成因是在使用SOCKS5代理链接过程中造成的堆溢出。当Curl使用 SOCKS5代理以便它解析地址时,主机名的最大长度为255字节。如果检测到主机名超过255字节,Curl将切换到本地主机解析地址,并将解析后的地址传递给代理。然而,由于程序bug,在建立延迟较高的 SOCKS5 链接过程中,此时主机解析地址可能会获取错误的值,此时会把过长的主机名也复制到缓冲区中。
主机名来自于提供给Curl解析的url。目标缓冲区是libcurl 中基于堆的下载缓冲区,缓冲区的默认大小为16kB,但可以由应用程序设置为不同的大小。Curl 工具默认将其设置为102400字节,但如果 --limit-rate 设置低于102400字节/秒,则会将缓冲区大小设置为较小的值。libcurl提供了CURLOPT_BUFFERSIZE 选项来更改下载缓冲区的大小。libcurl 在 URL 中接受最多达65535字节的主机名。
要发生溢出,需要一个足够慢的SOCKS5连接来触发局部变量bug,并且客户端使用的主机名长于下载缓冲区。通过恶意的 HTTPS 服务器进行重定向到一个特别设计的 URL。某些较老的服务器延迟可能足以触发此漏洞。堆溢出仅可能在未设置 CURLOPT_BUFFERSIZE 或将其设置为小于 65541的情况下发生。
1.3 漏洞复现
安天攻防实验室已复现CVE-2023-38545漏洞。
2.1 手动版本检测
2.1.1 Curl版本检测
Curl可通过命令直接检测版本。
curl --version |
2.1.2 libcurl版本检测
依赖libcurl的应用通常会在系统lib目录下以动态链接库形式存放,也可能被集成打包于应用目录下。版本对比检测方案通常有以下两个思路,对目录下的文件进行检测和对运行中进程打开的文件进行检测。
strings libcurl.so | egrep -o 'libcurl[ -/]([678]+.[0-9]+.[0-9]+)' |
lsof | egrep -o '/.*.so.*' | xargs -I {} bash -c "strings {} | egrep -o 'libcurl[ -/]([678]+.[0-9]+.[0-9]+)'" |
ldconfig -p | grep libcurl |
dpkg -l | grep libcurl |
通过下面的python脚本,可以输出Curl的版本信息和libcurl库的路径和版本信息,用于比对是否在漏洞影响范围。后续我们会对脚本进行完善,直接输出受影响的文件全路径。
import platform import subprocess import os def get_curl_version(): operating_system = platform.system().lower() if "windows" in operating_system: return get_windows_curl_version() elif "linux" in operating_system: return get_linux_curl_version() elif "darwin" in operating_system: return "NA" else: return "Unsupported operating system" def get_libcurl(): uname_output = subprocess.run(['uname', '-a'], capture_output=True, text=True) uname_output = uname_output.stdout.lower() if "linux" in uname_output: return get_linux_libcurl() elif "darwin" in uname_output: return get_macos_libcurl() else: return "Unsupported operating system" def get_windows_curl_version(): try: result = subprocess.run(['curl', '--version'], capture_output=True, text=True) lines = result.stdout.strip().splitlines() return lines[0] except FileNotFoundError: return "curl is not installed on Windows" def get_linux_curl_version(): try: result = subprocess.run(['curl', '--version'], capture_output=True, text=True) lines = result.stdout.strip().splitlines() return lines[0] except FileNotFoundError: |
2.1.3 相关第三方模块 libcurl版本检测
import pycurl print(pycurl.version) print(pycurl.__file__) 输出: windows: PycURL/7.43.0.5 libcurl/7.68.0 OpenSSL/1.1.1d zlib/1.2.11 c-ares/1.15.0 WinIDN libssh2/1.9.0 nghttp2/1.40.0 C:Python38libsite-packagespycurl.cp38-win_amd64.pyd linux: libcurl/7.29.0 NSS/3.53.1 zlib/1.2.7 libidn/1.28 libssh2/1.8.0 /usr/lib64/python2.7/site-packages/pycurl.so |
2.2 漏洞批量检测
2.2.1 批量检测方法1
检测逻辑:
通过罗列系统内所有的 curl工具和libcurl.dll文件的版本,方便进行版本比对,检测是否受漏洞影响。Windows/Linux平台,libcurl版本检测python脚本,Windows需搭配everyting软件,Linux 需配合自带命令使用。
使用说明:
1. 复制curl和libcurl的完整路径。
Windows:
在everything中搜索"curl.exe | libcurl.dll",选中需要检测的文件,右键->复制完整路径和文件名。
Linux:
输入以下命令复制结果。
sudo find / -name "curl" -o -name "*libcurl*" |
2. 打开path.txt,将复制的内容粘贴进去。
运行python curl_detect.py,输出curl和libcurl.dll的版本信息。
import re # 定义正则表达式模式 pattern = re.compile(r'([678]+.[0-9]+.[0-9]+)') # 从 path.txt 文件中读取文件路径 with open('path.txt', 'r') as path_file: for line in path_file: file_path = line.strip('"n').strip("'n") # 删除双引号、单引号、换行、空白 try: with open(file_path, 'r', encoding='ascii', errors='ignore') as file: contents = file.read() match = pattern.search(contents) if match: print(f"{file_path}n版本:{match.group(1)}") else: print(f"{file_path}n检测版本失败,请确认文件无误") except: print(f"{file_path}n检测版本失败,请确认路径及文件权限") |
2.2.2 批量检测方法2
检测逻辑:
在windows平台下,通过罗列系统内所有的curl.exe 、libcurl.lib和pycurl,进行版本比对,检测是否受漏洞影响。需搭配同目录下精简后的everything工具es.exe使用,其中-f参数为检测模式,默认全部检测(dll、exe、pycurl)。
import win32api import subprocess import pefile import argparse def is_16_bit_exe(file_path): with open(file_path, 'rb') as f: # Read the MZ header mz_header = f.read(2) # Check if it's a valid MZ header if mz_header != b'MZ': return False f.seek(0x3C) pe_header_addr = int.from_bytes(f.read(4), byteorder='little') return pe_header_addr < 1024 def run_command(cmd): try: process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, creationflags=subprocess.CREATE_NO_WINDOW) out, err = process.communicate() if process.returncode != 0: return None return out.decode(encoding="Gbk") except Exception as e: print(f"Error: {e}") return None def comparaV(v1): lower_bound = [7, 69, 0] upper_bound = [8, 4, 0] input_version = list(map(int, v1.split('.'))) return lower_bound <= input_version < upper_bound class EXE: def __init__(self) -> None: self.dllout = run_command("es.exe curl.exe") self.dllpath = self.dllout.splitlines() # splitlines()将字符串分割成行的列表 print(len(self.dllpath)) |
虽然上述两个漏洞单独对系统的影响有限,但基于如今攻击者通常利用多个漏洞的组合来实施攻击的严峻形势,对其可能造成损失并不能掉以轻心。安天高度关注软件供应链安全,建议用户积极使用代码安全检测工具进行软件物料清单分析,对自身使用的软件成分更加明晰化,主动发现和排查此类漏洞。
安天融川代码安全检测系统 Antiy SCS (以下简称“融川”)提供了组件成分分析(SCA)功能,用户可以通过上传源代码文件或制品文件,快速检查和分析组件清单和漏洞分布情况,及时检测、预防和修复漏洞,保障安全。
在此次Libcurl爆出高危漏洞的第一时间,融川即对客户相关程序进行了深度的组件成分分析与跟踪,及时发现了相关风险,并提供了安全防护措施,有效地保障了客户的相关资产安全,帮助客户业务免受本次漏洞事件的影响。(相关截图已进行脱敏)。
Vulnerabilities in curl 7.69.0
Ubuntu/Debian:
sudo apt-get update && sudo apt-get install curl |
sudo dnf upgrade curl |
CentOS/RedHat:
sudo yum update curl |
macOS:使用Homebrew安装最新版curl:
brew install curl |
/bin/bash -c “$(curl - fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)” |
echo ‘export PATH=”/usr/local/opt/curl/bin:$PATH”‘ >> ~/.bash_profile Source your updated ~/.bash_profile: .~/.bash_profile |
curl --version |
此外,官方给出的修复建议如下:
1. 勿将CURLPROXY_SOCKS5_HOSTNAME代理与curl一起使用
2. 勿将代理环境变量设置为socks5h://
原文始发于微信公众号(安天集团):Curl高危漏洞(CVE-2023-38545)分析报告及建议
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论