如何拒绝 base64 编码的垃圾邮件?

use*_*969 12 postfix spam

我刚刚收到几封内容相似的邮件,这些邮件是用 base64 编码的。现在我想使用正文检查拒绝或丢弃此类电子邮件。

在我的 body_checks 中有这样的东西之前:

/Quanzhoucooway/ DISCARD
Run Code Online (Sandbox Code Playgroud)

但由于消息已编码,因此不会检测到该关键字。

这是一个 base64 编码的消息:

DQpIaSBGcmllbmRzLA0KDQpHb29kIGRheSENCg0KVGhpcyBpcyBWaWN0b3JpYSBmcm9tIFF1YW56
aG91Y29vd2F5IHNob2VzIHRyYWRpbmcgY28uLGx0ZCwgYSBwcm9mZXNzaW9uYWxtYW51ZmFjdHVy
ZXIgYW5kIGV4cG9ydGVyIG9mIGFsbCBraW5kcyBvZiBzaG9lcywgbWFpbmx5IGluIGNhc3VhbCBz
aG9lcyBhbmQgc3BvcnRzIHNob2VzICwgd2hpY2ggaGFzIGJlZW4gc3VwcGxpZWQgdG8gdGhlIGZh
bW91cyBmYXNoaW9uIGJyYW5kIHN0b3JlcyBmcm9tIDIwMTAuDQoNCk5vdGljaW5ndGhhdCB5b3Ug
YXJlIGxvb2tpbmcgZm9yIGhpZ2ggcXVhbGl0eSBmYXNoaW9uIHNob2VzLCBzbyBJIGhvcGUgd2Ug
Y2FuIHdvcmsgdG9nZXRoZXIgaW4gdGhlIGZ1dHVyZS4gSWYgeW91IGFyZSBpbnRlcmVzdGVkLCBJ
IHdpbGwgc2VuZCB5b3Ugb3VyIGl0ZW1zIGFjY29yZGluZ2x5Lg0KDQpGWUksIHdlIGNhbiBtYWtl
IGN1c3RvbWl6ZWQgc2FtcGxlcyBmb3IgeW91IGFjY29yZGluZ2x5Lg0KDQpMb29raW5nIGZvciB5
b3VyIHNvb25lc3QgcmVzcG9uc2UuDQoNCkJSIQ0KDQpWaWN0b3JpYSANCg==
Run Code Online (Sandbox Code Playgroud)

那么阻止此类电子邮件的最佳做法是什么?

Esa*_*nen 19

不要使用 Postfix 执行此操作,body_check而是为它编写 Spamassassin 规则。Spamassain 在应用其规则之前对邮件正文进行解码。就像是:

body     LOCAL_QUANZHOUCOOWAY  /Quanzhoucooway/
score    LOCAL_QUANZHOUCOOWAY  7.0
describe LOCAL_QUANZHOUCOOWAY  Block word Quanzhoucooway
Run Code Online (Sandbox Code Playgroud)

这些规则属于/etc/mail/spamassassin/local.cf(或~/.spamassassin/user_prefs)。

  • 是的。有人已经编辑了我的答案以澄清这一点。感谢那个匿名的人!:) (2认同)

Ilm*_*nen 10

从技术上讲,您可以直接过滤关键字的 base64 编码数据。鉴于存在更好和更简单的替代方案(如上面 Esa 的回答中所述),我并不是说这是一项实用或合理的做法,但这可能的。

诀窍是要意识到base64 编码是将原始未编码数据的 3 字节块确定性映射到 4 个字符的 base64 字符块。因此,任何时候在未编码数据中出现特定的 3 字节块序列时,相同的 4 字符块序列将出现在编码版本中。

例如,如果您输入的字符串Quanzhoucooway的base64编码器,你会得到输出UXVhbnpob3Vjb293YXk=。由于输入的长度不是 3 个字节的倍数,因此输出在末尾包含一些填充,但是如果我们去掉最后的=符号和最后一个实际的 base64 字符k(因为它还编码了一些填充位),我们得到了字符串UXVhbnpob3Vjb293YX这是保证出现在base64编码数据每当字节三胞胎Quanzhoucoow和部分三重态ay出现在以该顺序输入。

但是,当然,字符串Quanzhoucooway可能不会恰好在三元组边界上开始。例如,如果我们对字符串进行编码,则会XQuanzhoucooway得到WFF1YW56aG91Y29vd2F5看起来完全不同的输出。这一次,输入长度是由三个整除,所以没有填充字符在最后放弃,但我们确实需要丢弃前两个字符(WF),每个编码一些来自预谋位的X字节,留给我们F1YW56aG91Y29vd2F5.

最后,base64 编码XXQuanzhoucooway给出输出WFhRdWFuemhvdWNvb3dheQ==,其两端都有填充。去除前三个字符WFh(编码XX前缀)和最后三个字符Q==(编码末尾的零位填充),我们剩下字符串RdWFuemhvdWNvb3dhe. 因此,我们获得以下三个 base64 编码的字符串:

UXVhbnpob3Vjb293YX
F1YW56aG91Y29vd2F5
RdWFuemhvdWNvb3dhe
Run Code Online (Sandbox Code Playgroud)

其中(至少)一个必须以包含单词 的任何输入字符串的 base64 编码形式出现Quanzhoucooway

当然,如果你不走运,base64 编码器可能会在它们中间、任何两个编码的三元组之间插入一个换行符。(例如,您的示例消息在F1YW56和之间有一个aG91Y29vd2F5。)因此,要可靠地将这些字符串与正则表达式匹配,您需要类似以下内容(使用 PCRE 语法):

/UXVh\s*bnpo\s*b3Vj\s*b293\s*YX/ DISCARD
/F1\s*YW56\s*aG91\s*Y29v\s*d2F5/ DISCARD
/R\s*dWFu\s*emhv\s*dWNv\s*b3dh\s*e/ DISCARD
Run Code Online (Sandbox Code Playgroud)

手动生成这些模式有点乏味,但是编写一个简单的脚本来使用您最喜欢的编程语言来完成它并不难,至少只要它提供 base64 编码器即可。

如果您真的需要,您甚至可以通过 base64 对关键字的小写和大写版本进行编码并将它们组合成匹配​​它们的任意组合的正则表达式来实现不区分大小写的匹配。例如,base64 编码quanzhoucoowaycXVhbnpob3Vjb293YXk=QUANZHOUCOOWAYis 的UVVBTlpIT1VDT09XQVk=,所以规则:

/[cU][XV]V[hB]\s*[bT][nl]p[oI]\s*[bT][31]V[jD]\s*[bT][20]9[3X]\s*[YQ][XV]/ DISCARD
Run Code Online (Sandbox Code Playgroud)

在任何情况下都将匹配 base64 编码的单词“Quanzhoucooway”,前提是它以三元组边界开始。为转换版本生成另外两个相应的正则表达式留作练习。;)

唉,做任何比这样简单的子字符串匹配更复杂的事情很快就变得不切实际了。但至少这是一个巧妙的技巧。原则上,如果您出于某种原因无法使用 SpamAssassin 或任何其他可以在过滤之前解码 base64 编码的过滤器,它甚至可能很有用。但是如果你能做到这一点,而不是像这样使用黑客,你当然应该这样做。