安全反馈了我们系统存在的一些问题
虽然不是我的代码导致,但还是趁机学习了一下
主要是 “XML实体引用约束不足” 与 “跨站历史操作”
XXE
XML External Entity
原因是咱用了鹅厂某个变更回调的接口,而这个回调的数据是XML格式的(为什么不是JSON?
于是代码中简单得使用了DocumentBuilder的parse方法来解析XML,导致了安全问题
XML
Extensible Markup Language,提供了一种标准的、可扩展的数据交换格式
DTD(文档类型定义)是用来定义 XML 文档的合法构建模块
DTD有两种使用方式:
- 内部DTD:即DTD的声明和属性都在 XML 中
- 外部DTD:即 XML 中使用的 DTD 引用了一个外部的单独的DTD文件
为什么
- XML组件默认没有禁用外部实体引用,XML 实体可动态包含来自给定资源的数据。
- XML 解析器无法预防和限制外部实体进行解析,这会使解析器暴露在 XML External Entities 攻击之下。
- 当动态构建XML时,XML 解析器可以访问由用户输入的 URI 所指定的资源,因此可能导致读取任意文件;执行系统命令;探测内网端口;攻击内网网站等
因此外界攻击者可以通过模拟回调通知,在回调通知中引入不安全的XML来达到自己的目的
解决办法
事实上,当前的SpringBoot版本已经修复了这个漏洞,但如果使用更早期的版本或其他框架,可能遭受风险。
所以,咱们需要做的就是禁用DTD以及外部实体引用
JAVA
1
2
3
4
5
6
7
8
9
10
11// 完全禁用DTD
DocumentBuilderFactory dbf = DocumentBuilderFactory.newInstance();
dbf.setFeature("http://apache.org/xml/features/disallow-doctype-decl", true);
// 不包括外部一般实体
dbf.setFeature("http://xml.org/sax/features/external-general-entities", false);
// 不包含外部参数实体或外部DTD
dbf.setFeature("http://xml.org/sax/features/external-parameter-entities", false);
// 忽略外部DTD
dbf.setFeature("http://apache.org/xml/features/nonvalidating/load-external-dtd", false);
dbf.setExpandEntityReferences(false);最好再加上 异常捕获 ,以免一些意外发生
PHP
1
2libxml_disable_entity_loader(true);
$xml = simplexml_load_string($xmlContent);Python
1
2from lxml import etree
xmlData = etree.parse(xmlContent,etree.XMLParser(resolve_entities=False))
跨站历史操作
Cross Site History Manipulation
为什么
现代浏览器会将用户的浏览历史记录作为先前访问过的 URL 的堆栈公开给本地 JavaScript
在某些情况下,利用History对象,攻击者即可以发现应用程序在服务器端执行的某些检查的结果,例如是否登录
解决方法
在重定向的时候,加入一个随机值参数,像这样:1
2
3
4SecureRandom random = SecureRandom.getInstance("SHA1PRNG");
int securityR = random.nextInt();
If (!unAuthenticated)
response.sendRedirect("Login.jsp?securityR=" +securityR );
如果长时间无法加载,请针对 disq.us | disquscdn.com | disqus.com 启用代理