近年来,机器学习在计算机视觉、语音识别、自然语言处理、医疗数据分析等方面的应用取得了瞩目的研究成果,展现了机器学习在解决分类、预测以及辅助决策中强大的能力,使得机器学习技术为解决传统方法难以建模的网络空间安全问题提供了可能性。在20世纪80年代,已有学者在网络入侵检测中应用机器学习技术,但受限于当时的存储空间及计算能力,机器学习未能引起学者们的重视,随着大数据、云计算技术的出现,对搜集、存储、管理及处理数据的能力大幅提升,因此将机器学习应用到网络安全中,已成为近年来安全领域的研究热点。
在本文中,我们通过卷积神经网络实现对XSS恶意代码的攻击检测,通过一步一步搭建模型框架可以看到机器学习在网络安全领域做恶意流量识别的效果,也能够引发我们对模型安全层面的一些思考。在实验之前,一些基础知识介绍如下:
0x01 基础知识介绍
1、XSS攻击介绍
从OWASP上可以看到对XSS攻击的概述如下:跨站脚本(XSS)攻击是一种注入攻击,攻击者通过将恶意脚本植入原本安全且受信任的网站中来实施攻击。此类攻击发生在攻击者利用Web应用向不同终端用户发送恶意代码(通常以浏览器端脚本形式存在)时。若Web应用在生成输出内容时未对用户输入进行验证或编码,便存在此类漏洞,且该漏洞普遍存在,可能出现在任何需要将用户输入嵌入输出内容的环节。
攻击者可利用XSS向用户发送恶意脚本。由于终端用户的浏览器无法识别该脚本不可信,便会执行该脚本。由于浏览器误认为脚本来自可信来源,恶意脚本即可访问浏览器中保存的所有Cookie、会话令牌或其他与该网站相关的敏感信息。这些脚本甚至能够重写HTML页面的内容。
2、卷积神经网络介绍
卷积神经网络(CNN)是人工神经网络(ANNs)的高级版本,主要用于从网格状矩阵数据集中提取特征。这对于图像或视频等视觉数据集特别有用,因为数据模式在其中起着至关重要的作用。由于卷积神经网络在处理视觉数据方面的有效性,它在计算机视觉应用中得到了广泛的应用。CNN由输入层、卷积层、池化层和全连接层等多层组成。如下图所示:
卷积神经网络示意图
0x02 数据集
数据集来自Kaggle平台,地址如下:
https://www.kaggle.com/syedsaqlainhussain/cross-site-scripting-xss-dataset-for-deep-learning
数据是csv形式,一共有三列,第一列是序号,第二列是具体的XSS字符串,第三列是标签。一共有13686条数据,没有划分训练集和测试集。
XSS数据集示意图
0x03 框架设计
从数据集可以看到,XSS数据是字符串格式,为了更好的对数据进行训练,我们要对数据做预处理,处理方式是对数据进行编码,将其转换成向量的形式,这里向量的值应该写什么呢?是单个字符吗,不是,这里我们会将每一条数据中的每一个字符转为该字符的ASCII数值,对于一些超过ASCII范围的,我们会自定义该字符的数值,这样操作的目的是为了后续数据计算更加方便。之后再通过reshape(重组)操作,将向量转换为二维向量,从而作为模型的输入参数,之后会经过一层一层的卷积操作完成特征提取。总结一句话就是不断使用卷积层和池化层来压缩特征,压缩到一定程度时,再使用全连接层来拟合输出。
整体检测的框架设计如下图所示,从图中可以看到,一共做了3次卷积操作,两次池化操作。需要强调的是,整个模型的训练过程会将数据集分为训练集和测试集,对于训练集和测试集每一行数据,我们都有编码和标签两种数据,在每一轮的批次训练中会将训练结果与标签进比对,计算模型损失,最后通过测试集进行验证。
模型训练示意图
0x04 代码实现
本次实验代码通过Pytorch框架实现。
1、模块导入
import numpy as npimport pandas as pdimport torchimport torch.nn as nnimport torch.nn.functional as Ffrom torch.utils.data import DataLoaderimport torch.optim as optimimport cv2from sklearn.model_selection import train_test_split
-
NumPy是Python中用于科学计算和数值计算的核心库,它提供了高性能的多维数组对象以及大量操作这些数组的数学函数。它是Python在数据科学、机器学习和工程计算领域广泛应用的基础工具之一。
-
Pandas是Python中用于数据处理、分析和操作的核心库,Pandas适用于处理表格型数据(如Excel表格、CSV文件)。它提供了高效的数据结构以及丰富的数据操作方法,是数据清洗、数据探索和数据分析的必备工具。
-
PyTorch是一个基于软件的开源深度学习框架,用于构建神经网络,将Torch的机器学习(ML)库与基于Python的高级API相结合。它的灵活性和易用性以及其他优点使其成为学术和研究界领先的机器学习框架。PyTorch支持多种神经网络架构,从简单的线性回归算法到复杂的卷积神经网络和用于计算机视觉和自然语言处理等任务的生成式转换器模型。
-
CV2指的是OpenCV2,是一个开源的库平台计算机视觉库。有很强大的图片处理功能,可实现图像处理和计算机视觉方面的很多通用算法。
-
Scikit-learn是一个开源机器学习库,支持监督学习和无监督学习。它还提供了各种工具,用于模型拟合、数据预处理、模型选择、模型评估以及许多其他实用程序。
2、数据集加载
将XSS数据集下载之后,放在和代码同级的目录下。通过pandas模块可以实现对csv文件的读取等操作。
df = pd.read_csv("XSS_dataset.csv",encoding="utf-8-sig")sentences = df['Sentence'].values
3、定义编码函数
对于一些编码后比较大的字符,可以为他们分配一个比较小的值,方便后续进行正则化。将每一条数据都通过一个长度为10000的向量进行存储。
defconvert_to_ascii(sentence): sentence_ascii = [] for i in sentence: if (ord(i) < 8222): if (ord(i) == 8217): sentence_ascii.append(134) if (ord(i) == 8221): sentence_ascii.append(129) if (ord(i) == 8220): sentence_ascii.append(130) if (ord(i) == 8216): sentence_ascii.append(131) if (ord(i) == 8217): sentence_ascii.append(132) if (ord(i) == 8211): sentence_ascii.append(133) if (ord(i) <= 128): sentence_ascii.append(ord(i)) else: pass zer = np.zeros((10000)) #初始化一个长度为10000的向量 for i in range(len(sentence_ascii)): zer[i] = sentence_ascii[i] zer.shape = (100, 100) #将一维转为二维 return zer
一条XSS数据是一个长度为10000的一维向量,我们需要存储的是数据集的所有XSS数据,因此应该采用数组的形式进行存储,数组的大小是数据集的长度,数组中具体的类型是一个二维向量,二维向量的大小是100*100,这里的大小是由长度为10000的一维向量转换而来,之后对XSS数据集中每一条数据都进行编码转换,并将二维向量中的数据都转为float类型表示,这样是为了确保后续计算的精度。最终得到的就是对数据集编码后的结果。
arr = np.zeros((len(sentences), 100, 100))for i in range(len(sentences)): image = convert_to_ascii(sentences[i]) x = np.asarray(image, dtype='float') #将二维里的数据类型转为float型 image = cv2.resize(x, dsize=(100, 100), interpolation=cv2.INTER_CUBIC) image /= 128 arr[i] = imagedata = arr.reshape(arr.shape[0],1,100, 100)
4、数据集划分
采用train_test_split函数随机划分数据。其中test_size是指测试数据占样本数据的比例,这里取样本总数的20%作为测试数据,random_state是一个随机数种子。之后通过DataLoader函数设定训练批次大小,shuffle字段用于决定是否在每个epoch开始时随机打乱数据,在训练模型时,通常建议将训练集的shuffle设置为True,以确保数据的随机性。然而,对于测试集,通常不建议设置shuffle=True,因为测试集的目的是评估模型的性能,保持数据的原始顺序可以更准确地反映模型的预测能力。需要注意的是数据和标签中的值都是ndarray类型的,因此还需要进行类型转换,转为tensor类型。
trainX, testX, trainY, testY = train_test_split(data,y, test_size=0.2, random_state=42)trainX = torch.from_numpy(trainX)trainX = DataLoader(trainX,batch_size=batch_size,shuffle=True)testX = torch.from_numpy(testX)testX = DataLoader(testX,batch_size=batch_size,shuffle=False)trainY = torch.from_numpy(trainY)trainY = DataLoader(trainY,batch_size=batch_size,shuffle=True)testY = torch.from_numpy(testY)testY = DataLoader(testY,batch_size=batch_size,shuffle=False)
5、模型定义
模型定义是对于我们上面所画框架的代码实现,其中卷积核的大小是3*3,卷积之后使用了最大池化,这一步的作用是提取重要信息,可以去掉不重要的信息,减少计算开销。ReLU激活函数的核心作用是通过非线性引入、梯度稳定性、计算高效性和稀疏性,使得神经网络能够有效学习复杂模式。MaxPool的核心作用是通过降维、提取主要特征和增强模型的鲁棒性来提升网络性能。Dropout通过随机失活神经元,强制网络学习更鲁棒的特征,有效防止过拟合并提升泛化能力。
classCNN_XSS_Net(nn.Module): def__init__(self): super(CNN_XSS_Net, self).__init__() self.cnn = nn.Sequential( nn.Conv2d(1,64,3), nn.ReLU(), nn.MaxPool2d(2), nn.Dropout(0.3), nn.Conv2d(64,128,3), nn.ReLU(), nn.Conv2d(128,256,3), nn.MaxPool2d(2), nn.Dropout(0.3), nn.Relu(), ) self.fc1 = nn.Linear(123904,256) self.fc2 = nn.Linear(256,128) self.fc3 = nn.Linear(128, 64) self.fc4 = nn.Linear(64, 2) def forward(self,x): x = torch.tensor(x, dtype=torch.float32) cnn_res = self.cnn(x) # print(cnn_res.shape) #128*256*22*22 cnn_res = cnn_res.view(cnn_res.size(0), -1) # print(cnn_res.shape) #128*123904 f1 = self.fc1(cnn_res) f2 = self.fc2(f1) f3 = self.fc3(f2) f4 = self.fc4(f3) return f4
Maxpool示意图
Dropout示意图
如果觉得全连接层第一层的输入尺寸计算复杂的话,可以直接询问deepseek,deepseek会可视化计算整个过程,非常方便。
6、实例化模型
优化器使用Adam优化器,Adam优化器有着自适应学习率、快速收敛等优点,可以显著提高模型的训练效率。损失函数使用交叉熵损失函数,交叉熵损失函数能够衡量模型预测的概率分布与真实标签分布之间的差异,并提供良好的梯度信息,有助于模型更快地收敛。
model = CNN_XSS_Net()optimizer = optim.Adam(model.parameters(),0.001)criterion = nn.CrossEntropyLoss()
7、定义训练函数
deftrain(model,trainX,trainY,optimizer,epochs): model.train() i=0for data, target in zip(trainX,trainY): i+=1 optimizer.zero_grad() output = model(data) loss = criterion(output, target) loss.backward() optimizer.step()if i % 50 == 0:print("Train Epoch : {} t Loss : {:.6f}".format(epochs, loss.item()))
8、定义测试函数
deftest_model(model,testX,testY): model.eval() correct = 0.0 test_loss = 0.0with torch.no_grad():for data,target in zip(testX,testY): output = model(data) test_loss+=F.cross_entropy(output,target).item() pred = output.max(1,keepdim=True)[1] correct += pred.eq(target.view_as(pred)).sum().item() test_loss /= len(testX.dataset) print("Test ---- Average loss : {:.4f},Accuracy : {:.3f}n".format(test_loss,100.0*correct/len(testX.dataset)))
9、结果展示
batch_size大小设置为50,epoch设置为100,通过100轮次的模型训练可以看到损失在逐渐收敛,测试集的识别准确率大约在99.01%。
0x05 思考
从上述的检测实验中引出以下两个层面的思考,第一个层面是模型训练层面的思考,主要表现在以下几个方面:
数据质量与分布偏移,主要表现在:
-
不平衡性:正常请求远多于攻击请求,导致模型容易偏向多数类。
-
动态性:攻击者会不断变化攻击载荷(如编码、混淆、变形),导致训练数据与实际攻击分布不一致。
-
噪声干扰:正常请求中可能包含与攻击模式相似的合法脚本(如网站本身的JavaScript代码)。
特征工程的复杂性,主要表现在:
-
特征选择困难:XSS攻击的特征可能包括URL参数、请求头、JavaScript代码结构等,但关键特征(如恶意函数调用、编码模式)可能被攻击者隐藏或混淆。
-
高维稀疏性:文本特征(如n-gram)可能产生高维稀疏向量,增加模型训练难度。
对抗样本与模型鲁棒性,主要表现在:
-
攻击者可能通过微小修改(如添加无害字符、改变编码方式)绕过模型检测,导致模型在对抗样本前失效。
第二个是从卷积神经网络识别XSS攻击引申出关于AIGC内容安全的思考,主要有以下几个方面:
-
卷积神经网络通过局部特征(例如关键词、编码模式)检测XSS攻击,而AIGC的内容安全同样需要从生成内容中提取潜在威胁特征(例如隐含的诱导性文本、对抗性提示等),XSS主要针对文本,但AIGC可生成图像、音频、视频等多模态内容,其中可能隐藏更复杂的攻击,如何统一跨模态的安全检测框架?
-
XSS攻击多为显性代码,而AIGC可能生成看似无害但隐含社会工程学攻击的内容,如何通过语义理解捕捉深层意图?
-
XSS攻击的变体(如混淆编码、语法变形)需要卷积神经网络动态更新模型权重,类似地,AIGC生成的恶意内容可能通过对抗性输入绕过检测。在XSS检测中,攻击者试图绕过卷积神经网络的检测规则;在AIGC中,恶意用户可能通过精心设计的提示词诱导模型生成有害内容(例如钓鱼邮件、虚假信息等),如何构建对抗训练框架,让AIGC模型具有更高的鲁棒性?
-
卷积神经网络依赖大量标注数据,而AIGC的训练数据可能隐含偏见或敏感信息,导致生成内容泄露隐私或放大歧视,如何确保训练数据的清洁性?
-
最后,如果面对从未见过的XSS变种或AIGC生成的新型攻击,应该如何通过小样本学习或元学习提升模型的泛化能力?
0x06 参考资料
-
http://cjc.ict.ac.cn/online/onlinepaper/zl-2018911171138.pdf
-
https://owasp.org/www-community/attacks/xss/
-
https://www.geeksforgeeks.org/introduction-convolution-neural-network
原文始发于微信公众号(安全驾驶舱):【AI安全】从XSS文本检测到模型安全思考
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论