leroidubuffet/cenit-propuestas
GitHub: leroidubuffet/cenit-propuestas
一个 LLM 提示词注入安全教学实验室,通过三个版本的聊天机器人演示和对比分层防护方案的实际效果。
Stars: 0 | Forks: 0
# Cenit Propuestas — 安全实验室模块 7
同一个 chatbot 的三个版本,用于演示和缓解
基于 LLM 系统中的 prompt injection 漏洞。
| 端口 | 版本 | 模型 | 演示内容 |
|--------|---------|--------|---------------|
| 8000 | `app_vulnerable.py` | Llama 3.1 8B (Groq) | System prompt 被直接拼接到 `user` 角色的 input 中。三种攻击均可成功。 |
| 8001 | `app_parcheada.py` | Claude Sonnet 4.6 | 结构化分离(`system=`) + blacklists。`DISABLE_BLACKLISTS` flag 允许单独测试每一层防护。 |
| 8002 | `app_parcheada_v2.py` | Claude Sonnet 4.6 + Haiku 4.5 | 结构化分离 + 使用 Claude Haiku 的语义 guardrails。也能抵抗规避攻击。 |
## 前置条件
- Docker 和 Docker Compose(24.0 / 2.20 或更高版本)
- 带有可用余额的 Anthropic API Key(`sk-ant-...`) — 用于端口 8001 和 8002
- Groq API Key(在 console.groq.com 免费获取) — 用于端口 8000
- Python 3.8 或更高版本(用于通过 `python3 -m json.tool` 格式化输出)
- `jq`(用于攻击脚本:`brew install jq` / `sudo apt install jq`)
- `curl`
## 步骤 0:初始配置
```
cp .env.example .env
```
编辑 `.env` 并添加这两个密钥:
```
ANTHROPIC_API_KEY=sk-ant-...
GROQ_API_KEY=gsk_...
```
Groq 密钥可在 **console.groq.com → API Keys → Create API Key** 获取(免费账号,无需信用卡)。
```
docker compose build
```
## 步骤 1:攻击易受攻击的系统
### 1.1 启动易受攻击的服务
```
docker compose up cenit-propuestas-vulnerable -d
```
在继续之前验证其是否已准备就绪:
```
curl -s http://localhost:8000/
# 应该返回:{"servicio": "Cenit Propuestas", "version": "vulnerable", ...}
```
### 1.2 发起攻击
```
./attacks/attack_1_extraccion_rol.sh
./attacks/attack_2_suplantacion.sh
./attacks/attack_3_simulacion_admin.sh
```
这三次攻击都应该泄露内部费率或确认虚假操作。
将结果记录在 `EXERCISE_NOTES.md` 中。
## 步骤 2:应用防御并检查其效果
### 2.1 仅使用结构化分离(不含 blacklists)
```
docker compose down
DISABLE_BLACKLISTS=true docker compose up cenit-propuestas-parcheado -d
```
验证其是否已准备就绪:
```
curl -s http://localhost:8001/
# 应该返回:{..., "blacklists_activas": false}
```
对已修补的服务重复攻击:
```
ENDPOINT=http://localhost:8001/chat ./attacks/attack_1_extraccion_rol.sh
ENDPOINT=http://localhost:8001/chat ./attacks/attack_2_suplantacion.sh
ENDPOINT=http://localhost:8001/chat ./attacks/attack_3_simulacion_admin.sh
```
三种攻击均被拦截。模型拒绝了它们,因为 system prompt
是通过 `system=` 字段以结构化权威传递的,而不是作为可以被覆盖的
用户文本。没有任何激活的过滤器:抵抗力
完全由结构化分离提供。
### 2.2 添加 blacklists
```
docker compose down
docker compose up cenit-propuestas-parcheado -d
```
验证其是否已准备就绪:
```
curl -s http://localhost:8001/
# 应该返回:{..., "blacklists_activas": true}
```
重复攻击:
```
ENDPOINT=http://localhost:8001/chat ./attacks/attack_1_extraccion_rol.sh
ENDPOINT=http://localhost:8001/chat ./attacks/attack_2_suplantacion.sh
ENDPOINT=http://localhost:8001/chat ./attacks/attack_3_simulacion_admin.sh
```
三种攻击均被拦截。在日志中查看警报:
```
docker compose logs cenit-propuestas-parcheado | grep ALERTA
```
### 2.3 绕过 blacklists
无需更改已启动的服务:
```
ENDPOINT=http://localhost:8001/chat ./attacks/attack_4_evasion.sh
```
这三个变体(不同语言、同义词、间接比例)绕过了
input 过滤器并到达了模型。如果模型包含列表中的术语,output 过滤器可以捕获
响应;在这种情况下,响应
将是 "No puedo responder a esa pregunta." (我无法回答这个问题),而不是泄露的信息。
教训是 blacklists 在两层中都很脆弱:已知词汇
是有限的,任何重新表述都可以绕过它。
## 步骤 3(附加):使用 Haiku 的语义 guardrails
```
docker compose down
docker compose up cenit-propuestas-parcheado-v2 -d
```
验证其是否已准备就绪:
```
curl -s http://localhost:8002/
```
六种攻击(3 种原始攻击 + 3 种规避攻击)都应该被拦截:
```
ENDPOINT=http://localhost:8002/chat ./attacks/attack_1_extraccion_rol.sh
ENDPOINT=http://localhost:8002/chat ./attacks/attack_2_suplantacion.sh
ENDPOINT=http://localhost:8002/chat ./attacks/attack_3_simulacion_admin.sh
ENDPOINT=http://localhost:8002/chat ./attacks/attack_4_evasion.sh
```
blacklist 和语义 guardrail 之间的直接对比:
```
# 绕过 blacklist
ENDPOINT=http://localhost:8001/chat ./attacks/attack_4_evasion.sh
# 被 Haiku guardrail 阻止
ENDPOINT=http://localhost:8002/chat ./attacks/attack_4_evasion.sh
```
## 停止服务
```
# 停止所有 contenedores(保留它们以便重新启动)
docker compose stop
# 停止并删除 contenedores
docker compose down
# 停止并删除 contenedores、imágenes 和 volúmenes
docker compose down --rmi all
```
## 附加文档
| 文件 | 内容 |
|---------|-----------|
| `EXERCISE_NOTES.md` | 供学生记录结果和反思的模板 |
| `guia_docente.md` | 包含时间、各阶段说明和 troubleshooting 的会话指南 |
| `notas_diseno.md` | 变体 B 的技术决策:为何更好,为何更差,如何绕过该补丁 |
标签:Docker, Sysdig, 安全防御评估, 安全防护, 版权保护, 生成式AI, 索引, 请求拦截, 逆向工具