正则表达恶意代码

极客

正则表达式的“温柔陷阱”:当恶意代码披上合法外衣,我差点就信了!

哎,兄弟们,今天咱们得好好聊聊正则表达式这玩意儿,说实话,我写代码这么多年,自认为对正则表达式算是门儿清了,但直到前几天,我在一个安全日志分析项目里,亲眼目睹了一段看起来人畜无害的正则表达式,竟然成了恶意代码的“完美伪装”——那一刻,我后背是真的发凉啊!你说气不气人?

正则表达式?不就是个匹配工具吗?咋就成恶意代码的帮凶了?

先别急,我跟你讲,这事儿真没你想的那么简单,咱们平时用正则表达式,无非就是匹配个邮箱、电话号码、IP地址啥的,觉得它就是个“文本匹配小助手”。但你知道吗?在某些“高手”眼里,正则表达式引擎本身就是个“沙盒”,而里面的量词、回溯、断言,全都是可以利用的“漏洞开关”!

拿我之前遇到的那个案例来说吧,攻击者构造了一个超复杂的嵌套正则,表面上是在校验用户输入的“日期格式”,实际上呢?它利用正则引擎里的灾难性回溯(Catastrophic Backtracking),让服务器CPU瞬间飙到99%,这跟分布式拒绝服务攻击(DDoS)有啥区别?更绝的是,他们把这段正则用base64编码后藏在配置文件里,你若不仔细看,还以为是正常的配置项呢!哎呀,这不就是“挂羊头卖狗肉”嘛!

恶意代码的“寄生”:它们是怎么藏进正则里的?

你有没有想过,为什么安全软件有时候扫不出问题?我告诉你,因为恶意代码根本不走寻常路!它们不写在脚本文件里,而是直接“画”在正则字符串里,攻击者会在正则里插入形如(?{system('cat /etc/passwd')})这样的Perl兼容正则(PCRE)代码注入功能,要是你的程序恰好用了PCRE引擎,且没有禁用e修饰符,那完蛋了,这串正则一执行,你的服务器就像脱光了衣服站在大街上——啥秘密都守不住!

我还见过更损的招儿,用正则的“零宽断言”来隐藏恶意载荷,啥意思呢?就是匹配位置,但不消耗字符,攻击者把恶意代码拆成无数小段,塞进断言的括号里,通过多次匹配把数据拼凑起来再执行,这波操作,简直是“巧妙他妈给巧妙开门——巧妙到家了”!你说,这谁能防得住?

别怕!咱们也有“反杀”的招儿

咱也不是吃素的!既然知道了它们的套路,那我也得给你支两招,免得你哪天也掉进这个坑里。

第一招:禁用危险函数。 你写代码的时候,千万别图省事儿就开启e修饰符(eval),用Python的话,尽量别用re模块里那些带exec的第三方包,我上次写支付接口的签名校验,就直接把正则引擎换成纯DFA的,虽然速度慢点,但安全啊!

第二招:正则公式化审查。 你以为你写的是^[a-z0-9]+$就安全了?太天真了!恶意代码最擅长藏在字符类里了,比如[^\x00-\x7F]这种,看起来是匹配非ASCII字符,但配合\x转义,后面能跟一串十六进制shellcode!凡是涉及用户输入的正则,我建议你都跑一遍PCRE静态扫描工具,把那些可疑的“递归匹配”“条件子组”给揪出来。

第三招:输入长度限制+白名单。 这可是我血的教训啊!以前我这边有过一个接口,因为没限制输入长度,攻击者塞了10万字符的超长正则,直接让引擎内存溢出崩溃了,从那以后,我规定所有输入必须小于256字节,且只允许字母数字和少数符号,嘿,你还真别说,那些“花活儿”正则直接失效了,因为它们都太长啦!

最后说点掏心窝子的话

写这篇文章,我是真的希望各位同行能对正则表达式多留个心眼儿,它就像一把瑞士军刀,用好了是神器,用歪了就是凶器,别等到线上出故障了,或者被黑得裤衩都不剩了,才后悔当初没认真看那几行正则代码。

哎,其实我每次看到安全报告里那些“正则表达式导致的远程代码执行(RCE)”漏洞,心里都特别不是滋味,你说,咱们辛辛苦苦写的业务逻辑,就因为一个偷懒的正则,全毁了,值得吗?所以啊,以后写正则的时候,多想想“这个会不会被利用?”,脑子里多根弦,总没错!

哦对了,如果你也对网络安全、正则表达式防注入这些话题感兴趣,想跟我深入聊聊,或者想学点系统性的防御技巧,欢迎加我的QQ:2367370895(添加时备注“正则安全”),咱们可以一起探讨,一起避坑!

正则表达恶意代码

行了,今天就唠到这儿,我得去再检查一遍我那埋了好几层嵌套正则的代码了,实在是怕了怕了……你也赶紧去看看吧,别等到被入侵了才想起来!哭都来不及哟!

文章版权声明:除非注明,否则均为咸鱼-即刻攻防原创文章,转载或复制请以超链接形式并注明出处。

目录[+]

取消
微信二维码
微信二维码
支付宝二维码