如何验证用户输入的Perl正则表达式是否合法有效?
Perl正则表达式合法性安全验证方案
验证用户提交的Perl正则时,核心要规避的风险是Perl正则支持嵌入可执行代码的特性,只要提前禁用相关特性,就可以安全完成校验。
安全验证方法
方法1:Perl原生编译校验(最准确,100%兼容Perl正则语法)
这是最稳妥的方案,通过禁用正则代码执行特性后尝试编译正则来判断合法性,不会触发任何用户可控的代码执行:
- 首先开启
no re 'eval'配置,该配置会完全拦截正则中嵌入的(?{ ... })、??{ ... }等代码执行结构,编译时直接抛出错误而不会执行代码 - 用块级
eval尝试编译正则,捕获编译异常判断合法性,参考代码如下:
use strict; use warnings; no re 'eval'; # 必须开启,禁止正则内部执行任意代码 sub validate_perl_regex { my ($regex_str) = @_; # 块级eval仅尝试编译正则,不会执行用户输入内容 my $compile_success = eval { my $re = qr/$regex_str/; 1; }; return $compile_success ? (1, undef) : (0, $@); } # 测试示例正则 my @test_regexes = ( '\b[Bb]anana\b', '\s*Apples[BANANA]\s+', '(?{ system("恶意命令") })' # 恶意正则示例,会被拦截 ); foreach my $r (@test_regexes) { my ($is_valid, $err_msg) = validate_perl_regex($r); if ($is_valid) { print "正则「$r」合法\n"; } else { print "正则「$r」非法,错误信息:$err_msg\n"; } }
方法2:白名单语法校验(适合非Perl环境使用)
如果你只需要用到基础正则特性,不需要Perl的高级扩展语法,可以自己实现白名单校验,拦截所有风险结构:
- 仅允许常用的基础语法:普通字符、
\d/\s/\w等常规转义、[]字符组、()普通分组/非捕获分组(?:)、^/$/\b锚点、*/+/?/{m,n}量词、基础预查(?=/(?<=/(?!/(?<! - 禁止所有以
(?开头的其他扩展结构、禁止\N/\p等复杂转义
这种方法不需要依赖Perl运行时,可在任意语言中实现,适合跨环境校验场景。
必须规避的风险操作
- 不要使用字符串形式的
eval编译正则,极易触发代码注入 - 不要在开启
use re 'eval'的情况下编译用户输入的正则 - 不要给正则添加
/e、/ee修饰符,这类修饰符会将匹配/替换内容作为代码执行
内容的提问来源于stack exchange,提问作者Gordon
相关产品推荐
相关产品推荐

