学生党好容易才接触到了网络安全和AI原理!我接触这个领域有一段时间了,最近在学习卷积神经网络(CNN)的攻防技术,感觉很有意思,也踩了不少坑。趁着端午假期,我把自己的实践过程整理成了这篇文章。我知道在座的大佬很多,文章里肯定有错误或理解不到位的地方,恳请大家不吝赐教、斧正。这篇文章算是我的学习笔记,如果能给同样刚起步的朋友一点参考,那就更好了。
免责声明:本文所有内容仅用于在受控环境下的安全研究与学习,请勿用于任何未经授权的攻击行为。所有操作均在本地实验环境进行。
一、先看城墙:CNN的底层结构
在理解如何攻击之前,我首先尝试搞清楚CNN的内部结构。卷积神经网络的核心无非是三部分:
1. 卷积层:可以理解为用一个个小方块(卷积核)在图像上滑动,提取边缘、纹理等特征。就像用不同的滤镜扫描图片,滤镜不同,提取的特征也不同。
2. 池化层:这一层会主动丢弃部分细节信息,例如最大池化只保留区域内的最强信号。从安全角度看,丢弃的信息可能成为潜在的攻击面。
3. 全连接层:最后所有特征被展平,通过全连接层给出最终判断。
我的一个粗浅理解是:CNN的决策过程是一个从原始像素到抽象概念的连续“压缩”过程,压缩必然带来信息丢失,这些丢失的信息就可能成为攻击的突破口。
二、攻击者的视角:尝试让CNN“失明”
我的实验目标是:给输入数据添加人眼难以察觉的微小扰动,让模型输出完全错误的结果。我使用的经典方法是基于梯度的对抗样本攻击——FGSM(快速梯度符号法)。
它的核心公式是:
adv_x = x + ε * sign(∇x J(θ, x, y))
沿着损失函数对输入图像的梯度方向走一小步(ε),让损失变大,模型预测就可能会出错。
实验环境与设备情况:
下面的代码是在一台普通笔记本上运行的,配置不高(没有独立显卡)。为了节省时间,我只训练了3个epoch,模型精度有限,但足够演示攻击效果。原本想截取训练过程中的loss曲线图,但运行时为了截图导致系统卡死,图片没保存下来,所以文中只放了最终结果的截图——这也算是一个小插曲吧。
攻击代码实战(TensorFlow/Keras)
我使用MNIST手写数字数据集,先训练一个简单的CNN,然后生成对抗样本进行攻击。
import tensorflow as tf
import numpy as np
import matplotlib.pyplot as plt
# 1. 加载并预处理数据
(x_train, y_train), (x_test, y_test) = tf.keras.datasets.mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0
x_train = x_train[..., tf.newaxis]
x_test = x_test[..., tf.newaxis]
# 2. 训练一个简单的CNN靶机
model = tf.keras.models.Sequential([
tf.keras.layers.Conv2D(32, (3,3), activation='relu', input_shape=(28,28,1)),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Conv2D(64, (3,3), activation='relu'),
tf.keras.layers.MaxPooling2D((2,2)),
tf.keras.layers.Flatten(),
tf.keras.layers.Dense(64, activation='relu'),
tf.keras.layers.Dense(10, activation='softmax')
])
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', metrics=['accuracy'])
model.fit(x_train, y_train, epochs=3, batch_size=64)
# 3. FGSM攻击函数
def fgsm_attack(image, epsilon, gradient):
signed_grad = tf.sign(gradient)
perturbed_image = image + epsilon * signed_grad
perturbed_image = tf.clip_by_value(perturbed_image, 0, 1)
return perturbed_image
# 4. 生成对抗样本
def generate_adversarial(model, image, label, epsilon):
image = tf.convert_to_tensor(image.reshape((1,28,28,1)))
with tf.GradientTape() as tape:
tape.watch(image)
prediction = model(image)
loss = tf.keras.losses.sparse_categorical_crossentropy(label, prediction)
gradient = tape.gradient(loss, image)
adversarial_image = fgsm_attack(image, epsilon, gradient)
return adversarial_image.numpy().squeeze()
# 5. 取一张测试图片进行攻击
test_idx = 1
original_img = x_test[test_idx]
true_label = y_test[test_idx]
pred_orig = model.predict(original_img.reshape(1,28,28,1)).argmax()
print(f"原始预测: {pred_orig}, 真实标签: {true_label}")
epsilon = 0.1
adv_img = generate_adversarial(model, original_img, true_label, epsilon)
pred_adv = model.predict(adv_img.reshape(1,28,28,1)).argmax()
print(f"对抗样本预测: {pred_adv}, 真实标签: {true_label}")
plt.figure(figsize=(8,3))
plt.subplot(1,2,1)
plt.title(f'Original (pred:{pred_orig})')
plt.imshow(original_img.squeeze(), cmap='gray')
plt.subplot(1,2,2)
plt.title(f'Adversarial (pred:{pred_adv})')
plt.imshow(adv_img.squeeze(), cmap='gray')
plt.show()
实验结果:人眼几乎看不出两张图片的区别,但CNN已经将对抗样本识别成了完全不同的数字。这个结果让我挺意外的,原来AI的视觉系统并没有想象中那么可靠。
一些进一步的思考(不完全,抛砖引玉):
· 如果拿不到梯度(黑盒场景),还能攻击吗?我了解到的有迁移攻击、查询攻击等方式,但还没深入实践。
· 扰动能更隐蔽吗?应该有C&W攻击、DeepFool等更精细的方法。
· 物理世界攻击:把生成的扰动打印出来贴在路牌上,自动驾驶的CNN会犯错吗?——这可能是更接近现实的威胁场景。
这些我暂时只停留在理论层面,欢迎大佬指点。
三、从攻击到防御:如何提高CNN的鲁棒性?
既然知道了攻击的原理,自然就想尝试一下如何防御。以下是我尝试过的几种方法,效果不一。
1. 对抗训练(Adversarial Training):把生成的对抗样本混入训练集,让模型学习识别它们,提高鲁棒性。这是目前工业界常用的手段,但缺点是可能会降低模型在干净样本上的精度。
2. 梯度掩蔽(Gradient Masking):通过不可微的操作(如JPEG压缩)让梯度无法准确计算,增加攻击难度。不过高级攻击者可能通过BPDA等技术绕过,所以不是万能的。
3. 输入预处理与检测:在模型前加一个检测层,判断输入是否带有对抗扰动,实时拦截。
这些防御手段我还在学习中,目前只是跑通了基本流程,效果还有待验证。
四、后续学习方向
这篇文章只是我的一个起点。在未来,我希望能把CNN攻防的思想延伸到更广泛的AI安全领域:
· 多模态模型攻击:对视觉+语言大模型注入伪装指令
· 联邦学习投毒:在分布式训练中注入恶意数据,使模型产生后门
· AI驱动的免杀:用生成模型实时改变恶意代码特征
学习资源推荐(我自己也在看):
· 书籍:《对抗机器学习》(中文译本)、《AI安全之对抗样本入门》
· 实战平台:Kaggle上的对抗样本竞赛、阿里云天池AI安全赛道
· 学术会议:USENIX Security、IEEE S&P上最新的AI安全论文
结语
通过这次实践,我深刻体会到:只有亲手攻破过模型,才知道如何更好地防御它。每一次攻击实验,都加深了我对防御策略的理解。
这篇文章是我的学习笔记,代码虽然经过了测试,但因为个人水平有限,肯定存在不少疏漏。欢迎各位在评论区指正,也希望能和更多对这个方向感兴趣的朋友交流。
---
作者注:本文所有技术内容仅供在受控环境下的授权安全研究与学习使用,任何未授权的攻击行为均属违法。
—— 一名学生的实践笔记&spm=1001.2101.3001.5002&articleId=162129010&d=1&t=3&u=6cd14f0d678d49358d9a823b32e77a5d)
1515

被折叠的 条评论
为什么被折叠?



