CISCN2025 半决赛 AWDP rng-assistant
字数 1552 2025-08-29 08:29:59

CISCN2025 半决赛 AWDP rng-assistant 题目分析与教学文档

题目概述

这是一个基于Flask框架的Web应用,结合了Redis缓存和"大模型"通信功能,存在多个安全漏洞点,主要涉及Redis未授权访问和格式化字符串漏洞。

系统架构分析

组件结构

  • start.sh: 启动脚本,通过redis-cli config set save ""禁用Redis的RDB持久化
  • default.pymath-v1.py: 分别监听两个端口,处理来自Flask的请求(随机返回字符串)
  • Flask: 监听8000端口,提供Web服务
  • Nginx: 监听80端口作为反向代理

请求处理流程

  1. Nginx接收外部请求
  2. 反向代理到Flask应用
  3. Flask处理请求,可能涉及Redis交互或与"大模型"通信

安全机制分析

身份验证机制

  • 默认给非本地连接的HTTP请求添加X-User-Role: guest请求头
  • 可通过自行传递X-User-Role头绕过此限制

功能模块

  1. 用户注册
  2. 用户登录
  3. 用户提问
  4. Redis未授权访问

漏洞点分析

1. Redis未授权访问漏洞

漏洞原理:

  • 系统通过socket连接与"大模型"通信,并设置了回答的缓存机制
  • 提示词和对应模型作为key,将"大模型"的回答缓存到Redis中
  • 管理员可以修改模型通信端口
  • 攻击者可将通信端口修改为Redis默认端口6379,实现Redis未授权访问

利用步骤:

  1. 获取管理员权限
  2. 修改模型通信端口为6379
  3. 通过该端口直接与Redis交互

2. 格式化字符串漏洞

漏洞位置:

  • PromptTemplate#get_template方法
    • 首先从Redis寻找模板,找到则直接返回
    • 否则在static/prompts目录下查找
  • 关键代码: PromptTemplate.get_template(template_id).format(t=self)
    • 将类对象self传入格式化字符串的上下文

触发路径:

  • /ask路由调用generate_prompt但未传prompt_id
  • 通过往Redis增加键prompt:math-v1,获取模板时可设置格式化字符串

利用方法:

  1. 通过Redis未授权访问或其它方式设置prompt:math-v1键值
  2. 设置包含恶意格式化字符串的模板
  3. 触发/ask路由执行格式化字符串攻击

3. Flag获取

  • Flag存储在from flag import FLAG引入的变量中
  • 通过格式化字符串漏洞可能直接读取或间接获取FLAG值

修复建议

  1. Redis端口修改限制:

    • 禁止将模型通信端口修改为Redis默认端口6379
    • 实施端口范围检查或黑名单机制
  2. 格式化字符串安全修复:

    • 修改PromptTemplate.get_template(template_id).format(t=self)代码
    • 不将self对象传入格式化字符串上下文
    • 使用安全的模板渲染方式,如Jinja2的沙箱环境
  3. 其他安全加固:

    • 实施Redis认证
    • 限制Redis绑定IP
    • 对用户输入进行严格过滤

攻击利用链示例

  1. 利用身份验证缺陷获取管理员权限
  2. 修改模型通信端口为6379
  3. 通过Redis未授权访问设置恶意模板
  4. 触发格式化字符串漏洞读取FLAG

教学总结

本题展示了Web应用中常见的两类高危漏洞的组合利用:

  1. 配置不当导致的未授权访问(Redis)
  2. 代码实现缺陷导致的格式化字符串漏洞

通过本题可以学习到:

  • Redis安全配置的重要性
  • 格式化字符串漏洞的原理与利用
  • 系统组件间信任边界的安全考量
  • 权限提升与横向移动的技巧
  • 多漏洞组合利用的攻击链构建
CISCN2025 半决赛 AWDP rng-assistant 题目分析与教学文档 题目概述 这是一个基于Flask框架的Web应用,结合了Redis缓存和"大模型"通信功能,存在多个安全漏洞点,主要涉及Redis未授权访问和格式化字符串漏洞。 系统架构分析 组件结构 start.sh : 启动脚本,通过 redis-cli config set save "" 禁用Redis的RDB持久化 default.py 和 math-v1.py : 分别监听两个端口,处理来自Flask的请求(随机返回字符串) Flask : 监听8000端口,提供Web服务 Nginx : 监听80端口作为反向代理 请求处理流程 Nginx接收外部请求 反向代理到Flask应用 Flask处理请求,可能涉及Redis交互或与"大模型"通信 安全机制分析 身份验证机制 默认给非本地连接的HTTP请求添加 X-User-Role: guest 请求头 可通过自行传递 X-User-Role 头绕过此限制 功能模块 用户注册 用户登录 用户提问 Redis未授权访问 漏洞点分析 1. Redis未授权访问漏洞 漏洞原理 : 系统通过socket连接与"大模型"通信,并设置了回答的缓存机制 提示词和对应模型作为key,将"大模型"的回答缓存到Redis中 管理员可以修改模型通信端口 攻击者可将通信端口修改为Redis默认端口6379,实现Redis未授权访问 利用步骤 : 获取管理员权限 修改模型通信端口为6379 通过该端口直接与Redis交互 2. 格式化字符串漏洞 漏洞位置 : PromptTemplate#get_template 方法 首先从Redis寻找模板,找到则直接返回 否则在 static/prompts 目录下查找 关键代码: PromptTemplate.get_template(template_id).format(t=self) 将类对象 self 传入格式化字符串的上下文 触发路径 : /ask 路由调用 generate_prompt 但未传 prompt_id 通过往Redis增加键 prompt:math-v1 ,获取模板时可设置格式化字符串 利用方法 : 通过Redis未授权访问或其它方式设置 prompt:math-v1 键值 设置包含恶意格式化字符串的模板 触发 /ask 路由执行格式化字符串攻击 3. Flag获取 Flag存储在 from flag import FLAG 引入的变量中 通过格式化字符串漏洞可能直接读取或间接获取FLAG值 修复建议 Redis端口修改限制 : 禁止将模型通信端口修改为Redis默认端口6379 实施端口范围检查或黑名单机制 格式化字符串安全修复 : 修改 PromptTemplate.get_template(template_id).format(t=self) 代码 不将 self 对象传入格式化字符串上下文 使用安全的模板渲染方式,如Jinja2的沙箱环境 其他安全加固 : 实施Redis认证 限制Redis绑定IP 对用户输入进行严格过滤 攻击利用链示例 利用身份验证缺陷获取管理员权限 修改模型通信端口为6379 通过Redis未授权访问设置恶意模板 触发格式化字符串漏洞读取FLAG 教学总结 本题展示了Web应用中常见的两类高危漏洞的组合利用: 配置不当导致的未授权访问(Redis) 代码实现缺陷导致的格式化字符串漏洞 通过本题可以学习到: Redis安全配置的重要性 格式化字符串漏洞的原理与利用 系统组件间信任边界的安全考量 权限提升与横向移动的技巧 多漏洞组合利用的攻击链构建