开发失误XML注入

极客

开发失误引发的XML注入:我这辈子都不想再犯的错,你千万要避开!

哎,说到这个XML注入,我这心里就一阵后怕,真的,搞了这么多年开发,什么坑没见过?但那次因为一个开发失误导致的XML注入漏洞,差点让我把饭碗都砸了,今天必须拿出来说说,给各位同行提个醒,不然我总觉得自己这跟头白摔了。

事情是这样的,你们可得听我唠叨

那会儿我接手了一个客户数据对接系统,对方要求用XML格式传数据,说是安全,我当时就寻思,这XML解析不就是老本行吗,闭着眼都能写,结果呢?就因为我图省事,没做严格的XML注入防护,直接在字符串拼接处用了用户输入的数据,当时还觉得自己挺聪明,代码写得多简洁啊,一个加号搞定一切。

你们猜怎么着?上线第三天,系统就出幺蛾子了,黑客给的那段XML里藏了 <!DOCTYPE 实体定义,我那个解析器傻乎乎地就去解析了,然后呢?服务器直接对外网发起了请求,密钥文件差点就被读出来了,要不是运维大哥及时发现异常流量,我这系统就成人家内网的跳板了,想想都冒冷汗。

说真的,那天晚上我躺在工位旁边的行军床上,翻来覆去睡不着,那会儿才明白,别人说“XML注入比SQL注入更隐蔽”是什么意思,SQL注入好歹能写个单引号试试,XML注入呢?你不把整段报文打出来看,压根发现不了,尤其是现在很多微服务间通信还爱用XML配置,一旦某个字段没转义,那就是白送一个高危漏洞啊。

我的血泪教训:这些坑大家都得躲着

第一,千万别手动拼XML,我知道有些人爱显摆技术,觉得用DOM或者SAX解析不够“优雅”,但咱说实话,你手动拼一个 <node> 标签,能保证把 <, >, & 全转义成实体吗?我当时就是栽在这上面的,用标准库里的XMLWriter,或者至少用 htmlspecialchars 那样的转义函数,它能帮你挡掉大部分常见攻击。

第二,外部实体一定要禁用,这个不用我多说了吧,XXE攻击可是上了OWASP Top 10的,设置 libxml_disable_entity_loader(true) 就那么一行代码,为什么我当时就没写呢?现在想想都觉得自己脑子被门夹了,如果你用的是Java,记得在DocumentBuilderFactory里设置 setFeature("http://apache.org/xml/features/disallow-doctype-decl", true),这玩意儿能救命。

第三,校验你的Schema,不是说能解析出来就完事了,你总得验证一下每个节点的类型和长度吧?比如客户ID应该是整数,结果对方传个 <customerId>1 UNION SELECT password FROM users</customerId>,你不校验就直接用了,这不等于开门揖盗吗?我就是因为没加这层检查,人家直接通过注入点把系统文件路径探得明明白白,唉,说多了都是泪。

现在再回头看,其实这坑完全可以避开的

你说气不气人?后来我查了查官方文档,发现主流的XML解析库基本都内置了防御措施,比如Python的 defusedxml,人家库名字就叫“defused”,就是为了这场景量身定做的,还有,咱们写代码的时候是不是应该多想想:“如果我是黑客,这个输入里能塞什么坏东西?”我当时要是这么想,就不会把一个 XML注入 漏洞留到生产环境了。

而且吧,最让我羞愧的是,出了这事之后,测试部的同事拿着审计报告来问我:“这个参数不是没对外公开吗?”我一查日志,好家伙,原来有个老接口的调试模式没关,IP白名单形同虚设,你说这算什么?开发失误连着失误,聚在一起就变成一个大写的“惨”字。

所以啊,各位兄弟姐妹,我在这儿真心奉劝一句:哪怕再熟悉的技术,也要保持敬畏心,写XML解析之前,先画个图,理清楚哪些数据是可信的,哪些不可信,再做边界处理,别像我一样,非要等系统被攻击了,才在凌晨两点的机房角落里抱着键盘后悔。

还是希望每位开发者都能平平安安上线,不要经历我那种险些“社会性死亡”的时刻,如果你们公司有专门做安全测试的师傅,记得多请教请教,别嫌人家烦,关键时刻能救你的职业生涯。

开发失误XML注入

好啦,啰嗦了半天,其实就是希望大家引以为戒,如果你也正在学习网络安全,或者对这些漏洞防御感兴趣,想找个人聊聊,欢迎加我QQ:1234567890(备注“安全学习”),咱们一起切磋,少走些弯路,毕竟,安全这行,真的是用教训堆出来的。😅

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

目录[+]

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