首页
课程
问答
CTF
社区
招聘
峰会
发现
排行榜
知识库
工具下载
看雪20年
看雪商城
证书查询
登录
注册
首页
社区
课程
招聘
发现
问答
CTF
排行榜
知识库
工具下载
峰会
看雪商城
证书查询
社区
WEB安全
发新帖
0
1
[原创]《邮件钓鱼攻防工程》Part 3:内容对抗——贝叶斯和NLP
发表于: 2026-7-11 22:26
2206
[原创]《邮件钓鱼攻防工程》Part 3:内容对抗——贝叶斯和NLP
毅种循环
2
2026-7-11 22:26
2206
> 本文是「邮件钓鱼攻防工程」系列的第三篇。前两篇解决了发信通道和反沙箱。但发信只是一部分,正文被网关过滤,前面的工作全白做。 > > 邮件能不能进网关,内容进网关之后能不能不进垃圾箱,这是两个完全不同的对抗维度。本篇拆邮件安全网关(SEG)最核心的内容检测逻辑:贝叶斯分类器和 NLP 语义引擎,以及工程上的规避思路。 --- 作者: 可惜夜 首发至公众号:Yofune安全研究 欢迎关注。 ## 0x01 对手模型:SEG 内容层的双层检测架构 国内和境外的环境差异直接影响内容对抗的策略选择。境外企业网络的主力 SEG 是 Microsoft Defender for Office 365 和 Proofpoint;国内环境更复杂,大型央企和金融机构普遍部署了国产邮件网关,安全厂商这类产品百花齐放,不一一例举。中小企业大量使用腾讯企业邮、阿里云企业邮,后端反垃圾接的是云端能力。 这些产品的内容检测架构大体一致,底层两层叠加:第一层是**贝叶斯概率层**,基于词袋模型,SpamAssassin 和 Rspamd 是最典型的开源实现,国产厂商基本在此之上做了中文语料的二次训练;第二层是**深度语义层**,国内有不少基于 BERT-base 的轻量检测模型,不详细展开,感兴趣的可以搜索关键字。两层检测**不是串联阻断**,而是评分加权合并。一封邮件贝叶斯层得分很低,但只要深度语义层捕捉到了钓鱼邮件特征,照样被拦。目标是让最终得分低于阈值,需要两层一起对抗。  #### SpamAssassin 的 Bayes 插件(`lib/Mail/SpamAssassin/Plugin/Bayes.pm`) **Token 化流程**(源码 `tokenize` 函数位于第 1134-1217 行,`_tokenize_line` 位于第 1219-1380 行): ```bash 原始文本 → 正则提取 → 最少3字符过滤 → SHA1哈希截取40位 → 停用词过滤 ``` Token 提取正则(`_tokenize_line` 函数内,行 1235-1240):  ```bash # 使用正则表达式提取Token:匹配ASCII单词、英文字符,以及多字节的UTF-8编码字符(用于支持中文等非ASCII文本) s{ ( [A-Za-z0-9,@*!_'"\$. -]+ | # 匹配常规ASCII词元 [\xC0-\xDF][\x80-\xBF] | # 匹配UTF-8双字节字符 [\xE0-\xEF][\x80-\xBF]{2} | # 匹配UTF-8三字节字符(包含常见中文字符) [\xF0-\xF4][\x80-\xBF]{3} | # 匹配UTF-8四字节字符 [\xA1-\xFF] ) | . } # 匹配ISO-8859等单字符或多字节边缘字符,其余未匹配的单个字符替换为空格 { defined $1 ? $1 : ' ' }xsge; ``` SHA1 哈希压缩为 40 位 Key(`tokenize` 函数内,行 1212): ```bash # 对提取出的Token计算SHA1值,并截取其哈希结果的最后5个字节(40位),作为统计数据库中存储的唯一键值 $tokens{substr(sha1($token), -5)} = $token if $token ne ''; ``` SpamAssassin 实现里有三个硬性设计边界值得利用。 **Token 计数上限**(行 250):  ```bash # 声明在对数似然比排序中参与评分合并计算的最大有效Token数量为150。超过该限制的弱特征Token将被舍弃。 use constant N_SIGNIFICANT_TOKENS => 150; ``` SpamAssassin 在计算贝叶斯分值时,会把分词拿到的所有 Token 按概率偏差(即该词有多偏向垃圾邮件或正常邮件)进行降序排列,最多只取前 150 个最明显的 Token 参与最终计算,超出 150 个的词直接丢弃。这个 150 的限制是代码里写死的硬性规定。 只要在正文里混入足够多(超过 150 个)的强 Ham 词(即正常业务往来中的高频词),就能把真正敏感的恶意词挤出这 150 个计分窗口,使其不参与最终评分。  **Robinson 平滑算法**(行 1644-1653,常量在 CombineChi.pm 第 47-50 行定义,`FW_S_CONSTANT = 0.030`,`FW_S_DOT_X = 0.538 * 0.030 = 0.01614`): ```bash # 1. 计算原始贝叶斯分类概率 my $prob = ($s * $nn) / ($n * $ns + $s * $nn); # 2. 如果启用了 Robinson 平滑算法(针对低频出现的 Token) if (USE_ROBINSON_FX_EQUATION_FOR_LOW_FREQS) { my $robn = $s + $n; # 该 Token 在所有样本中出现的文档总数 # 使用 Gary Robinson 的 f(w) 公式计算平滑后的概率: # P_smooth = (s * x + n * P_raw) / (s + n) $prob = ($Mail::SpamAssassin::Bayes::Combine::FW_S_DOT_X + ($robn * $prob)) / ($Mail::SpamAssassin::Bayes::Combine::FW_S_CONSTANT + $robn); } ``` robn 是词库里记录的该词总频次。塞入拼写奇怪的罕见词或生僻词,平滑公式会直接把它的概率拉回 0.5(代表无特征)。概率为 0.5 的词在排序时垫底,进不了 150 个评分窗口。所以,做正文稀释时,必须使用网关已经见过多次的常规商务词汇,不能胡乱生造冷门词。 **得分合并的数学核心**,在 CombineChi.pm(行 60-104):  ```bash # 1. 累加计算双假设 Fisher 对数概率 foreach my $prob (@$sortedref) { $S *= 1.0 - $prob; # 假设邮件为 Spam 的概率累乘因子 (1 - P(Spam|Token)) $H *= $prob; # 假设邮件为 Ham 的概率累乘因子 (P(Spam|Token)) # 浮点防下溢处理省略(使用 frexp 分解科学计数法) } $S = log($S) + $Sexp * LN2; # 计算假设 Spam 的对数似然 $H = log($H) + $Hexp * LN2; # 计算假设 Ham 的对数似然 # 2. 通过卡方逆累积分布函数 (chi2q) 转换为 p 值评分。 # 传入 $wc (即 $token_count) 代表自由度相关的半值参数,省略了重复的乘除2操作。 $S = 1.0 - chi2q(-2.0 * $S, $wc); $H = 1.0 - chi2q(-2.0 * $H, $wc); # 3. 将得分归一化到 [0, 1] 区间,作为最终贝叶斯概率分值 return (($S - $H) + 1.0) / 2.0; ``` Fisher 算法在数学上默认所有词相互独立。但实际邮件中,词语之间关联性非常强。塞入一整段连贯的商务文本,这些关联词会直接扭曲卡方统计的自由度计算,降低分类器判定的把握,反而容易触发误判放行。 #### Rspamd 的 Bayes 分类器(`src/libstat/classifiers/bayes.c`) 和 SpamAssassin 不同,Rspamd 使用的是 OSB(Optimal Score Based)算法。 它的一个核心特点是把单个词(Unigram)的权重设成了 0(行 215)。不管单个词有多敏感,它都不会直接影响最终分值,必须和相邻词语结合组成 Bigram(双词组)或 Trigram(三词组)窗口才会计分。 光堆砌单个单词没用,必须注入连贯的词组或完整的商务短语。在中文场景下,分词器如果把词切得太细,容易破坏 OSB 窗口的统计结构。 Rspamd 里的 Robinson 平滑通过 `PROB_COMBINE` 宏实现(行 217): ```bash // prob: 原始概率, cnt: Token出现总数, weight: Robinson平滑权重, assumed: 默认假设概率(通常为0.5) #define PROB_COMBINE(prob, cnt, weight, assumed) (((weight) * (assumed) + (cnt) * (prob)) / ((weight) + (cnt))) ``` 在 `bayes_classify_token` 函数(行 227-324)中被调用: ```bash // 计算 w w = (fw * total_count) / (1.0 + fw * total_count); // 平滑合并概率 bayes_spam_prob = PROB_COMBINE(spam_prob, total_count, w, 0.5); ``` ##### Rspamd 统计 Token 标志位定义(`src/libserver/word.h` 与 `src/libstat/tokenizers/tokenizers.c`) 分词阶段,Rspamd 会在 `src/libserver/word.h`(行 34-47)中为 Token 标记不同的 Flag,这些属性采用 bitmask 形式定义: | 标志名称 | 位偏移量 | 掩码实际值 | 安全对抗及分析含义 | | :-- | :-- | :-- | :-- | | `RSPAMD_STAT_TOKEN_FLAG_TEXT` | `1u << 0` | `0x01` | 纯文本内容提取的常规 Token | | `RSPAMD_STAT_TOKEN_FLAG_META` | `1u << 1` | `0x02` | 元数据或指令生成的 Token | | `RSPAMD_STAT_TOKEN_FLAG_LUA_META` | `1u << 2` | `0x04` | 由 Lua 规则接口动态产生的 Token | | `RSPAMD_STAT_TOKEN_FLAG_EXCEPTION` | `1u << 3` | `0x08` | 异常 Token(例如 URL 提取出的特征) | | `RSPAMD_STAT_TOKEN_FLAG_HEADER` | `1u << 4` | `0x10` | 邮件 Header 头部字段提取的 Token | | `RSPAMD_STAT_TOKEN_FLAG_UNIGRAM` | `1u << 5` | `0x20` | 单字/单词一元 Token 标志 | | `RSPAMD_STAT_TOKEN_FLAG_UTF` | `1u << 6` | `0x40` | UTF-8/Unicode 多字节文本 Token | | `RSPAMD_STAT_TOKEN_FLAG_NORMALISED` | `1u << 7` | `0x80` | ICU 库成功进行规范化转换的 Token | | `RSPAMD_STAT_TOKEN_FLAG_STEMMED` | `1u << 8` | `0x100` | 已成功执行词干提取转换的 Token | | `RSPAMD_STAT_TOKEN_FLAG_BROKEN_UNICODE` | `1u << 9` | `0x200` | Unicode 序列规范化失败或格式损坏。该标志会被用于将任务全局标志标记为 `RSPAMD_TASK_FLAG_BAD_UNICODE`,但不会在 Bayes 概率计算中对 Token 权重进行“降权 50%”的操作。 | | `RSPAMD_STAT_TOKEN_FLAG_STOP_WORD` | `1u << 10` | `0x400` | 识别为高频中性的停用词 | | `RSPAMD_STAT_TOKEN_FLAG_SKIPPED` | `1u << 11` | `0x800` | 属于被衰减或跳过的 Token,不参与评分计算 | | `RSPAMD_STAT_TOKEN_FLAG_INVISIBLE_SPACES` | `1u << 12` | `0x1000` | 包含不可见字符的 Token | | `RSPAMD_STAT_TOKEN_FLAG_EMOJI` | `1u << 13` | `0x2000` | 包含 Emoji 表情符号的 Token | `BROKEN_UNICODE` 和 `INVISIBLE_SPACES` 是判断是否存在异常绕过行为的重要技术线索。若邮件中包含大量非规范 Unicode 或隐藏格式,容易触发网关的异常拦截逻辑。 ##### 词干提取与自定义分词(`tokenizers.c` 约第 600-650 行) 词干提取(Stemming)会消除单词变形的影响,例如 `"approved"` 与 `"approves"` 会归并为相同的词干 `"approv"`。这虽然限制了通过同词变形刷计数的做法,但也意味着如果注入大量 `"unanimously"`,等于在全局给 `"unanim"` 这一族词干刷了强烈的 Ham 信誉。在中文或日文的实际部署中,如果网关引入了自定义的中文分词器,需要摸清其词典边界,OOV的打散退化往往会减弱稀释效果。 所有 Token 在生成时都会计算 Mum-hash 用于 Redis 端的去重。即使使用等价 Unicode 字符替换,哈希值的改变也会使其被当作新词统计。 ##### 自动学习决策(`lualib/lua_bayes_learn.lua`,行 184、368) 在 `can_learn()` 逻辑中,Rspamd 设置了自适应防过拟合的保护机制。默认的置信度阈值为 `min_prob = 0.95`: ```bash -- 判断当前邮件的贝叶斯分类置信度是否已经达到阈值(默认为0.95) in_class = prob >= (probability_opts.min_prob or probability_opts.spam_min or 0.95) if in_class then -- 若系统已经足够确信,则拒绝进一步将其加入训练库中,以防止模型过拟合 return false, reason, ctx.result end ``` 如果稀释文本成功将评分卡在拦截线以下,且置信度未达到 0.95,则分类器既不会拦截该邮件,也无法从中学习到最新的特征漂移,从而提供了一个稳定的绕过时间窗口。  #### Rspamd 的神经网络插件(`src/plugins/lua/neural.lua`) 除了贝叶斯层,Rspamd 默认启用了 ANN(神经网络)分类插件。 其后置过滤器回调 `ann_scores_filter`(源码约在 121 行)在贝叶斯分类器**之后**执行。这意味着神经网络看到的特征已经经过了贝叶斯层的预处理。 特征提取依赖以下五个 Provider 接口(源码第 33-37 行): ```bash -- 动态加载这五个特征提供者模块 pcall(require, "plugins/neural/providers/llm") -- 外部LLM嵌入特征 pcall(require, "plugins/neural/providers/symbols") -- 规则得分缓存收集 pcall(require, "plugins/neural/providers/text_hash") -- 局部特征哈希 pcall(require, "plugins/neural/providers/fasttext_embed") -- FastText 词嵌入 pcall(require, "plugins/neural/providers/static_embed") -- 静态词嵌入 ``` 在生产环境中,通常仅启用 `symbols` 和 `text_hash`。 在 Hybrid特征提取模式下,神经网络把贝叶斯的打分直接当做特征输入的一部分。贝叶斯分数被稀释词干扰降下来后,这个偏低的分数被神经网络直接吃进去。神经网络虽然学到了”低贝叶斯分 = Ham”,但它无法区分这封信是因为干净还是被掺了沙子。 网关串行审计架构在这里存在盲区。 网关开启了 PCA 特征降维时,多封邮件里注入的相似良性文本被当作主成分保留,而原本维度较低的恶意敏感词特征反而容易在降维过程中被过滤掉,导致神经网络失效。 权重继承机制(行 1452)通过 Redis 的 zset 查找 `providers_digest` 匹配的旧 profile 并复制权重,避免在配置更新时重新训练。 五个 Provider 绝大部分仍然依赖对 Token 流的切分。一旦贝叶斯层削弱了 Token 的区分力,神经网络所接收的输入特征也会随之失效。 #### Rspamd LLM Provider 的底层细节(`llm.lua`) 在 LLM Provider 的工程设计中,有两个机制值得关注: **拼装输入文本**:`collect_async` 中,输入文本强制按**主题优先**(Subject first)原则拼接: ```bash "Subject: " + 邮件主题 + "\n" + 正文内容 ``` 确保在嵌入向量的位置编码中,高信息价值的主题行始终被置于最前,避免因长文本截断而丢失关键信息。 **路由与缓存**:该插件支持根据邮件检测语言路由到不同的第三方模型,且使用了 Redis 进行本地缓存(TTL 默认 24 小时): Redis 缓存机制引入了新的规避面。已知目标网关开启了该缓存时,可以提前发送一封内容正常的良性邮件(使用特定主题词),让网关缓存下该特征。后续发送带有相同主题词的邮件即可命中该干净缓存,绕过实时审计。 #### SpamAssassin 的独立神经网络插件(`NeuralNetwork.pm`) SpamAssassin 的 NeuralNetwork 插件(v0.11.2)走另一条路:不依赖贝叶斯分,而是维护自己独立的词汇表与特征流水线。 **隐藏层结构**(源码第 767-770 行、第 1327-1330 行): ```bash # 隐藏层1节点数计算:≈ √输入维度 × 0.25 (向上取整) my $num_hidden1 = int(sqrt($num_input) * 0.25 + 0.5); $num_hidden1 = 4 if $num_hidden1 < 4; # 最少4个节点 # 隐藏层2节点数计算:为隐藏层1节点数的一半 my $num_hidden2 = int($num_hidden1 / 2); $num_hidden2 = 2 if $num_hidden2 < 2; # 最少2个节点 ``` 输入层映射至该双隐层结构,并在单输出神经元输出结果。 **词表修剪卡方计算**(`_chi2_score`,行 1065): ```bash # 计算特定词项(term)的卡方得分,用于过滤全局区分度弱的特征词 sub _chi2_score { my ($spam, $ham, $total_spam, $total_ham) = @_; my $total = $total_spam + $total_ham; return 0 unless $total > 0; my $total_spam_noterm = $total_spam - $spam; # 未包含该词的Spam文档数 my $total_ham_noterm = $total_ham - $ham; # 未包含该词的Ham文档数 # 分母为各维频数的乘积 my $denom = ($spam+$ham) * ($total-$spam-$ham) * $total_spam * $total_ham; return 0 unless $denom > 0; # 卡方检验矩阵交叉相乘平方差计算,提取鉴别度分值 return ($total * ($spam*$total_ham_noterm - $ham*$total_spam_noterm)**2) / $denom; } ``` 在词汇表达到 10,000 的上限进行清理时,其卡方算法偏向于删除低频但有高特异性的词,而保留高频的中性词。使用高信誉的常规商务词汇进行稀释,它们不容易在词汇表清理中被剔除。 **类别加权训练**(行 817-825): ```bash # 根据训练样本中Spam与Ham的文档比例,为少数类乘以一个反比权重,最大加权值为4.0倍 if ($isspam) { $class_weight = ($spam_docs > 0) ? $ham_docs / $spam_docs : 1.0; } else { $class_weight = ($ham_docs > 0) ? $spam_docs / $ham_docs : 1.0; } $class_weight = 1.0 if $class_weight < 1.0; $class_weight = 4.0 if $class_weight > 4.0; my $weighted_epochs = int($train_epochs * $class_weight) || 1; ``` 大量发送被标记为 Ham 的稀释邮件,会稀释掉 ham\_docs/spam\_docs 的权重比例,直接把整个模型的权重偏向有利于 Ham 判定的方向。 在重训计算”类原型向量”时,一段周期内持续发送含有良性术语的稀释信,这些词录入词表后直接毒化类原型向量,在重训后整体带偏神经网络的判断基准。 SpamAssassin 神经网络插件有四道硬性检测门槛:邮件长度小于 256 字符,或命中词汇表的有效词少于 10 个时,系统直接跳过神经网络检测,退回到贝叶斯层。 正文中把可见字符控制在 200~250 字符(大约 3、4 句话),然后将大段的稀释语料通过 CSS 隐藏(不可见语料不计入正文字数),神经网络就会因为有效字数不足而直接放弃检测,退回贝叶斯层,此时隐藏稀释词已经绕过了它。 #### 其他方案对比:无原生 ML 的 SMTP 架构 Haraka(Node.js 开发)的内容检测插件不含原生 ML/NLP 组件,只做外部 Rspamd/SpamAssassin 接口转发,或者用 karma 等插件按硬编码规则对信誉、SPF 状态做加减分。自建 Node.js 邮件网关在这块很脆弱——绕过外部检测器之后,本地几乎没有防御。yangdongchao/mailscanner 这类 PyTorch 学术分类器就更不用说了,完全没考虑工程对抗。 --- ## 0x02 维度一:HTML 多态变异 网关审计 HTML 时,通常会将其解析为 DOM 树并计算指纹(如 Fuzzy Hash)。短时间内发送的多封邮件在 DOM 树特征上相似度过高,就会被判定为已知模板的变种。 对抗方法:生成 HTML 时对每个收件人的邮件单独做变异编译,用多态方式扰乱 DOM 特征。 ### 2.1 结构注入(Structural Injection) 编译引擎会在 DOM 树结构中动态引入以下变异: - • **随机嵌套**:在 `<body>` 路径下随机引入 1~3 层无样式的 `<div>` / `<span>` 嵌套,其 class 类名完全动态随机生成。 - • **空节点引入**:随机插入多个 `display:none` 占位符。视觉上不可见,但会影响 DOM 解析树的深度和兄弟节点计数,直接改变特征 Hash 值。 - • **属性顺序置乱**:在生成 HTML 元素时,随机打乱各标签属性的输出顺序(例如将 href, style, class 顺序倒置)。许多 DOM 解析器是顺序敏感的,这会改变网关的 Hash 指纹。 ### 2.2 等效标签置换(Tag Normalization Bypass) 编译引擎结合转换映射,随机置换等效标签: | 原始标签 | 变异标签 | NLP 解析差异 | | :-- | :-- | :-- | | `<b>` | `<strong>` | 语义标签 vs 样式标签 | | `<i>` | `<em>` | 同上 | | `<strike>` | `<s>` / `<del>` | 新旧语法标准混杂 | | `<center>` | `<div style="text-align:center">` | 标签 vs CSS 样式 | | `<font>` | `<span style="...">` | 传统样式 vs CSS 样式 | 每次生成以 50% 的概率随机置换,破坏基于标签分布的特征词频统计。 ### 2.3 随机 CSS 格式化 模板里的类名均采用随机字符代替,同时内联 CSS 样式的属性格式也随机选择: ```bash /* 格式一 — 十六进制 */ color: #ff0000; margin: 10px; /* 格式二 — rgb函数 */ color: rgb(255, 0, 0); margin: 10px 10px 10px 10px; /* 格式三 — hsl简写 */ color: hsl(0, 100%, 50%); margin: 10px; ``` 网关提取 CSS 的正则过滤规则因此无法成功匹配。 --- ## 0x03 维度二:语义稀释——拉低贝叶斯评分 语义稀释的数学原理是通过在正文引入大量的强 Ham 词,来拉低贝叶斯联合概率分值,让原本超标的分数降到网关拦截线以下。但工程落地中需要考虑这些稀释词的注入方式,以对抗网关的可见性检测。 ### 3.1 数学原理 贝叶斯的代数加和公式为: 一封包含”立即登录”、”验证账号”等 10~15 个强敏感词的钓鱼邮件,判定值容易突破 +60(网关拦截线通常为 +40)。 不修改原有核心文案,通过在正文中注入大量强 Ham Token(每个词贡献 -2 至 -5 的得分),将联合分数拉低: 当 Misplaced & 时,系统会自动将该邮件归为 Ham 类别。 根据工程实践,稀释注水词量的注入公式为: TaiGong 设置了三档注水等级: | 级别 | 注水比例 (DilutionRatio) | 适用场景 | | :-- | --: | :-- | | Light | 2.0 | 对付消费级邮(Gmail / Outlook) | | Standard | 5.0 | 对付企业 邮服环境 | | Aggressive | 10.0 | 高防目标(金融、央企) |  ### 3.2 七种文本注入手段 按检测难度从低到高排列: **[#1](javascript:;) HTML 注释区** ```bash <!-- quarterly budget review meeting scheduled for next Thursday --> ``` HTML 注释区注入最基础——直接把词写在 `<!-- -->` 里。现代网关分词时一般会自动过滤注释,只对极少数老旧系统有效。 **[#2](javascript:;) 同色极小字体** ```bash <span style="font-size:1px;color:#ffffff">budget allocation approved</span> ``` 用 CSS 把字体设成 1px、颜色设成与背景相同。简单网关上有效,但带可见字符占比审计的高级网关会触发惩罚。 **[#3](javascript:;) overflow:hidden 与零高度容器** ```bash <div style="height:0;overflow:hidden;max-height:0;opacity:0"> team meeting scheduled for Thursday </div> ``` `overflow:hidden` 配合零高度容器(`height:0; max-height:0; opacity:0`),比单一隐藏样式更稳定,不同环境下表现一致。 **[#4](javascript:;) ARIA 语义隐藏** ```bash <span aria-hidden="true" role="presentation" style="position:absolute;left:-9999px"> project milestone review </span> ``` ARIA 无障碍属性也能用来隐藏:`aria-hidden="true" role="presentation"` 配合 `left:-9999px` 绝对定位,读屏器会跳过这段内容,但直接提取文本的网关引擎照读不误。 **[#5](javascript:;) mime multipart/alternative 差异注入**复合格式邮件走 `multipart/alternative` 结构:`text/plain` 放良性长文本,HTML 放实际内容。网关为了性能往往初筛只扫 plain 部分——第一轮评分就这样拉下来了。 **[#6](javascript:;) CSS 伪元素 **`content`** 注入** ```bash <style> .d1::after { content: "budget allocation quarterly review"; } .d2::before { content: "team meeting scheduled for Thursday afternoon"; } </style> <div class="d1"></div> <div class="d2"></div> ``` CSS 伪元素 `::before` / `::after` 注入则更难检测。稀释内容写入样式表的 `content` 属性,普通文本提取器只读 DOM textContent,读不到 CSSOM 的计算值。 **[#7](javascript:;) JavaScript 动态延时渲染** ```bash <div id="dilution_container" style="display:none">...</div> <script> setTimeout(function() { document.getElementById('dilution_container').style.display = 'block'; }, 5000); </script> ``` JavaScript 延时渲染是检测难度天花板。容器初始状态设为隐藏,JS 延时数秒后再改为显示,网关一般不会等待 JS 执行完毕,扫描时这部分词被忽略,用户端依然可以渲染。 ### 3.3 语料库筛选 语料库分三层: - • **Layer 1 — 通用商务(基础 500条)**:全是项目审批、会议通知等纯商业文案(比如“本季度财务预算已经提交审阅”)。 - • **Layer 2 — 行业特异(约 200条)**:根据每个行业所接触的邮件预料不同而塞入不同的词组进行干扰,因为目标行业的网关本就会经常放行这类词,把它们视为极高 Ham 概率特征。 - • **Layer 3 — 动态生成**:调用 LLM 获取当天或本周的商业、时政热点,组装成和发信场景匹配的模板,也许能绕过网关的缓存名单? **Token 筛选准则**:SpamAssassin 分值为负、长度超 5 字符、不带任何 URL 链接,三个条件缺一不可。 --- ## 0x04 未完成的维度三:HTML5 Smuggling 流量层绕过 绕过网关内容过滤后,进一步投送可执行程序(Cobalt Strike 载payload)时,还需要解决网络流量和附件特征的检测问题。 HTML5 Smuggling 提供了流量层免杀的思路:让文件在受害者本地的浏览器内存中生成,而不是直接在网络上传输。 暂时没有找到好的思路实现这一目标,目前来说这只是一个设想,因此也不过多套困了,具体的思路可以搜索相关关键词。 ### 4.1 落地页上的对抗 TaiGong 实战中,目前只是语义稀释配合落地页一起用。 效果不算很好,究极的理想状态就是我说的:受害者点击链接进入落地页后,后台执行 Smuggling ,同时往网关塞入大量良性商务免责声明等 Ham 文本,能够有效阻挡安全策略对 URL 的爬行和标记就如愿了。 --- ## 0x05 结语 从开源产品来看,策略应该都是大同小异的,就是不清楚闭源设备有LLM的参与之后,进化会到何种地步。 更根本的防线在终端上。 --- *参考资料:* - • \_Proofpoint: Introduction to HTML Smuggling, \_<mark class="encrypted">386K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2H3M7X3!0G2k6Y4m8G2K9h3&6@1i4K6u0W2j5$3!0E0i4K6u0r3N6i4y4Q4x3V1k6T1L8r3!0Y4i4K6u0r3N6r3S2J5k6h3q4@1i4K6u0V1K9h3&6K6K9h3N6Z5N6q4)9J5c8X3W2F1N6s2u0G2k6s2g2U0N6r3W2G2L8W2)9J5k6r3S2@1L8h3I4Q4x3X3c8K6L8i4g2Y4k6$3I4A6L8X3M7`.</mark> - • \_Proofpoint: HTML Smuggling Evolves - Threat Actor Adoption and Detection, \_<mark class="encrypted">978K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2H3M7X3!0G2k6Y4m8G2K9h3&6@1i4K6u0W2j5$3!0E0i4K6u0r3N6i4y4Q4x3V1k6T1L8r3!0Y4i4K6u0r3N6r3S2J5k6h3q4@1i4K6u0V1K9h3&6K6K9h3N6Z5N6q4)9J5c8X3S2@1L8h3I4Q4x3X3c8K6L8i4g2Y4k6$3I4A6L8X3N6Q4x3X3c8W2N6X3!0D9N6X3g2K6</mark> - • \_SpamAssassin Bayes Scoring Documentation, \_<mark class="encrypted">839K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6U0N6$3W2C8K9g2)9J5k6h3q4H3j5h3y4Z5k6g2)9J5k6h3!0J5k6#2)9J5c8X3y4G2L8X3k6D9N6h3g2F1j5$3g2Q4x3V1k6V1K9i4y4H3L8r3q4&6i4K6u0r3f1#2m8m8e0f1q4e0f1@1q4e0f1@1W2z5i4K6u0r3b7X3q4&6k6i4x3`.</mark> - • \_Rspamd Documentation: Statistics and Bayes, \_<mark class="encrypted">70bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3X3g2U0L8$3#2Q4x3V1k6V1L8$3y4Q4x3V1k6U0L8$3&6X3K9h3N6#2M7X3q4@1K9h3!0F1i4K6u0r3M7%4c8S2N6r3W2K6N6r3W2U0i4K6u0W2K9s2c8E0L8l9`.`.</mark> - • \_Microsoft 365 Defender Anti-Phishing Policy Reference, \_<mark class="encrypted">1dbK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6D9k6h3q4J5L8W2)9J5k6h3#2A6j5%4u0G2M7$3!0X3N6q4)9J5k6h3y4G2L8g2)9J5c8X3g2F1i4K6u0V1N6i4y4Q4x3V1k6V1k6h3k6W2L8X3c8W2M7W2)9J5k6r3!0X3k6X3W2U0k6g2)9J5k6o6x3$3y4g2)9J5c8X3q4F1N6r3W2Q4x3X3c8H3K9r3W2K6K9r3W2F1k6#2)9J5k6s2m8G2L8r3W2U0K9h3g2K6i4K6u0V1j5h3u0G2N6i4b7`.</mark> - • \_IcedID Banking Trojan Leveraging HTML Smuggling (2021), \_<mark class="encrypted">122K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6%4N6%4N6Q4x3X3g2E0j5$3q4X3k6h3g2Q4x3X3g2U0L8$3#2Q4x3V1k6T1L8r3!0Y4M7#2)9J5c8X3!0@1K9r3g2J5i4K6u0V1j5X3I4G2k6%4y4Q4x3V1k6E0j5$3q4X3k6h3g2Q4x3X3c8D9j5h3u0K6i4K6u0r3K9h3y4W2k6r3W2V1i4K6u0V1j5X3q4F1K9$3W2F1k6#2)9J5k6s2c8J5L8$3A6S2L8W2)9J5k6s2g2K6k6i4y4Q4x3X3c8Z5N6r3#2D9i4K6u0V1M7$3#2#2k6$3N6D9K9h3&6Y4i4K6u0V1N6r3g2U0K9r3&6A6M7i4g2W2i4K6u0r3</mark> - • \_SpamAssassin Bayes Plugin source\_<mark class="encrypted">4daK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6S2M7r3q4U0K9r3g2Q4x3V1k6K6M7r3q4E0j5i4y4K6j5i4y4K6K9h3&6Q4x3V1k6T1L8r3!0T1i4K6u0r3N6s2u0#2L8X3E0Q4x3V1k6D9K9h3u0Q4x3V1k6y4j5h3W2D9i4K6u0r3f1%4m8S2L8f1q4K6M7$3q4K6M7$3W2F1i4K6u0r3f1r3I4#2k6$3W2F1i4K6u0r3b7X3q4&6k6i4y4Q4x3X3g2H3L8b7`.`.</mark> - • \_SpamAssassin CombineChi source: \_<mark class="encrypted">468K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6S2M7r3q4U0K9r3g2Q4x3V1k6K6M7r3q4E0j5i4y4K6j5i4y4K6K9h3&6Q4x3V1k6T1L8r3!0T1i4K6u0r3N6s2u0#2L8X3E0Q4x3V1k6D9K9h3u0Q4x3V1k6y4j5h3W2D9i4K6u0r3f1%4m8S2L8f1q4K6M7$3q4K6M7$3W2F1i4K6u0r3b7X3q4&6k6i4y4Q4x3V1k6o6L8$3#2T1K9h3&6W2b7$3S2A6i4K6u0W2M7r3@1`.</mark> - • \_Rspamd Bayes classifier source: \_<mark class="encrypted">020K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4K6N6r3g2J5i4K6u0r3M7%4u0U0i4K6u0r3L8r3W2T1M7%4c8S2N6q4)9J5c8X3y4D9j5i4y4K6K9h3k6A6k6i4u0K6i4K6u0r3j5X3q4&6k6i4y4Q4x3X3g2U0</mark> - • \_Rspamd Neural Network plugin source: \_<mark class="encrypted">997K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4K6N6r3g2J5i4K6u0r3M7%4u0U0i4K6u0r3M7r3I4#2k6$3W2F1M7#2)9J5c8X3I4#2j5g2)9J5c8X3&6W2N6i4u0S2L8q4)9J5k6h3I4#2j5b7`.`.</mark> - • \_Rspamd Neural Network providers (LLM): \_<mark class="encrypted">466K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4K6N6r3g2J5i4K6u0r3L8s2g2S2L8r3W2T1i4K6u0r3M7r3I4#2k6$3W2F1M7#2)9J5c8X3&6W2N6i4u0S2L8q4)9J5c8Y4m8J5L8%4k6A6k6r3g2J5M7#2)9J5c8X3I4D9L8g2)9J5k6h3I4#2j5b7`.`.</mark> - • \_Rspamd Tokenizer source: \_<mark class="encrypted">ebeK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4K6N6r3g2J5i4K6u0r3M7%4u0U0i4K6u0r3L8r3W2T1M7%4c8S2N6q4)9J5c8Y4c8G2K9$3g2F1K9i4A6W2M7Y4y4Q4x3V1k6@1L8$3E0W2L8X3W2*7k6i4u0K6i4K6u0W2j5H3`.`.</mark> - • \_Rspamd Bayes autolearn: \_<mark class="encrypted">32bK9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6J5M7%4m8S2L8h3c8Q4x3V1k6T1L8r3!0T1i4K6u0r3L8h3q4K6N6r3g2J5i4K6u0r3L8s2g2S2L8r3W2T1i4K6u0r3L8s2g2S2i4K6g2o6i4K6g2X3j5X3q4&6k6i4y4Q4y4f1y4Q4y4h3k6D9k6h3q4J5L8W2)9J5k6h3I4#2j5b7`.`.</mark> - • \_SpamAssassin NeuralNetwork Plugin source: \_<mark class="encrypted">004K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6S2M7r3q4U0K9r3g2Q4x3V1k6K6M7r3q4E0j5i4y4K6j5i4y4K6K9h3&6Q4x3V1k6T1L8r3!0T1i4K6u0r3N6s2u0#2L8X3E0Q4x3V1k6D9K9h3u0Q4x3V1k6y4j5h3W2D9i4K6u0r3f1%4m8S2L8f1q4K6M7$3q4K6M7$3W2F1i4K6u0r3f1r3I4#2k6$3W2F1i4K6u0r3e0X3g2#2M7X3q4D9e0X3g2@1N6$3!0J5K9#2)9J5k6i4m8E0</mark> - • \_Haraka Plugin Ecosystem: \_<mark class="encrypted">bb1K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6Z5j5i4u0S2K9$3q4Q4x3V1k6t1j5i4u0S2K9$3p5`.</mark> - • \_yangdongchao/mailscanner (Python ML): \_<mark class="encrypted">987K9s2c8@1M7s2y4Q4x3@1q4Q4x3V1k6Q4x3V1k6Y4K9i4c8Z5N6h3u0Q4x3X3g2U0L8$3#2Q4x3V1k6&6j5h3&6Y4k6r3!0F1k6$3y4Z5j5h3!0Q4x3V1k6E0j5h3W2D9M7$3y4S2L8X3&6W2M7R3`.`.</mark>
冰与火的战歌:Windows内核攻防实战高级班!从零到实战,融合AI与Windows内核攻防全技术栈,打造具备自动化能力的内核开发高手。
收藏
・
0
点赞
・
1
打赏
分享
分享到微信
分享到QQ
分享到微博
赞赏记录
参与人
雪币
留言
时间
wx_晨梦
感谢你分享这么好的资源!
2026-7-16 07:59
查看更多
赞赏
×
1 雪花
5 雪花
10 雪花
20 雪花
50 雪花
80 雪花
100 雪花
150 雪花
200 雪花
支付方式:
微信支付
赞赏留言:
快捷留言
感谢分享~
精品文章~
原创内容~
精彩转帖~
助人为乐~
感谢分享~
最新回复
(
0
)
游客
登录
|
注册
方可回帖
回帖
表情
雪币赚取及消费
高级回复
返回
毅种循环
2
21
发帖
69
回帖
140
RANK
关注
私信
他的文章
[原创]《邮件钓鱼攻防工程》Part 3:内容对抗——贝叶斯和NLP
2206
[原创]《邮件钓鱼攻防工程》Part 2:构建不可溯源的基础设施
2571
[原创]《邮件钓鱼攻防工程》Part 1:从 GoPhish 的天花板谈起
1670
[建议]test建议删除
1971
[原创] 红队视角下的AzureAD
2608
关于我们
联系我们
企业服务
看雪公众号
专注于PC、移动、智能设备安全研究及逆向工程的开发者社区
看原图
赞赏
×
雪币:
+
留言:
快捷留言
为你点赞!
返回
顶部