《Web安全之深度学习实战》笔记:第十二章 智能扫描器(1) XSS攻击载荷

本文介绍了如何运用深度学习技术来构建智能安全扫描器,特别是针对XSS攻击载荷的生成。通过学习攻击样本,使用循环神经网络(RNN)模型,自动生成XSS载荷。传统扫描器依赖预设规则,易遗漏未知漏洞,而智能扫描器模仿人工渗透过程,提高检测效率。在数据集构建过程中,解决了文件编码问题,确保了数据读取的正确性。最后,模型训练和测试展示了不同温度参数下生成的XSS攻击字符串。

目录

一、扫描器

二、数据集

三、textfile_to_semi_redundant_sequences

四、模型构建

四、总结


        本小节讲述通过webshell载荷的生成。别看本小节的标题较为炫酷,实际上是这就是通过让机器通过学习攻击样本,使用RNN的LSMT算法自动生成XSS攻击载荷,具体的流程如下所示。

与本书第三章中使用的SequenceGenerator原理相同,具体可参考我之前的笔记。

《Web安全之深度学习实战》笔记:第三章 循环神经网络_-CSDN博客

一、扫描器

        漏洞扫描主要就是基于扫描器,扫描器是安全领域非常重要的一个工具,大多数安全公司都会有自己的扫描器产品。扫描器的原理非常简单,如图12-1所示,扫描器通过对目标网站发送攻击请求,根据应答内容判断是否存在漏洞,整个过程就是模拟黑客踩点和渗透的过程。常见的开源扫描器有Nikto、WebScarab、Burpsuite等。

        传统扫描器基于事先配置好的规则模板,发送攻击请求,然后分析应答内容,从而进一步判断是否存在漏洞。扫描器的漏洞发现能力取决于规则的丰富程度,一旦出现规则集合中不覆盖的漏洞,就无法检出,这是传统安全产品的通病。在实际的工作中,我们经常发现人工渗透可以发现大量扫描器无法发现的漏洞,排除扫描器本来就难以支持的业务逻辑漏洞,即使是常见的XSS和SQL注入漏洞也会有不少遗漏 [1] 。对比人工渗透和扫描器的扫描过程,主要差异点在于,安全工程师通过学习Web漏洞的原理,根据以往的经验,结合具体网站的实际情况展开渗透测试,人工渗透具有很强的灵活性,不像扫描器只会死板地照套模板规则。智能扫描器就可以学习人工渗透过程,如图12-2所示。 

二、数据集

        本节将使用常见的XSS攻击载荷数据集,数据集的获取方法是使用常见的Web扫描器对我们的靶场进行扫描,搜集扫描日志,提取XSS的攻击载荷,然后去重即可。

xss_data_file="../data/aiscanner/xss.txt"

三、textfile_to_semi_redundant_sequences

1、函数功能

textfile_to_semi_redundant_sequences是 TFLearn 库中的一个数据处理函数,专门用于将文本文件转换为适合训练序列生成模型(如RNN/LSTM)的序列格式,函数的核心作用是将文本文件转换为适合训练字符级语言模型的序列数据。

  • 文本读取和预处理:读取文本文件并可选地进行预处理(移除特殊字符、转换为小写等)

  • 词汇表创建:基于文本中的唯一字符创建字符级词汇表

  • 序列生成:使用滑动窗口方法生成重叠的文本序列

    • seq_maxlen 控制每个序列的长度

    • step 控制滑动窗口的步长(较小的步长会产生更多重叠序列)

  • 向量化:将字符序列转换为one-hot编码形式

2、函数参数

textfile_to_semi_redundant_sequences函数定义如下所示。

def textfile_to_semi_redundant_sequences(
    file_path, 
    seq_maxlen=25, 
    step=3, 
    max_chars=10000, 
    preprocess_text=True,
    lower=True,
    return_vocab=False
)
参数名作用
path文本文件路径
seq_maxlen每个序列的最大长度(如100个字符)
step滑动窗口步长(值越小序列重叠越多,数据量越大)
max_chars要处理的最大字符数,-1表示处理整个文件

3、函数返回值

textfile_to_semi_redundant_sequences 函数的输出包括X,Y和char_idx,具体如下所示。

  • 输入序列 (X): 固定长度的连续字符/词片段

  • 输出标签 (Y): 每个序列的下一个字符/词(即预测目标)

  • 字符索引 (char_idx): 字符到数字的映射字典

 举例,假设输入文本是 "hello world",参数为 seq_maxlen=5, step=2。

# 生成的序列示例(实际输出是one-hot形式):
X序列示例       y目标字符
"hello"       " "
"llo w"       "o"
"o wor"       "l"
" worl"       "d"

实际的输出如下所示。

# 假设小词汇表 [' ', 'd', 'e', 'h', 'l', 'o', 'r', 'w']
X[0] = [  # 序列 "hello"
  [0, 0, 0, 1, 0, 0, 0, 0],  # 'h'
  [0, 0, 1, 0, 0, 0, 0, 0],  # 'e'
  [0, 0, 0, 0, 1, 0, 0, 0],  # 'l'
  [0, 0, 0, 0, 1, 0, 0, 0],  # 'l'
  [0, 0, 0, 0, 0, 1, 0, 0]   # 'o'
]
y[0] = [1, 0, 0, 0, 0, 0, 0, 0]  # 下一个字符是空格 ' '

四、模型构建

接下来通过使用RNN的LSTM算法,特征提取字符序列。代码实现了一个基于LSTM的XSS攻击载荷生成器。首先加载或创建字符索引字典,将XSS样本转换为训练序列。构建三层LSTM网络(每层32神经元,10% Dropout),通过softmax输出层生成字符概率。使用Adam优化器训练模型后,以"/><script>为种子,生成不同随机性(温度0.1/0.5/1.0)的XSS攻击载荷,可用于安全测试场景。

  • 数据加载:读取XSS样本并建立字符索引
  • 序列生成:将文本转为训练用特征序列
  • 网络构建:使用三层LSTM+Dropout防止过拟合
  • 模型配置:Adam优化器+交叉熵损失
  • 训练过程:2轮训练+10%验证集
  • 载荷生成:基于种子字符串生成测试用例
  • 参数控制:调节temperature参数值随机生成XSS攻击载荷
def generator_xss():
    global char_idx  # 字符索引字典
    global xss_data_file  # XSS攻击样本数据文件路径
    global maxlen  # 序列最大长度

    # 加载已有的字符索引(如果存在)
    if os.path.isfile(char_idx_file):
        print('加载已有的字符索引')
        char_idx = pickle.load(open(char_idx_file, 'rb'))

    # 从文本文件生成半冗余序列
    X, Y, char_idx = textfile_to_semi_redundant_sequences(
        xss_data_file,  # 输入文件
        seq_maxlen=maxlen,  # 序列最大长度
        redun_step=3,  # 滑动窗口步长
        pre_defined_char_idx=char_idx)  # 预定义的字符索引

    # 构建LSTM神经网络
    g = tflearn.input_data([None, maxlen, len(char_idx)])  # 输入层
    g = tflearn.lstm(g, 32, return_seq=True)  # 第一层LSTM(32神经元)
    g = tflearn.dropout(g, 0.1)  # 10%的dropout
    g = tflearn.lstm(g, 32, return_seq=True)  # 第二层LSTM
    g = tflearn.dropout(g, 0.1)  # dropout
    g = tflearn.lstm(g, 32)  # 第三层LSTM
    g = tflearn.dropout(g, 0.1)  # dropout
    g = tflearn.fully_connected(g, len(char_idx), activation='softmax')  # 全连接输出层
    g = tflearn.regression(g, optimizer='adam', loss='categorical_crossentropy',
                         learning_rate=0.001)  # 回归层配置

    # 创建序列生成器
    m = tflearn.SequenceGenerator(
        g,  # 网络结构
        dictionary=char_idx,  # 字符字典
        seq_maxlen=maxlen,  # 序列最大长度
        clip_gradients=5.0,  # 梯度裁剪阈值
        checkpoint_path='chkpoint/model_scanner_poc')  # 模型保存路径

    # 训练配置
    seed = '"/><script>'  # 初始种子序列
    m.fit(X, Y, validation_set=0.1, batch_size=128,
        n_epoch=2, run_id='scanner-poc')  # 训练2个epoch
    
    # 生成测试样例(不同温度参数)
    print("-- 测试生成 --")
    print("-- temperature 0.1(保守)--")
    print(m.generate(32, temperature=0.1, seq_seed=seed))
    print("-- temperature 0.5(平衡)--")
    print(m.generate(32, temperature=0.5, seq_seed=seed))
    print("-- temperature 1.0(随机)--")
    print(m.generate(32, temperature=1.0, seq_seed=seed))

这里面textfile_to_semi_redundant_sequences函数会报错,提示gbk无法解码。

UnicodeDecodeError: 'gbk' codec can't decode byte 0x9d in position 67564: illegal multibyte sequence

我是这样解决的,我直接修改了textfile_to_semi_redundant_sequences函数,将open函数增加了使用utf-8编码,具体处理如下。

def textfile_to_semi_redundant_sequences(path, seq_maxlen=25, redun_step=3,
                                         to_lower_case=False, pre_defined_char_idx=None):
    """ Vectorize Text file """
    text = open(path,encoding='utf-8').read()
    if to_lower_case:
        text = text.lower()
    return string_to_semi_redundant_sequences(text, seq_maxlen, redun_step, pre_defined_char_idx)

 以及还要对random_sequence_from_textfile进行修改,具体如下所示。

def random_sequence_from_textfile(path, seq_maxlen):
    text = open(path,encoding='utf-8').read()
    return random_sequence_from_string(text, seq_maxlen)

五、总结

本小节实际上就是本书第三章最后一个示例在网络安全中的一个应用,较容易理解,难度不高。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mooyuan安全

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值