Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/php/260.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 装饰哈希映射添加随机性以防止(D)DoS_Java_Php_Hashmap_Denial Of Service - Fatal编程技术网

Java 装饰哈希映射添加随机性以防止(D)DoS

Java 装饰哈希映射添加随机性以防止(D)DoS,java,php,hashmap,denial-of-service,Java,Php,Hashmap,Denial Of Service,编辑顺便说一句,这里的解决方法是重用所有现有的HashMap(如ConcurrentHashMap等),而不是完全重新发明轮子。使用随机散列函数(如Perl)的语言可以抵御这种攻击 鉴于最近在几个hashmap实现(已知会影响Java Web服务器,但也会影响PHP和其他)中使用已知缺陷的破坏性DDoS,Apache Tomcat刚刚推出了一个补丁形式的“修复”,允许对POST请求中允许的最大参数数设置上限(顺便说一句,将你的Tomcat补丁到6.0.35+或7.0.23+版本) (D)DoS显

编辑顺便说一句,这里的解决方法是重用所有现有的HashMap(如ConcurrentHashMap等),而不是完全重新发明轮子。使用随机散列函数(如Perl)的语言可以抵御这种攻击

鉴于最近在几个hashmap实现(已知会影响Java Web服务器,但也会影响PHP和其他)中使用已知缺陷的破坏性DDoS,Apache Tomcat刚刚推出了一个补丁形式的“修复”,允许对POST请求中允许的最大参数数设置上限(顺便说一句,将你的Tomcat补丁到6.0.35+或7.0.23+版本)

(D)DoS显然基本上利用了这样一个事实:字符串可以被精心设计,这样它们在散列时就会发生冲突,而且许多Web服务器“愚蠢地”将键/值参数放在(断开的)散列映射中

我想知道是否有可能在HashMap{String,String}周围编写一个修饰符,以便向每个字符串添加一个随机(从受攻击的角度来看是随机)值,如下所示:

... get( String s ) {
    return wrappedBrokenMap.get( s + crunch(s );
}

... put( String key, String value ) {


  wrappedBrokenMap.put( s + crunch(s), value );
}
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);
    }
}
下面是crunch(…)的一个实现(这只是一个示例,重点是:攻击者不知道该实现):

如果对于任何字符串,crunch返回一个攻击者无法猜到的可复制字符串,则DDoS攻击已被有效阻止,对吗


这行得通吗?

我想当它到达您的代码时(您可以在代码中进行上述更改),处理POST请求的底层库已经完成了哈希处理。因此,不,我认为它行不通。

为了保证更改是全局的,我将使用类似这样的方法创建一个修补字符串

// from java.lang.String
public int hashCode() {
    int h = hash;
    if (h == 0 && count > 0) {
        h = MY_STARTING_VALUE;
        int off = offset;
        char val[] = value;
        int len = count;

        for (int i = 0; i < len; i++) {
            h = MY_PRIME*h + val[off++];
        }
        hash = h;
    }
    return h;
}
//来自java.lang.String
公共int hashCode(){
int h=散列;
如果(h==0&&count>0){
h=我的\u开始\u值;
int off=偏移量;
char val[]=值;
int len=计数;
对于(int i=0;i
问题是有些库依赖于hashCode的实现,这是一种特殊的方式。如果您不使用这样的库,这保证了使用字符串的每一段代码都会被修补


使用“crush”或seed的问题是,首先需要知道它的值才能执行查找。如果使用随机值,则必须轮询每个可能的键,以获得一个听起来效率不高的值

如果您担心最坏情况下的性能,可以使用TreeMap。最典型的最坏情况下的性能是O(logn)来执行插入/查找


如果您真的担心这一点,您可以将String类与您自己的hashCode()一起使用,或者可以覆盖String的内置hashCode或HashMap使用的值

如果对于任何字符串,crunch返回一个攻击者无法猜到的可复制字符串,则DDoS攻击已被有效阻止,对吗

基本上,这就是对密码哈希进行salt时所做的操作(尽管原因稍有不同)。这并不能完全防止冲突攻击(如果您有一个哈希函数将任意长度的输入映射到固定长度的输出,哈希总是会发生冲突),但使用秘密salt应该会使此类攻击更加困难

一个快速的“脏”实现可能看起来像这样:

... get( String s ) {
    return wrappedBrokenMap.get( s + crunch(s );
}

... put( String key, String value ) {


  wrappedBrokenMap.put( s + crunch(s), value );
}
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);
    }
}
公共类SaltedHashMap{
私有最终映射=新HashMap();
私家最后一串盐;
公共SaltedHashMap(字符串salt){
盐=盐;
}
公共V get(字符串键){
返回地图。获取(键+盐);
}
公共void put(字符串键,V值){
地图放置(键+盐,值);
}
}

以web服务器为例,我们可以使用一个
SecureRandom
为每个传入的请求随机分配一个新的salt,这意味着即使您设法为一个请求找出一个产生冲突的输入,它也不太可能对其他请求起作用。

在7u6中添加的替代字符串哈希函数已经被重新定义与JDK.map.althashing.threshold系统属性一起从JDK 8移动。相反,包含大量冲突键的哈希箱通过将其条目存储在平衡树而不是链表中来提高性能。此JDK 8更改仅适用于HashMap、LinkedHashMap和ConcurrentHashMap

请参阅:

与其使用总是有问题的硬编码数字(开源代码至少会变得“有趣”),为什么不使用
System.millizes()
而是在启动时。这似乎是最简单的解决方案,只要哈希映射没有序列化。你有针对该攻击的链接吗?我不太明白,因为当发生冲突时,它就被解决了。我认为Java使用链接列表来冲突存储桶。@toto2确实是一种古老的攻击,但现在有一些媒体-。问题是:如果如果将数百万个对象放入一个映射中,其所有键都映射到同一个存储桶,则会得到一个始终在末尾插入的链表的性能(即O(n)插入和查找)@Voo谢谢。所以每个服务器实例都需要自己的哈希函数。@toto2:这里,这真的很糟糕:嗯?如果你想在哈希映射中查找某个东西,你需要密钥。如果你有密钥,你可以处理它-问题出在哪里?他只需要做一个简单的
key=crunch(key)
在他的类中添加/搜索数组之前获取一般解决方案。这取决于您是否希望它是随机的。随机将更难预测,但也更难预测。如果您希望向键添加种子,它应该可以工作,但不是随机的。OP使用一个
静态final
值。这不是random、 但至少它会击退“标准”攻击(如果它们存在的话)。@Peter Lawrey:我不担心。整个行业都是。Apache