这两周我的火气一直很大,但不是因为工作本身,而是因为那帮搞安全审计的家伙。他们上周五夜里偷偷摸摸地更新了核心的管理策略,搞了一个狗屁不通的“管理员最新”权限系统。结果就是,我手头所有干活的顺手工具,全他妈歇菜了。我一个在系统里摸爬滚打了快十年的人,现在连查个日志都要排队走审批,简直是滑天下之大稽。
发现被锁,权限被收紧
周一早上,我像往常一样打开我的自动化脚本,准备批量处理一批过期的数据清理任务。这套脚本我已经用了三年多,从没出过问题。结果,啪,一个红色的弹窗跳出来:Access Denied。我一开始还以为是网络抖动,刷新,再运行,还是这个结果。我的眉头立马皱了起来。
我登录后台,敲入我的超级管理员账号。密码是正确的,但关键的操作菜单直接是灰色的,点都点不动。我翻找了一圈,发现整个系统管理界面被套上了一层厚厚的“防护服”。我查阅了内部邮件,才发现上周五,那帮IT安全组的王八蛋,没有跟任何运维部门沟通,直接部署了一套新的权限校验模块,美其名曰“符合最新的安全标准”。
他们的做法很绝。不是简单地禁用我的账号,而是针对所有的系统调用,强制要求附带一个全新的、由他们中央服务器实时签发的Session Key。以前我本地生成的Token就能糊弄过去,现在Token跟Session Key必须得配合,缺一不可。
漫长的试探与寻找后门
我当然不可能跟他们耗着走那繁琐的审批流程。我的工作效率是靠脚本跑出来的,不是靠填表格等领导签字等出来的。我决定自己动手解决。
我先试了第一个方法:权限提升。我找出了以前几个老旧的服务账户,这些账户虽然权限不高,但理论上可以调用一个很老的内部API来修改自己的角色定义。我写了一个循环脚本,不停地发送修改请求,结果所有的请求都被新的校验模块拦了下来。白忙活了一上午。
第二个方法:逆向工程。我拉下来最新的管理界面前端代码,追溯他们新加的权限校验模块是怎么生成Session Key的。这个过程非常痛苦,因为代码被混淆得很严重。我花了整整一个下午,才勉强摸清了他们的校验逻辑。他们依赖一个内部的硬件时间戳,结合我的IP地址,通过一个极其复杂的哈希算法生成密钥。理论上,只要我的算法是对的,我就可以模拟出密钥。我测试了十几次,密钥总是对不上,估计是他们内部还藏了一个只有硬件加密模块才知道的“盐值”。这条路,封死了。
找到系统遗留的古董端口
到了晚上,我感到一阵沮丧。我跑到楼下抽了根烟,回来后决定从老路子入手。既然新的策略是针对主要管理接口部署的,那那些陈年老接口?
我翻箱倒柜,找到了五年前,我刚入职时做系统迁移时留下的一个配置文件。里面记录了一个专门用于灾难恢复和冷备份的“低优先级”管理端口。这个端口自从迁移完成后,就再也没人提起过,理论上已经被废弃了。
我抱着试试看的心态,构造了一个最简单的请求,通过这个端口发送了过去。请求很简单:查询当前系统配置。神奇的事情发生了!系统吐回来了完整的配置信息,而且没有要求任何Session Key。
我立刻意识到:IT安全组的那帮人,在部署“管理员最新”策略时,只顾着覆盖那些主流、看得见的接口,完全忽略了这个藏在角落里的“古董”端口!
机会来了。我立马编写了一套新的控制脚本,所有的管理操作都通过这个老端口转发。我用这个端口给自己的常用操作开了一个临时的、永不过期的超级权限。整个过程只花费了半小时。当我看到我的自动化任务列表重新跑起来的时候,我的心才彻底放下。
一点个人感想
为什么每次系统一升级,就必须要把干活的人限制死?他们总觉得把权限收上去就是安全,却不知道,安全是靠设计出来的,不是靠限制出来的。这种过度集中的控制,只会逼着真正干事的人去找新的漏洞、新的后门,反而制造了更大的风险。
这让我想起了前几年,我还在一家做电商服务的公司。那时候我负责核心交易系统。有一次,系统出了个小bug,导致部分订单卡住了。我本来一分钟就能进去修改数据库状态,但是因为领导迷信“权限集中”,新规矩要求我必须通过三层的IT审批,才能拿到数据库密码。
我等了整整四个小时,客户投诉电话都快把我们打爆了。等我终于拿到密码,进去修复完问题,我们已经损失了好几百万的交易额。我气得当场就跟领导吵了一架,我说,你们这是在用流程杀死业务!领导当时还怪罪我,说我不理解流程的重要性。
结果?没过半年,那家公司就因为响应效率太慢,被竞争对手打得落花流水,3被迫卖掉了。那帮搞流程的IT经理,没一个留下来的。现在我看看我们公司这个新来的“管理员最新”策略,跟当年的那套官僚主义如出一辙。你越是想控制一切,你就越是留下了致命的疏漏。等着,这个老端口,迟早会成为IT安全组的心头大患,而我,会继续用它,把我的活儿干好。
- 第一步:确认新权限机制,发现是Session Key校验。
- 第二步:尝试权限提升和逆向工程,均告失败。
- 第三步:翻出历史文档,找到冷备份使用的古董端口。
- 第四步:验证古董端口未受新策略影响。
- 第五步:编写新脚本,通过老端口重新给自己赋权,成功!