AI在网络安全中的应用之钓鱼邮件检测

发布于:2025-05-20 ⋅ 阅读:(21) ⋅ 点赞:(0)

0x01 前言

为什么写这个呢,源自于我之前在某教培网站留了信息,不出意外的个人信息泄露的飞快,邮箱开始疯狂收到垃圾邮件甚至钓鱼邮件,看着每天的拦截消息,就在想这个拦截机制挺好玩的,拦截器是怎么知道是不是正常邮件呢,结合现在AI有些爆火,于是就学习一下。

此处也建议大家尽量不要去在网站上留个人信息,最好去找一些有实体公司的中介或者机构,网上的大部分都是第三方平台,他们收到信息就会推到所有合作的机构手里,个人信息就满天飞啦~啦~啦~

0x02 先来思考

我们如何判断一封邮件是钓鱼邮件还是正常邮件呢?像这种

图片

那么我们可以从邮件内容看出来,钓鱼邮件的内容通常是用一两句我们认为比较重要的提示信息+诱导点击链接。 但是,只要出现特征点就一定是吗,当然不是。比如这种就是正常邮件:

图片

所以此时就要引出神秘的三人组:权重、激活函数、阈值

0x03 神秘三幻神:权重、激活函数、阈值

权重:表示特征点重要程度,就像比如当我们看到“bo彩”就会知道这一定不是什么好内容。

激活函数:作用是将加权信号转换为输出信号。人话就是把一堆特征点算出来的值通过线代求和的方式变成一个值。

阈值:通过激活函数出来的值如果大于阈值,则输出为aaa,否则输出为bbb。 这样经过权重的加持下,就可以友好的避免了误伤,文字有点难理解了,那我们就看个表

图片

可以看到,我们给予"点击查看"的权重为3,"更新"为2,而这,就组成了激活函数y=3a+2b,当计算值为5的时候达到阈值,判断为钓鱼邮件。 那么一个新的问题,现在的钓鱼手段层出不穷,对于特征点的权重和阈值也需要实时更新才可以,这里就要提到AI在网络安全领域里的第一个例子-感知机

0x04 感知机

何为感知机?

感知机是模仿人类神经元的一个二分类模型,将输入值做线性代数运算求和,并在达到一定值时激活函数从而得出结论。就像人类,看到红色的软妹币大脑就会刺激我们开心,但是打开看到的是印着玉皇大帝的时候又会刺激我们做出愤恨的情绪一样。 那感知机如何做到实时更新的能力呢?他的运转过程大概如下: 1、将权重初始化为预订值,通常为0 2、计算每个训练样本x,并输出y(结论) 3、根据样本中预设的y与输出的y之间的差距更新权重

用感知机实现一下嘞

理论结束,开始实践。首先解决输入样本的问题,这次先做简单的样本尝试一下,特征点就采用“点击查看”和“更新”并预设邮件类型和特征点出现次数搞个一百来行(其实ai生成一下也行)。

图片

输入样本搞定,然后使用pandas库的DataFrame提供文件加载能力,iloc函数提供数据提取能力,使用numpy库提供数学运算能力

import pandas as pd
import numpy as np
df = pd.read_csv('heihei.csv', encoding='gbk')# 读取数据集,注意文件路径是否正确,并指定正确的编码格式
y = df.iloc[:, 0].values
y = np.where(y == '钓鱼邮件', -1, 1)  # 此处的where函数由numpy提供,用于将类别转换成-1和+1
X = df.iloc[:, [1, 2]].values# 获取特征列(假设第2和第3列为特征)

人工智能嘛必须得训练一下

设定用来训练和预测的数据范围,这里为了看最终效果强制73分了,其实可以随机取70%做训练集。

split_index = int(len(X) * 0.7)# 取前70%为训练集
X_train, X_test = X[:split_index], X[split_index:]
y_train, y_test = y[:split_index], y[split_index:]
#随机取可以用:X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=0)

输入都完事了,开始实例化感知机,使用scikit-learn库提供感知机模型,给予他最大迭代次数70,学习率0.1,并初始化权重,看他经过训练最终权重会发生怎样的变化。

# 创建感知机实例,使用SGDClassifier模拟感知机行为
p = SGDClassifier(loss='perceptron', max_iter=70, eta0=1.0, learning_rate='constant', random_state=0)
#初始化权重
p.coef_ = np.zeros((1, X_train.shape[1]))
p.intercept_ = np.zeros(1)
# 训练模型
p.fit(X_train, y_train)

使用predict()方法预估值

y_pred = p.predict(X_test)

打印数据看看结果

图片

可以看到结果正确率八成以上,并且权重完成了更新。

意犹未尽,继续思考

刚才说,这其实就是一个二分类模型,说白了就是把所有样本化成坐标然后一分为二,一半是钓鱼邮件、一半是正常邮件,用刚才的例子画成图:

图片

这就有一个局限性,如果点变多了,可能无法找到可以一分为二的地方,就会产生无限震荡(挂了),且这是我提前预设好了特征点,而现在随着技术进步,显然已经不实用了,他应该可以自己从邮件里找到特征点,那么怎么才能解决这一堆的问题呢?

0x05 感知机究极进化

朴素贝叶斯

先看下贝叶斯公式

图片

  • P(Ck∣x):数据点 x 属于类别 Ck 的概率。

  • P(x∣Ck):在类别 Ck 下,数据点 x 出现的概率。

  • P(Ck):类别 Ck 的先验概率(即该类别在数据中的占比)。

  • P(x):数据点 x 的概率(可忽略,因为对所有类别相同)。 嗯。。把数学基础还给老师了。。。。还是用个例子说下

用相亲交友软件,假设坏人主页的常见词汇:“深夜”“寂寞”“约我”等,而正常用户中常见词汇:“读书”“认真”“吃苦”等。假设 **先验概率P(Ck)**:坏人占比:70%(即 P(坏人)=0.7)。正常用户占比:30%(即 P(正常)=0.3)。

条件概率:在坏人中,“寂寞”出现的概率:80%(即 P(寂寞∣坏人)=0.8)。在正常用户中,“寂寞”出现的概率:10%(即 P(寂寞∣正常)=0.1)。其他词汇的概率类似计算。 当再出现一个用户写有”寂寞”“约我”“认真”这个词时, 

预测坏人的概率就是: P(坏人|账号)=P(坏人)xP(寂寞|坏人)xP(约我|坏人)xP(认真|坏人)=0.7x0.8x0.7x0.2=0.0784, 

预测正常用户的概率时: P(正常用户|账号)=P(正常用户)xP(寂寞|正常用户)xP(约我|正常用户)xP(认真|正常用户)=0.3x0.1x0.1x0.6=0.0018, 那么这个账号大概率就是坏人。

而朴素贝叶斯算法,可以动态识别钓鱼邮件中的可以关键字,加上贝叶斯公式的原理,做到动态识别,精准分析。

朴素贝叶斯钓鱼邮件检测器的实现

理论结束,实践开始,首先还是要解决样本问题,这次,我们只需要做出样本的分类和内容就行,大概长这样:

图片

# 导入必要的库
import matplotlib.pyplot as plt  # 用于绘图
import csv  # 用于处理CSV文件
from textblob import TextBlob  # 用于自然语言处理
import pandas as pd  # 数据处理库
import sklearn  # 机器学习库
import numpy as np  # 数值计算库
import nltk  # 自然语言工具包
# 加载数据集,指定正确的编码格式
sms = pd.read_csv('yangben.csv', sep=',', names=["type", "text"], encoding='gbk')  # 读取CSV文件
# 数据集划分:将数据分为训练集和测试集
text_train, text_test, type_train, type_test = train_test_split(sms['text'], sms['type'], test_size=0.3, random_state=42)

使用sklearn.naive_bayes中的MultinomialNB实现一个基于贝叶斯的分类器

from sklearn.naive_bayes import MultinomialNB # 多项式朴素贝叶斯分类器
spam_detector = MultinomialNB().fit(sms_tfidf, type_train)# 模型训练:使用多项式朴素贝叶斯分类器训练模型

使用 sklearn.feature_extraction.text 中的 CountVectorizer为为文本中每个识别词标记一个数字,并使用get_lemmas提取

bow = CountVectorizer(analyzer=get_lemmas).fit(text_train)  # 使用词袋模型提取特征
sms_bow = bow.transform(text_train)  # 将训练文本转换为词袋表示
from sklearn.feature_extraction.text import CountVectorizer, TfidfTransformer # 文本向量化工具
from defs import get_tokens, get_lemmas # 获取分词和词形还原的函数

因为邮件有长有短,文件中出现过多词会影响计算,就需要使用scikit-learn 中的TfidfTransformer() 将词频计数转换为 TF-IDF (Term Frequency-Inverse Document Frequency) 值,从而把词频归一化并加权。

TF (Term Frequency):词频f(t,d),表示一个词在文档中出现的频率归一化(Normalization):tf(t,d) = f(t,d) / sqrt(sum(f(t,d)^2 for all t in d)),使不同特征在同一尺度上,便于比较和机器学习算法处理 IDF (Inverse Document Frequency):idf(t) = log((n + 1) / (df(t) + 1)) + 1逆文档频率,衡量一个词的普遍重要性 TF-IDF 计算:tfidf(t,d) = tf(t,d) * idf(t)TF-IDF 计算:tfidf(t,d) = tf(t,d) * idf(t)

tfidf = TfidfTransformer().fit(sms_bow)  # 计算TF-IDF权重
sms_tfidf = tfidf.transform(sms_bow)  # 将词袋表示转换为TF-IDF表示

然后先预测一行数据,如第45行为例子,看是否正确

图片

图片

图片

没啥毛病,开始完整预测测试集

# 对测试集进行特征提取和预测
text_test_bow = bow.transform(text_test)
text_test_tfidf = tfidf.transform(text_test_bow)
predictions = spam_detector.predict(text_test_tfidf)

图片

参数解释: precision(精确率):钓鱼邮件样本7个,预测到4个,4个均是钓鱼邮件,精确率100% recall(召回率):钓鱼邮件样本7个,预测到4个,召回率57% f1-score(调和平均值):F1 = 2 × (1.0 × 0.57) / (1.0 + 0.57)=0.73 support(支持):样本数量 Macro Avg (宏平均):对每个类别的精确率、召回率和F1分数取平均值 Weighted Avg (加权平均):对每个类别的精确率、召回率和F1分数按支持度加权取平均值。

可以看到最终准确率也是高达9成。

0x06 总结

钓鱼邮件攻击手段日益复杂,传统规则检测已不足以应对。未来需结合AI检测、用户教育、企业安全策略等多层防御,才能有效降低风险。机器学习(如BERT、异常检测)在钓鱼邮件识别中表现优异,但仍需不断优化以应对新型攻击手法并且我们自身也需要不断提高安全意识。


网站公告

今日签到

点亮在社区的每一天
去签到