博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
《Java编码指南:编写安全可靠程序的75条建议》—— 指南8:防止XPath注入
阅读量:6074 次
发布时间:2019-06-20

本文共 4199 字,大约阅读时间需要 13 分钟。

本节书摘来异步社区《Java编码指南:编写安全可靠程序的75条建议》一书中的第1章,第1.8节,作者:【美】Fred Long(弗雷德•朗), Dhruv Mohindra(德鲁•莫欣达), Robert C.Seacord(罗伯特 C.西科德), Dean F.Sutherland(迪恩 F.萨瑟兰), David Svoboda(大卫•斯沃博达),更多章节内容可以访问云栖社区“异步社区”公众号查看。

指南8:防止XPath注入

可扩展标记语言(Extensible Markup Language,XML)可用于以类似于关系数据库的方式来存储数据。XML文档中的数据通常是用XPath来检索。当给XPath检索例程提供的数据没有做合适的无害化处理时,就有可能会导致XPath注入(XPath injection)攻击。这种攻击类似于SQL注入或XML注入(参见《The CERT® Oracle® Secure Coding Standard for Java™》[Long 2012]的“IDS00-J. Sanitize untrusted data passed across a trust boundary”。攻击者可以在查询用的数据字段中输入有效的SQL构造或XML构造。典型的攻击是,让条件查询字段解析为一个永真式,这样就会导致攻击者访问到未经授权的信息。

该指南是指南7的一个具体示例。

XML路径注入示例

先来看看下面的XML模式。

 
  
Utah
  
e90205372a3b89e2
 
 
  
Bohdi
  
6c16b22029df4ec6
 
 
  
Busey
  
ad39b3c2a4dabc98
 
```密码已被散列加密,这符合指南13。出于演示目的,这里的密码就用MD5散列算法加密;在实践中,应该使用SHA-256这样的更安全的算法。不可信的代码可能会尝试在用户输入中动态构造XPath语句,然后利用这个语句从XML文件中检索出用户的详细信息。

//users/user[username/text()='&LOGIN&' and

 password/text()='&PASSWORD&' ]`
如果攻击者知道Utah是一个有效的用户名,他可以指定一个下面这样的输入:

Utah' or '1'='1````这样就构造出以下查询字符串:

//users/user[username/text()='Utah' or '1'='1'

 and password/text()='xxxx']`
因为'1'='1'自动为真,所以密码永远也不会被检查。因此,攻击者在不知道用户Utah的密码的情况下被不适当地验证成了该用户。

违规代码示例

下面的违规代码示例从用户输入中读取用户名和密码,并使用它们来构建查询字符串,将密码以字符数组的形式传递,然后对其进行散列加密。这个示例容易受到上面提到的那种方式的攻击。如果将上面描述的攻击字符串传递给evaluate()方法,这个方法调用会返回XML文件中的相应节点,这会导致doLogin()方法返回true,并绕过所有授权。

private boolean doLogin(String userName, char[] password)    throws ParserConfigurationException, SAXException,        IOException, XPathExpressionException { DocumentBuilderFactory domFactory =  DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse("users.xml"); String pwd = hashPassword( password); XPathFactory factory = XPathFactory.newInstance(); XPath xpath = factory.newXPath(); XPathExpression expr =  xpath.compile("//users/user[username/text()='" +   userName + "' and password/text()='" + pwd + "' ]"); Object result = expr.evaluate(doc, XPathConstants.NODESET); NodeList nodes = (NodeList) result; // Print first names to the console for (int i = 0; i < nodes.getLength(); i++) {  Node node =   nodes.item(i).getChildNodes().item(1).    getChildNodes().item(0);  System.out.println(   "Authenticated: " + node.getNodeValue()  ); } return (nodes.getLength() >= 1);}```合规解决方案(XQuery)为了防止XPath注入,可以采用类似于防止SQL注入的方式。将所有的用户输入视为不可信,并执行适当的无害化处理。对用户输入进行无害化处理时,验证数据类型、数据长度、数据格式和数据内容的正确性。例如,使用一个正则表达式检查用户输入中是否包含XML标签和特殊字符。这种做法符合对用户输入进行无害化处理的规范。更多细节参见指南7。在客户端-服务器(client-server,CS)应用程序中,既执行客户端验证,也执行服务器端验证。广泛地测试用于提供、传播或接受用户输入的应用程序。一种有效防止SQL注入相关问题的技术是参数化。参数化能确保将用户指定的数据以参数的形式传递给API,这样数据就不会被解释为可执行内容了。遗憾的是,Java SE目前缺乏一个类似于XPath查询的接口。不过,通过使用XQuery这样的接口,XPath可以模拟SQL参数化。XQuery支持将查询语句写入运行时环境中的一个单独文件中。

输入文件:login.xq

declare variable $userName as xs:string external;
declare variable $password as xs:string external;
//users/user[@userName=$userName and @password=$password]`
下面的合规解决方案从一个文本文件中读取所需的特定格式的查询语句,然后将用户名和密码的值插入一个映射中。XQuery库构造了这些来自用户输入的XML查询。

private boolean doLogin(String userName, String pwd)  throws ParserConfigurationException, SAXException,     IOException, XPathExpressionException { DocumentBuilderFactory domFactory =  DocumentBuilderFactory.newInstance(); domFactory.setNamespaceAware(true); DocumentBuilder builder = domFactory.newDocumentBuilder(); Document doc = builder.parse("users.xml"); XQuery xquery =  new XQueryFactory().createXQuery(new File("login.xq")); Map queryVars = new HashMap(); queryVars.put("userName", userName); queryVars.put("password", pwd); NodeList nodes =  xquery.execute(doc, null, queryVars).toNodes(); // Print first names to the console for (int i = 0; i < nodes.getLength(); i++) {  Node node =   nodes.item(i).getChildNodes().item(1).    getChildNodes().item(0);  System.out.println(node.getNodeValue()); } return (nodes.getLength() >= 1);}```使用这种方法,用户名(userName)和密码(password)字段中输入的数据不会被运行时环境解释为可执行的内容。适用性未能验证用户输入可能会导致信息披露和未经授权代码的执行。

根据OWASP [OWASP 2013]:

(防止XPath注入)需要被删除(即禁止)或适当转义的字符如下。``< > / ' = "``可用于防止直接的参数注入。XPath查询不应该包含任何元字符(如'、=、*、?、//或类似字符)。

转载地址:http://gdsgx.baihongyu.com/

你可能感兴趣的文章
iphone 如何清空UIWebView的缓存
查看>>
EF里的继承映射关系TPH、TPT和TPC的讲解以及一些具体的例子
查看>>
很好的UI动效设计参考
查看>>
微信硬件平台智能路由行业解决方案
查看>>
S5P4418开发板使用要点
查看>>
【转】Angular运行原理揭秘 Part 1
查看>>
CStdioFile的Writestring无法写入中文的问题
查看>>
从热门话题世界这么大我想去看看想到的:年轻人该如何改变这个世界 无力感越来越强,最后却成为了力量...
查看>>
SGU 548 Dragons and Princesses
查看>>
nginx学习(二):初识配置文件
查看>>
Java设计模式菜鸟系列(两)建模与观察者模式的实现
查看>>
_00023 Kafka 奇怪的操作_001它们的定义Encoder达到Class数据传输水平和决心
查看>>
【转】一个FAE(AE)的体会和大家交流
查看>>
JSPatch 部署安全策略
查看>>
2015/9/22 开通博客园
查看>>
应该是什么在预新手发“外链”(4)最终的外链的方法
查看>>
jdbc数据连接池dbcp要导入的jar包
查看>>
HTTP请求中浏览器缓存
查看>>
C# 通过豆瓣网络编程API获取图书信息
查看>>
HDoj-2084-号码塔-dp
查看>>