[实践总结] 限制正则表达式匹配次数/时间 防止DoS攻击

思路

1、优化正则表达式

2、正则表达式无法优化的话,可以考虑限制匹配次数,或者限制匹配时间

限制 匹配次数

csharp 复制代码
public class CountedCharSequence implements CharSequence {
    private final CharSequence charSequence;
    private long count;

    public CountedCharSequence(CharSequence charSequence, long count) {
        this.charSequence = charSequence;
        this.count = count;
    }

    @Override
    public String toString() {
        return charSequence.toString();
    }

    @Override
    public int length() {
        return charSequence.length();
    }

    @Override
    public char charAt(int index) {
        if (index <= 0) {
            throw new IllegalArgumentException("Regex match over max " + count + " times");
        }
        count--;
        return charSequence.charAt(index);
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return charSequence.subSequence(start, end);
    }
}

模拟Dos攻击

csharp 复制代码
String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

long start = System.nanoTime();
Pattern.compile("^(a+)+$").matcher(str).matches();
System.out.println(((System.nanoTime() - start)) + " nano seconds");

执行用时
1399200 nano seconds

超过 1亿 就会报错

csharp 复制代码
long start1 = System.nanoTime();

try {
    Pattern.compile("^(a+)+$").matcher(new CountedCharSequence(str, 100_000_000)).matches();
} catch (Exception e) {
    System.out.println(e.getMessage());
}

System.out.println(((System.nanoTime() - start1)) + " nano seconds");

执行用时
Regex match over max 100000000 times
601800 nano seconds

限制 匹配时间

csharp 复制代码
import java.util.regex.Pattern;

public final class TimedCharSequence implements CharSequence {
    private final CharSequence sequence;
    private final long timestamp;

    public TimedCharSequence(CharSequence sequence, long nanoseconds) {
        this.sequence = sequence;
        this.timestamp = System.nanoTime() + nanoseconds;
    }

    @Override
    public String toString() {
        return sequence.toString();
    }

    @Override
    public int length() {
        return sequence.length();
    }

    @Override
    public char charAt(int index) {
        if (timestamp < System.nanoTime()) {
            throw new IllegalStateException("Regex match timeout");
        }
        return sequence.charAt(index);
    }

    @Override
    public CharSequence subSequence(int start, int end) {
        return sequence.subSequence(start, end);
    }
}

模拟Dos攻击

csharp 复制代码
String str = "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa";

long start = System.nanoTime();
Pattern.compile("^(a+)+$").matcher(str).matches();
System.out.println(((System.nanoTime() - start)) + " nano seconds");

执行用时:
1385400 nano seconds

超过 给定时间间隔就报错

csharp 复制代码
long start1 = System.nanoTime();

try {
    Pattern.compile("^(a+)+$").matcher(new TimedCharSequence(str, 10_000)).matches();
} catch (Exception e) {
    System.out.println(e.getMessage());
}

System.out.println(((System.nanoTime() - start1)) + " nano seconds");

执行用时:
Regex match timeout
123100 nano seconds

Ref

Ref 限制正则表达式执行时间

相关推荐
传奇开心果编程10 小时前
【Rust入门知识点学与练】第24课:Trait 基础
开发语言·学习·rust
wuminyu13 小时前
Kafka中sendfile与mmap实现机制解析
java·linux·c语言·jvm·c++
考虑考虑14 小时前
Java实现hmacsha256加密算法
java·后端·java ee
captain37615 小时前
▲网络原理(2)-TCP
java·服务器·网络·tcp/ip·java-ee
MetaLite15 小时前
SpringBoot接口分层规范-外网网关内部服务与参数边界
java·数据库·spring boot
Co_Hui15 小时前
Java 线程状态
java
土司大王15 小时前
LeetCode hot100——35.搜索插入位置:Java 二分模板、左闭右开区间与插入点分析
java·算法·leetcode
言乐616 小时前
Python加速器4跨境网络加速器
运维·服务器·开发语言·网络·python
土司大王16 小时前
LeetCode hot100——34.在排序数组中查找元素的第一个和最后一个位置:Java 二分模板、边界分析
java·算法·leetcode
金金计较.16 小时前
Go语言-3
java·开发语言·golang