CSV 公式注入是什么
导出的 CSV 文件被表格软件打开时,以等号、加号、减号或 at 符号开头的单元格内容可能被当作公式解释并执行,而不是当作普通文本。若单元格内容来自用户输入,攻击者可以借此在导出文件里埋入公式,交给查看者打开即触发。防护方式很直接:导出前对这类前缀做转义处理。
基本信息
| 触发字符 | =(等号)、+(加号)、-(减号)、@(at 符号) |
|---|---|
| 受影响的软件 | Excel、WPS、LibreOffice 等电子表格 |
| 处理时机 | 服务端生成导出内容时统一净化 |
| 处理方式 | 前置单引号或制表符,使其按文本处理 |
| 附带要求 | 文件编码按对接方约定,避免乱码引发误判 |
典型使用场景
- 用户列表导出:昵称、备注等用户可控字段
- 日志与告警导出:含用户提交的查询串与文件名
- 工单批量导出:标题与描述来自外部提交
- 报表下载:明细行中包含用户输入的分类名
- 接口对接:把数据以 CSV 形式交付给第三方系统
处理示例
处理示例
def sanitize_cell(value: str) -> str:
if value and value[0] in ('=', '+', '-', '@'):
return "'" + value # 前置单引号,表格软件按文本处理
return value
rows = [[sanitize_cell(str(c)) for c in row] for row in data]
# 导出统一走这一层,避免在业务代码里各处手工处理触发字符与处理
| 起始字符 | 风险 | 处理方式 |
|---|---|---|
| = | 被解析为公式 | 前置单引号或制表符 |
| + | 可能被解析为公式 | 同上 |
| - | 可能被解析为公式 | 同上 |
| @ | 部分软件中作为函数引用 | 同上 |
| 制表符与换行 | 单元格结构被破坏 | 统一做转义或替换 |
导出文件建议使用带 BOM 的 UTF-8 或按对接方要求的编码,并统一走净化函数,避免在不同导出路径里重复实现导致遗漏。
只对新增数据做处理是不够的:历史数据中的脏字段在下一次导出时同样会被完整带出,因此净化应放在导出环节,而不是录入环节。