一、引言:动态识别钓鱼网站的迫切性

网络钓鱼(Phishing)作为一种常见的网络攻击手段,其本质是一种社会工程学攻击,攻击者通过伪造可信实体的电子通信(如邮件、即时消息),诱导用户访问恶意网站,进而窃取敏感信息。在数字化生活日益普及的今天,我们几乎每天都离不开网络,但钓鱼网站却像隐藏在暗处的陷阱,严重威胁着我们的个人信息和财产安全。

传统的防护方式主要依赖“黑名单”拦截,即通过维护一个已知恶意网址的数据库进行匹配。然而,根据瑞星“云安全”系统的历史数据,传统杀毒软件对钓鱼网站的拦截率只有30%-40%。这种方式存在明显的滞后性覆盖不全的问题,难以应对日益隐蔽和多变的钓鱼网站,特别是那些由生成式AI(如ChatGPT)自动生成的新式钓鱼网站

因此,将人工智能技术,特别是深度学习模型,引入网络安全领域,探索一种能够动态、实时分析网站特征的识别方法,变得尤为重要。本文将详细介绍如何利用卷积神经网络(CNN)构建一个动态识别引擎,并将其封装为一款可实际运行的浏览器防护插件。

—文章最后附源码,可参考—

二、项目核心思路与技术选型

2.1 项目目标

本项目的核心目标是打破传统“黑名单”机制的局限,探索一种更智能、更主动的防护思路:

  • 验证AI动态识别钓鱼网站的可行性
  • 开发一款轻量级、可实时分析的浏览器防护插件原型
  • 探索“AI动态识别 + 传统安全机制”的立体化防护策略

2.2 为何选择卷积神经网络(CNN)?

在众多深度学习模型中,我选择CNN(卷积神经网络) 作为核心识别模型,主要基于其在特征提取方面的独特优势:

  1. 强大的局部特征提取能力:CNN通过其卷积核结构,能够自动、高效地捕捉输入数据中的局部相关性。对于钓鱼网站检测,这意味着模型可以精准识别出URL中的异常字符组合,以及网页截图中的虚假按钮形态、模仿特定品牌的色块布局等细微视觉特征。这种对局部模式的敏感性,对于发现高度仿真的钓鱼页面至关重要。

  2. 参数共享与池化操作:这两大特性使得CNN模型在计算上非常高效。参数共享大幅减少了模型需要学习的参数量,而池化操作在保留关键特征的同时降低了特征图的维度。这使模型能够满足终端部署的 “轻量化”需求,确保在用户端进行实时识别时依然保持流畅的用户体验。

2.3 技术对比:与其他方法的横向比较

为了更全面地展示技术选型的考量,下表对比了几种主流的AI反钓鱼技术:

技术方法 原理 优点 局限性
CNN(本项目采用) 提取网页视觉、URL序列的局部特征 特征提取能力强,适合图像式分析,模型相对轻量 对长序列URL的上下文语义理解较弱
LSTM孪生网络 通过双通道LSTM深度比对URL语义特征 对AI生成的钓鱼URL泛化能力强,善于捕捉语义相似性 模型相对复杂,计算开销可能更大
行为规则分析 基于用户一系列网络行为组合进行判断 不依赖网站内容,可从用户侧发现异常,降低误报 依赖对用户行为的准确定义,可能涉及隐私考量
胶囊网络(CapsNet) 通过向量神经元捕捉特征间的空间层次关系 对网页元素的相对位置、空间关系建模更优 技术较新,训练难度大,社区资源相对较少

三、系统设计与实现流程详解

整个项目的实现流程可以分为三个核心步骤:数据与算法准备、模型训练与优化、以及应用开发与部署。

3.1 第一步:数据与算法的准备

数据是模型的燃料。我从Kaggle等公开平台获取了包含钓鱼网站与合法网站的数据集。数据的预处理和质量直接决定了模型性能的上限。
Kaggle平台获取数据集

  • URL特征工程:除了将原始URL文本进行向量化,我还特别注重保留特殊符号(如./#)的拓扑信息,因为这些符号的分布模式通常蕴含着重要的判别特征。同时,借鉴了基于动态规划的模糊域名匹配算法基于广义后缀树的关键词提取方法,来有效识别域名仿冒(如paypa1.com冒充paypal.com)和提取钓鱼网站中高频出现的可疑词汇。

  • 视觉特征提取:将网页加载并截取屏幕截图。这些截图将作为CNN模型的输入,让模型学习识别钓鱼网站在整体布局、颜色搭配、Logo伪造、按钮样式等方面与真实网站的细微差别。瑞星公司的“智能反钓鱼”技术正是通过分析数十万钓鱼网站的色块布局等数据来构建智能辨别模型的。

3.2 第二步:模型的训练与优化

使用Python与TensorFlow/Keras框架搭建CNN模型。考虑到插件需要在用户终端实时运行,我特别注重模型的轻量化设计。

  1. 模型架构:没有一味追求层数很深的复杂模型,而是采用了几层卷积、池化层交替,最后连接全连接层的结构。在保证识别精度的同时,尽可能减少参数数量和计算量。

  2. 优化策略

    • 对抗训练:为了提高模型对恶意扰动的鲁棒性,我在训练中引入了对抗训练机制。这能让模型在面对经过轻微改动以图“欺骗”AI的钓鱼网站时,保持更高的识别稳定性。
    • 增量学习:为了应对不断出现的新的钓鱼手法,我参考了基于反馈的支持向量机增量学习算法的思路。这为未来模型在线学习新样本、实现持续进化提供了可行的技术路径。
      在这里插入图片描述
      在这里插入图片描述

3.3 第三步:应用开发——浏览器插件原型

将训练好的模型封装为可调用的接口(例如使用TensorFlow.js使其能在浏览器环境中运行),进而开发一个浏览器插件(Chrome Extension) 的原型。

该插件的工作机制如下:

  1. 实时监控:插件在后台静默运行,监听用户在浏览器中的标签页访问事件。
  2. 特征提取与分析:当用户访问一个新网站时,插件会立即获取该网站的URL和实时截图,并提取关键特征。
  3. 模型推理:将提取的特征输入到已加载的轻量化CNN模型中进行实时推理。
  4. 安全判决与响应:模型输出一个风险评分。如果评分超过预设阈值,插件会立即以非阻塞的方式(如地址栏旁的图标变色、弹出警告横幅)提醒用户,并建议用户谨慎操作。

四、行业应用与未来展望

AI动态检测技术正被越来越广泛地应用于各类安全产品中,例如国网重庆信通公司设计的网络安全运营智能助手,在可疑文件与链接检测上实现了99%的准确率。此外,在金融领域,面对AI深度伪造带来的新挑战,业界已普遍采用 “AI对抗AI” 的策略,通过模拟攻防演练不断提升防御体系的韧性。

对于本项目的未来规划,我考虑构建一个多层防御体系,其核心组成部分与功能如下:
多层防御体系示意图
这种“双保险”乃至“多保险”的策略,能够融合多种检测技术的优势,实现更快、更准、更安全的立体化防护效果。

五、总结

本项目完整地实践了将一个AI模型从理论训练应用到实际软件中的全过程。尽管当前的原型模型仍在持续测试和优化中,但它已经有力地证明了AI动态识别方案能够有效弥补传统黑名单的局限性,并对未来智能防护技术的发展具有积极的探索意义。

AI在网络安全领域的应用前景广阔,从浏览器插件到智能路由器,再到企业级邮件安全网关,防御的阵线正在不断扩展和深化。希望通过本文的分享,能吸引更多开发者投身于此,共同为构建更安全的网络环境贡献技术力量。

欢迎在评论区交流探讨!


附源码:

模型训练源码:

import pandas as pd
import numpy as np
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv1D, MaxPooling1D, Flatten, Dense, Dropout
import joblib

# 2. 加载数据集
df = pd.read_csv("E:\程君浩\技术\钓鱼网站公开数据集\phishing.csv")

# 确认特征列和标签列
feature_cols = [col for col in df.columns if col not in ['Index', 'class']]
X = df[feature_cols].values
y = df['class'].values  # 标签列为'class'

# 3. 数据标准化
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 4. 调整数据维度以适应Conv1D([样本数, 特征数, 1])
X_scaled = X_scaled.reshape(X_scaled.shape[0], X_scaled.shape[1], 1)

# 5. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X_scaled, y, test_size=0.2, random_state=42)

# 6. 构建CNN模型
model = Sequential()
model.add(Conv1D(filters=32, kernel_size=3, activation='relu', input_shape=(X_scaled.shape[1], 1)))
model.add(MaxPooling1D(pool_size=2))
model.add(Flatten())
model.add(Dense(64, activation='relu'))
model.add(Dropout(0.2))
model.add(Dense(1, activation='sigmoid'))  # 二分类问题,输出0或1

# 7. 编译模型
model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])

# 8. 训练模型
model.fit(X_train, y_train, epochs=10, batch_size=32, validation_data=(X_test, y_test))

# 9. 保存模型和标准化器
model.save("E:/程君浩/技术/phish_detect_model.keras")
joblib.dump(scaler, "E:/程君浩/技术/scaler.pkl")

print("模型训练完成并保存!")

调用模型检测源码:

import tensorflow as tf
import numpy as np
import tldextract
import re
import joblib

# 加载训练好的模型和标准化器
model = tf.keras.models.load_model("E:/程君浩/技术/phish_detect_model.keras")
scaler = joblib.load("E:/程君浩/技术/scaler.pkl")

# 定义与训练时一致的特征提取函数(需覆盖30个特征,需根据实际列名调整逻辑)
def extract_features(url):
    # 初始化特征列表(需与训练时的30个特征顺序完全一致)
    features = []
    
    # 1. UsingIP:是否使用IP(-1,0,1)
    has_ip = 1 if re.search(r'\d+\.\d+\.\d+\.\d+', url) else 0
    features.append(has_ip)
    
    # 2. LongURL:URL长度(-1,0,1)
    url_length = len(url)
    features.append(1 if url_length > 50 else (-1 if url_length < 20 else 0))
    
    # 3. ShortURL:是否为短链接(-1,0,1)
    short_domains = ['bit.ly', 'tinyurl.com', 't.co', 'goo.gl']
    is_short = 1 if any(domain in url for domain in short_domains) else 0
    features.append(is_short)
    
    # 4. Symbol@:是否包含@符号(-1,0,1)
    has_at = 1 if '@' in url else 0
    features.append(has_at)
    
    # 5. Redirecting//:是否有重定向(-1,0,1)
    has_redirect = 1 if '//' in url.split('http')[1] else 0
    features.append(has_redirect)
    
    # 6. PrefixSuffix-:前缀后缀异常(-1,0,1)
    ext = tldextract.extract(url)
    domain = ext.domain
    has_prefix_suffix = 1 if (domain.startswith('-') or domain.endswith('-')) else 0
    features.append(has_prefix_suffix)
    
    # 7. SubDomains:子域名数量(-1,0,1)
    subdomain_count = len(ext.subdomain.split('.')) if ext.subdomain else 0
    features.append(1 if subdomain_count > 3 else (-1 if subdomain_count == 0 else 0))
    
    # 8. HTTPS:是否为HTTPS(-1,0,1)
    is_https = 1 if 'https' in url[:5] else (-1 if 'http' not in url[:5] else 0)
    features.append(is_https)
    
    # 9. DomainRegLen:域名注册时长(-1,0,1)—— 这里简化为虚拟特征,实际需结合WHOIS查询,若没有可填0
    features.append(0)
    
    # 10. Favicon:图标异常(-1,0,1)
    features.append(0)  # 简化逻辑,实际需检测图标域名
    
    # 11. NonStdPort:非标准端口(-1,0,1)
    has_non_std_port = 1 if re.search(r':\d{4,}', url) else 0
    features.append(has_non_std_port)
    
    # 12. HTTPSDomainURL:HTTPS域名不一致(-1,0,1)
    features.append(0)  # 简化逻辑,实际需解析域名
    
    # 13. RequestURL:请求URL异常(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 14. AnchorURL:锚点URL异常(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 15. LinksInScriptTags:脚本中链接异常(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 16. ServerFormHandler:服务器表单处理异常(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 17. InfoEmail:信息邮箱异常(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 18. AbnormalURL:URL异常(-1,0,1)
    features.append(1 if re.search(r'[^\w\.-]', url) else 0)
    
    # 19. WebsiteForwarding:网站转发(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 20. StatusBarCust:状态栏自定义(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 21. DisableRightClick:禁用右键(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 22. UsingPopupWindow:使用弹窗(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 23. IframeRedirection:iframe重定向(-1,0,1)
    features.append(0)  # 简化逻辑
    
    # 24. AgeofDomain:域名年龄(-1,0,1)—— 简化为0
    features.append(0)
    
    # 25. DNSRecording:DNS记录(-1,0,1)—— 简化为0
    features.append(0)
    
    # 26. WebsiteTraffic:网站流量(-1,0,1)—— 简化为0
    features.append(0)
    
    # 27. PageRank:页面排名(-1,0,1)—— 简化为0
    features.append(0)
    
    # 28. GoogleIndex:谷歌索引(-1,0,1)—— 简化为0
    features.append(0)
    
    # 29. LinksPointingToPage:指向页面的链接(-1,0,1)—— 简化为0
    features.append(0)
    
    # 30. StatsReport:统计报告(-1,0,1)—— 简化为0
    features.append(0)
    
    return np.array(features)

# 输入要检测的URL
test_url = input("请输入要检测的URL(例如http://example.com):")

# 提取特征并预测
new_features = extract_features(test_url)
new_features_scaled = scaler.transform([new_features])
new_features_reshaped = np.expand_dims(new_features_scaled, axis=-1)

# 模型预测
prediction = model.predict(new_features_reshaped)
is_phishing = "是钓鱼网站" if prediction[0][0] > 0.5 else "不是钓鱼网站"

print(f"检测结果:{test_url} {is_phishing},置信度:{prediction[0][0]:.2f}")
Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐