网站struts2
2007年我接手一个政府门户网站,网站后台用的网站正是Struts2。那会儿没人觉得这框架有什么问题——XML配置里堆着几百个action,网站每个action对应一个Java类,网站页面跳转全靠struts.xml里那串<result>标签。网站开发人员挺喜欢它,网站因为拦截器机制确实省事,网站一个文件上传功能,网站配三个拦截器就能搞定权限校验和编码转换。网站
但问题出在升级那天。网站2010年7月,网站安全公告贴出第一个远程代码执行漏洞(S2-001),网站我没当回事,网站毕竟谁没事黑政府网站。网站直到三个月后,网站隔壁区县的服务器被挂上了赌博广告,运维才慌慌张张给所有action类加了@InputConversion注解补丁。那会儿修补漏洞的方式还很原始——改代码,重新打包,重启Tomcat,全程手工。
真正让人头疼的是OGNL表达式。这个玩意儿本意是让页面灵活读取对象属性,结果成了黑客的万能钥匙。你永远想不到,一个搜索框里输入#context["xwork.MethodAccessor.denyMethodExecution"]=false,就能绕过所有权限直接执行系统命令。我亲眼见过同事调试时,不小心在日志里打印了用户输入,结果那段恶意表达式直接在服务器上跑了whoami,返回root权限。
后来我们学聪明了,给所有输入框加了正则过滤,但Struts2的漏洞还是像韭菜一样,割了一茬又一茬。S2-045、S2-046、S2-048……每个编号背后都是一个被攻破的站点。最讽刺的是,官方推荐的修复方案往往是“升级到最新版”,可新版本又带来新的兼容问题——老项目里那些自定义拦截器,在新版本里动不动就报NoSuchMethodException。
2016年我换到电商公司,技术栈已经全面转向Spring Boot。有次闲聊,老同事说起当年那个政府网站,终于下定决心重构,把Struts2换成了Spring MVC。他说光迁移就花了两周,但之后再没半夜爬起来处理安全告警。现在看Struts2,它就像个老派的出租车司机——规矩多,脾气大,但确实载着无数网站跑过最颠簸的路段。只是当高速公路修好,人们自然选择更稳的车。
不过话说回来,Struts2的拦截器思想至今影响着主流框架。Spring MVC的HandlerInterceptor,甚至Spring Security的过滤器链,本质上都是同一套“请求前/后处理”的逻辑。只是它输在太灵活——灵活到连开发者自己都说不清哪些表达式可以安全执行。安全这东西,有时候恰恰需要笨拙的约束。

喜欢
讨厌