编辑 顺便说一句,这里的解决方法是重用所有现有的 HashMap(如 ConcurrentHashMap 等),而不是完全重新发明轮子。使用随机散列函数的语言(如 Perl)可免受此攻击。
鉴于最近使用几个 hashmap 实现中的已知缺陷(已知影响 Java 网络服务器,但也影响 PHP 和其他)的 DDoS,Apache Tomcat 刚刚以补丁的形式推出了“修复”允许对 POST 请求中允许的最大参数数量设置上限(将 Tomcat 修补到 6.0.35+ 或 7.0.23+ btw)。
(D)DoS 显然主要是利用这样一个事实,即可以制作字符串,以便它们在散列时发生碰撞,并且许多网络服务器“愚蠢地”将键/值参数放入(损坏的)散列图中。
我想知道是否可以围绕 HashMap{String,String} 编写一个装饰器,以便向每个字符串添加一个随机值(从被攻击的角度来看是随机的)值被添加到字符串中,比如这个:
... get( String s ) {
return wrappedBrokenMap.get( s + crunch(s );
}
... put( String key, String value ) {
wrappedBrokenMap.put( s + crunch(s), value );
}
这里是 crunch(...) 的一个实现(这只是一个例子,重点是:攻击者不知道实现):
private static final int MY_MAGICAL_NUMBER = 0x42BABE; // attacker doesn't know that number
private static String crunch( String s ) {
return s.length + "" + MY_MAGICAL_NUMBER;
}
如果对于任何字符串 crunch(s) 返回一个攻击者无法猜测的可重现字符串,那么 DDoS 攻击是否已被有效阻止,对吗?
那行得通吗?
最佳答案
If for any String s crunch(s) returns a reproducible String that the attacker cannot guess, the DDoS attack has effectively been prevented right?
基本上,这就是您在对密码哈希值加盐时所做的(尽管原因略有不同)。它不能完全防止碰撞攻击(如果你有一个散列函数将任意长度的输入映射到固定长度的输出,散列总是会发生碰撞),但是使用 secret 盐应该会使这种攻击更加困难.
快速的'n'dirty 实现看起来像这样:
public class SaltedHashMap<V> {
private final Map<String, V> map = new HashMap<>();
private final String salt;
public SaltedHashMap(String salt) {
this.salt = salt;
}
public V get(String key){
return map.get(key + salt);
}
public void put(String key, V value) {
map.put(key + salt, value);
}
}
以 Web 服务器为例,我们可以使用 SecureRandom
为每个传入请求随机生成一个新的盐,这意味着即使您设法为一个请求找出了产生冲突的输入,它极不可能适用于其他请求。
关于java - 装饰一个 HashMap 添加随机性以防止 (DDoS,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8669414/