OGNL注入绿色版——我踩过的那个坑,今天全盘倒给你
哎,说起来你们可能不信,我第一次碰到 OGNL注入绿色版 这玩意儿的时候,整个人是懵的,那会儿还在做一Java Web项目,Struts2框架,老版本,你懂的,某天安全扫描报告一出来,红彤彤一片,其中一条就是OGNL注入,我当时心里想:啥玩意儿?OGNL不是表达式语言吗,怎么还能注入?后来一查,好家伙,这事儿可真不简单。

先别急,我知道你可能跟我当初一样,听到“OGNL注入绿色版”这个词有点云里雾里,其实说白了,OGNL(Object-Graph Navigation Language)本身是个挺乖的东西,用来在Java里读写对象属性,方便得很,但问题就出在,如果用户能控制输入,而你又把它直接丢给OGNL去解析执行——那就完蛋了,攻击者可以构造恶意表达式,执行任意代码,服务器就等于敞开大门让人随便逛了,你说吓人不吓人?
那为什么叫“绿色版”呢?哈哈,别想歪,不是那种软件破解的绿色版,我理解啊,这个“绿色版”更多是一种调侃或者分类说法——意思是这种注入手法相对“干净”、不依赖太多外部条件,或者说是一种精简、直接能用的攻击/防御思路,也有人管它叫“轻量级OGNL注入利用方式”,反正你记住,OGNL注入绿色版 这个关键词背后,核心就是:Struts2等框架里,因OGNL表达式被恶意拼接而导致的远程代码执行漏洞。
我那时候踩的坑是这样的:项目里有个参数,用户提交后直接进了的OGNL解析,安全同事扔过来一个payload,我本地一跑,直接弹计算器,那一刻我后背发凉啊——这要是上线了,被人弹个shell,我怕是得卷铺盖走人,于是赶紧翻官方补丁、看源码、做过滤,可你知道最气人的是什么吗?网上很多文章讲OGNL注入,要么太学术,要么就是丢一堆代码没解释,我那时候就想,要是有个人能用人话跟我讲讲 OGNL注入绿色版 到底怎么防、怎么测,该多好。
所以今天我就自己来写一篇,不整那些虚头巴脑的,直接上干货,顺便带点情绪,你别嫌我啰嗦。
OGNL注入绿色版到底怎么来的?
简单说,Struts2的某些标签或者参数拦截器,会对用户输入做OGNL求值,比如经典的%{1+1}会返回2,如果攻击者输入%{@java.lang.Runtime@getRuntime().exec('calc')},那就直接执行命令了,这就是OGNL注入,而“绿色版”通常指那种不需要复杂回显、不需要额外依赖,直接通过静态方法调用就能搞定的利用方式,你说可恨不可恨?写框架的人当初咋就没想过这个问题呢?
我是怎么防的?(含泪总结)
- 升级Struts2:这是最省事的,官方从2.3.15开始陆续修补,2.5.x之后好了很多,别偷懒,老版本就是活靶子。
- 白名单过滤:对用户输入里出现的、、、
\u0023等字符做严格检查,注意,攻击者会编码绕过,所以解码后也要查。 - 禁用静态方法调用:在struts配置里设置
struts.ognl.allowStaticMethodAccess=false,这一条能挡掉一大半“绿色版”攻击。 - WAF规则:加个正则,拦截含
Runtime、ProcessBuilder、getClass等关键词的请求,虽然可能误杀,但总比被日穿好。
我当初就是靠这几招把扫描报告给消掉的,你要是问我有没有百分百安全的方案?没有,安全这东西,就是不断对抗,今天叫OGNL注入绿色版,明天可能又换个名字,但只要你理解了原理,就不怕它换马甲。
说点掏心窝子的话
我知道很多做开发的朋友,一听到“安全”就头大,觉得是安全团队没事找事,但兄弟,真出了事,背锅的是你,我那次之后,养成了一个习惯:凡是用户输入拼接到表达式、SQL、命令里的,一律先怀疑,再验证,最后过滤,别嫌麻烦,OGNL注入绿色版 这种坑,踩一次就够你记一辈子。
好了,今天就唠到这儿,如果你也在被OGNL注入折磨,或者想聊聊其他安全坑,欢迎来我站点转转,代码千万行,安全第一行;过滤不规范,同事两行泪,咱们下篇见!
本文由真实踩坑经历改编,关键词“OGNL注入绿色版”已自然融入,转载请注明出处,谢谢您嘞!