12.2 垃圾邮件检测绕过技术

攻防对抗是这本书的主要研究内容,也是安全领域永恒的一个主题。这里我们重点介绍基于英文邮件的垃圾邮件绕过技术。在垃圾邮件检测中,处理的最小单元往往是单词,所以绕过的突破点就在单词上。人在查看邮件时,明显的错别字、多余的回车、换行符和制表符等基本不影响人的阅读,但是对于机器来说却可以破坏基于单词的识别机制,例如下面这封垃圾邮件:


raw="thank you ,your email address was obtained from a purchased list ," \
    "reference # 2020 mid = 3300 . if you wish to unsubscribe"

12.2.1 随机增加TAB

在单词中插入TAB基本不会影响人的阅读,但是却可以破坏机器对单词的识别,比如上面那段代码就可以转化成:


thank you ,your ema
il address was obtained from a purchased list ,reference # 2020 mid = 3300 . if you wish to unsubscribe

一种简单的实现就是在文本中随机选择英文字符,在该字符后面增加TAB即可,替换的个数也可以随机在1~3之间选择,代码如下:


def addTab(self,str,seed=None):
    matchObjs = re.findall(r'[a-qA-Q]', str, re.M | re.I)
    if matchObjs:
        #选择替换的字符
        modify_char=random.choice(matchObjs)
        #生成替换的内容
        modify_char_tab="   {}".format(modify_char)
        #替换
        str=re.sub(modify_char, modify_char_tab, 
str,count=random.randrange(1,3))
    return str

12.2.2 随机增加回车

在单词中插入回车也基本不会影响人的阅读,但是却可以破坏机器对单词的识别,比如上面那段代码就可以转化成:


th  ank you ,your em  ail address was obtained from a purchased list, reference # 2020 mid = 3300 . if you wish to unsubscribe

一种简单的实现就是在文本中随机选择英文字符,在该字符前面增加回车即可。为了避免影响阅读,将替换的个数设置为1,代码如下:


def addEnter(self,str,seed=None):
    matchObjs = re.findall(r'[a-qA-Q]', str, re.M | re.I)
    if matchObjs:
        #选择替换的字符
        modify_char=random.choice(matchObjs)
        #生成替换的内容
        modify_char_enter="\\r\\n{}".format(modify_char)
        #替换
        str=re.sub(modify_char, modify_char_enter, str,count=1)
    return str

12.2.3 大小写混淆

有的检测规则是大小写敏感的,所以也可以使用大小写混淆的方式来尝试绕过,比如12.2节最前面的那段代码就可以转化成:


thank you ,your email ADDRESS was obtained from a purchased list ,reference # 2020 mid = 3300 . if you wish to unsubscribe

一种简单的实现就是在文本中随机选择英文单词,将该单词大小混淆即可。替换的个数也可以随机在1~3之间选择,代码如下:


def confusionCase(self,str,seed=None):
    matchObjs = re.findall(r'\b\w+\b', str, re.M | re.I)
    if matchObjs:
        #选择替换的单词
        modify_word=random.choice(matchObjs)
        #生成替换的内容
        modify_word_swapcase=modify_word.swapcase()
        #替换
        str=re.sub(modify_word, modify_word_swapcase, str,count=random.randrange(1,3))
    return str

需要说明的是,大小混淆有可能会影响个别单词的理解,尤其是专有名词的理解。

12.2.4 随机增加换行符

插入换行符也基本不会影响人的阅读,但是却可以破坏机器对单词的识别,比如12.2节最前面的那段代码就可以转化成:


than/k you ,your email address was obtained from a purchased list ,reference # 2020 mid = 3300 . if you wish to unsubscribe

一种简单的实现就是在文本中随机选择英文字符,在该字符后面增加换行符即可。替换的个数也可以随机在1~3之间选择,代码如下:


def lineBreak(self,str,seed=None):
    matchObjs = re.findall(r'[a-qA-Q]', str, re.M | re.I)
    if matchObjs:
        # 选择替换的字符
        modify_char = random.choice(matchObjs)
        # 生成替换的内容
        modify_char_lb = "{}/".format(modify_char)
        # 替换
        str = re.sub(modify_char, modify_char_lb, str, count=random.randrange(1, 3))
    return str

12.2.5 随机增加连字符

插入连字符也基本不会影响人的阅读,但是却可以破坏机器对单词的识别,比如12.2节最前面那段代码就可以转化成:


thank you ,your email ad-d-ress was obtained from a purchased list ,reference # 2020 mid = 3300 . if you wish to unsubscribe

一种简单的实现就是在文本中随机选择英文字符,在该字符后面增加连字符即可。替换的个数也可以随机在1~3之间选择,代码如下:


def addHyphen(self,str,seed=None):
    matchObjs = re.findall(r'[a-qA-Q]', str, re.M | re.I)
    if matchObjs:
        # 选择替换的字符
        modify_char = random.choice(matchObjs)
        # 生成替换的内容
        modify_char_lb = "{}-".format(modify_char)
        # 替换
        str = re.sub(modify_char, modify_char_lb, str, count=random.randrange(1, 3))
    return str

12.2.6 使用错别字

人在阅读的时候可以识别明显的语法错误以及错别字,但不影响对原文的理解,不过机器在进行垃圾邮件识别时,面对错别字有可能产生判断失误,比如12.2节最前面那段代码就可以转化成:


thank you ,your eemail addreess was obtained from a purchased list ,reference # 2020 mid = 3300 . if you wish to unsubscribe

一种简单的实现就是在文本中随机选择英文字符,将该字符替换成两个即可。替换的个数也可以随机在1~3之间选择,代码如下:


def doubleChar(self,str,seed=None):
    matchObjs = re.findall(r'[a-qA-Q]', str, re.M | re.I)
    if matchObjs:
        #选择替换的字符
        modify_char=random.choice(matchObjs)
        #生成替换的内容
        modify_char_enter="{}{}".format(modify_char,modify_char)
        #替换
        str=re.sub(modify_char, modify_char_enter, str,count=random.randrange (1,3))
    return str