[实践总结] 限制正则表达式匹配次数/时间 防止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] 限制正则表达式执行时间

相关推荐
郝学胜-神的一滴13 分钟前
深入理解前端 Axios 框架:特性、使用场景与最佳实践
开发语言·前端·程序人生·软件工程
jf加菲猫13 分钟前
条款11:优先选用删除函数,而非private未定义函数
开发语言·c++
歪歪10019 分钟前
什么是TCP/UDP/HTTP?
开发语言·网络·网络协议·tcp/ip·http·udp
WangMing_X26 分钟前
C#上位机软件:2.1 .NET项目解决方案的作用
开发语言·c#
沧澜sincerely40 分钟前
Redis 键空间 & 五大类型
java·redis·docker
Pocker_Spades_A40 分钟前
Python快速入门专业版(四十六):Python类的方法:实例方法、类方法、静态方法与魔术方法
开发语言·python
2351642 分钟前
【LeetCode】3. 无重复字符的最长子串
java·后端·算法·leetcode·职场和发展
nandao15844 分钟前
springBoot 集成Neo4j 实战演示
java·spring boot·neo4j
零雲1 小时前
java面试:可以讲一讲sychronized和ReentrantLock的异同点吗
java·开发语言·面试
没有bug.的程序员1 小时前
SQL 执行计划解析:从 EXPLAIN 到性能优化的完整指南
java·数据库·sql·性能优化·explain·执行计划