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

相关推荐
越来越无动于衷几秒前
基于 JWT 的登录验证功能实现详解
java·数据库·spring boot·mysql·mybatis
Villiam_AY3 小时前
Redis 缓存机制详解:原理、问题与最佳实践
开发语言·redis·后端
UQWRJ4 小时前
菜鸟教程R语言一二章阅读笔记
开发语言·笔记·r语言
飛_4 小时前
解决VSCode无法加载Json架构问题
java·服务器·前端
岁忧5 小时前
macOS配置 GO语言环境
开发语言·macos·golang
朝朝又沐沐6 小时前
算法竞赛阶段二-数据结构(36)数据结构双向链表模拟实现
开发语言·数据结构·c++·算法·链表
木棉软糖6 小时前
一个MySQL的数据表最多能够存多少的数据?
java
魔尔助理顾问6 小时前
系统整理Python的循环语句和常用方法
开发语言·后端·python
Ares-Wang6 小时前
JavaScript》》JS》 Var、Let、Const 大总结
开发语言·前端·javascript
程序视点7 小时前
Java BigDecimal详解:小数精确计算、使用方法与常见问题解决方案
java·后端