Fortify检测到String.format处存在格式化字符串DoS漏洞,咨询修复方案
Fortify格式化字符串类DoS告警可落地方案
告警根因
当前代码中String.format的第一个入参(格式串)取自数据库存储的错误详情值,一旦存储层的错误消息被篡改、或攻击者可通过可控的code值关联到被污染的消息文本,就会形成格式串外部可控的风险:轻则因非法格式符、参数数量不匹配抛出未捕获异常引发服务不稳定,重则通过超大格式符占用内存造成DoS,甚至借助格式串漏洞泄露运行时敏感信息。
具体修复手段
- 从链路层面切断格式串可控来源
应用启动阶段,将所有错误码对应的合法消息文本从可信源(项目内置配置文件、受控配置中心的只读配置)加载到本地静态内存Map,运行时直接从本地缓存匹配取消息,不再实时从数据库读取未校验的消息值。哪怕攻击者篡改了数据库中存储的message字段,运行时使用的仍是可信源加载的合法格式串,从根源消除可控风险。 - 增加格式串合法性白名单校验
对所有要传入format方法的格式串做逐段校验,仅放行业务约定的占位符类型(比如只允许%s、%d这类实际用到的占位符),拦截所有非白名单内的特殊格式符(比如%1$、%<、%#x这类可能触发异常或非预期行为的格式)。校验不通过的消息直接替换为固定通用提示,不参与format执行。 - 封装安全的format替代方法做兜底
不要直接调用原生String.format,自己封装带防护逻辑的工具方法,覆盖所有可能的风险场景:private String safeErrorFormat(String rawFormat, Object... args) { // 1. 限制格式串最大长度,避免超大字符串占用过多内存 String clippedFormat = rawFormat.length() > 2048 ? rawFormat.substring(0, 2048) : rawFormat; try { // 2. 执行原生format,捕获所有格式相关的运行时异常 return String.format(clippedFormat, args); } catch (java.util.IllegalFormatException e) { // 3. 捕获非法格式、参数不匹配等异常,不向外抛出,返回固定兜底文案 return "系统处理提示"; } } - 增加参数匹配校验
执行format前,统计格式串内的占位符数量,和传入的参数数组长度做快速比对,数量不匹配的直接跳过format流程,避免攻击者通过构造多占位符的格式串频繁触发参数不匹配异常消耗应用资源。
无效修复的避坑提醒
不要试图通过给Fortify加扫描例外来消除告警,也不要只靠单纯的try-catch包住原方法就当修复完成——一旦格式串被篡改,catch只能挡住异常抛出,但挡不住攻击者构造超长格式串造成的内存占用飙升类DoS问题。
内容的提问来源于stack exchange,提问作者Organik Street
相关产品推荐
相关产品推荐

