java中stringbuilder中Fortify的拒绝服务问题

Moh*_*han 3 java memory stringbuilder fortify

Fortify 客户端给出了字符串生成器的错误和建议,

问题代码:

StringBuilder sb=new StringBuilder();    
sb.append(request.getParameter("id"));
sb.append(request.getParameter("name"));
sb.append(request.getParameter("question"));
sb.append(request.getParameter("answer"));
Run Code Online (Sandbox Code Playgroud)

强化错误:

用户控制的数据附加到使用默认构造函数初始化的 StringBuilder 实例

将用户控制的数据附加到使用默认支持字符数组大小 (16) 初始化的 StringBuilder 或 StringBuffer 实例可能会导致应用程序在调整基础数组大小以适应用户数据时消耗大量堆内存。当数据追加到 StringBuilder 或 StringBuffer 实例时,该实例将确定支持字符数组是否有足够的可用空间来存储数据。如果数据不适合,StringBuilder 或 StringBuffer 实例将创建一个新数组,其容量至少是先前数组大小的两倍,而旧数组将保留在堆中,直到被垃圾收集。攻击者可以使用此实现细节来执行拒绝服务 (DoS) 攻击。

Fortify 建议: 使用预期附加数据大小的初始容量初始化 StringBuilder 或 StringBuffer,以减少调整后备数组大小的次数。在将数据附加到 StringBuilder 或 StringBuffer 实例之前检查数据的大小。

...
private final int BUFFER_CAPACITY = 5200;
StringBuilder sb = new StringBuilder(BUFFER_CAPACITY);
...
final String lineSeparator = System.lineSeparator();
String[] labels = request.getParameterValues("label");
for (String label : labels) {
if (label.length() + lineSeparator.length() + sb.length()<= sb.capacity()) {
sb.append(label).append(lineSeparator);
} else {
// Handle error
}
}
Run Code Online (Sandbox Code Playgroud)

对问题陈述和建议的查询:

  1. 如果垃圾收集器释放了它的内存,攻击者如何引起拒绝服务攻击?它适用吗?

  2. 我要求在字符串生成器中存储最多 0 到 12000 个字符的动态数据范围,因此,如果我使用 12000 个字符来初始化字符串生成器,那么如果我的输入只有 100 个字符串,则意味着不需要剩余 11900 长度的内存。那么在这种情况下,我真的需要设置字符串生成器容量中的最大字符数吗?或者我可以仅使用默认构造函数对输入参数进行长度验证?

这个问题有什么更好的解决方案?

Tom*_*ine 5

这是无稽之谈。

可能存在相关问题,例如:

  • 输入数据很大(尽管它似乎来自请求标头,所以应该已经受到上游限制)
  • 单个输入是空的,但有很多实例,用很少的输入数据创建合理值的所有开销 - 因此,如果您有可能不使用它,请不要分配大于默认的初始容量!
  • 如果不够小心,生成的字符串可能不明确或存在注入漏洞。

StringBuilder每当当前缓冲区耗尽时,容量至少会增加一倍,以将成本分摊到 O(n)。很StringBuilder可能比输入数据大。部分原因可能是过度分配,如果不将其转换为String. 另外,原始版本通常每个字符 1 个字节,但 Java 有 2 个字节char。如果输入被压缩,大小的爆炸可能会令人惊讶,特别是在多重压缩的情况下。

我建议您尝试对您自己的应用程序进行 DoS 攻击,尽管令人惊讶的是,我发现很少有证据表明应用程序级 DoS 攻击在野外很常见。

  • @BagusTesa 那么,你把赏金放在了错误的问题上。这个问题是“是否存在真正的问题?”,而不是“我怎样才能让 fortify 满意?” 您不能要求该问题的回答者专注于您完全不同的问题。顺便说一句,如果您的关键系统会受到长参数字符串的影响,那么您应该考虑到这些字符串甚至在字符串连接之前就已经在内存中了。此时试图解决这个问题已经太晚了。 (2认同)