Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

#java# 规范 XPath注入 增补修订建议 #13

Open
k4n5ha0 opened this issue May 24, 2021 · 0 comments
Open

#java# 规范 XPath注入 增补修订建议 #13

k4n5ha0 opened this issue May 24, 2021 · 0 comments

Comments

@k4n5ha0
Copy link

k4n5ha0 commented May 24, 2021

XPath注入风险类似于SQL注入,如果XPath查询包含不受信任的用户输入,则可能会暴露完整的数据源。这可能使攻击者可以访问未经授权的数据或恶意修改目标XML。

下面以登录验证中的模块为例,说明 XPath注入攻击的实现原理。

在应用程序的登录验证程序中,一般有用户名(username)和密码(password) 两个参数,程序会通过用户所提交输入的用户名和密码来执行授权操作。

若验证数据存放在XML文件中,其原理是通过查找user表中的用户名 (username)和密码(password)的结果进行授权访问。

例存在user.xml文件如下:

<user>
	<firstname>Ben</firstname>
	<lastname>Elmore</lastname>
	<loginID>abc</loginID>
	<password>test123</password>
</user>
<user>
	<firstname>Shlomy</firstname>
	<lastname>Gantz</lastname>
	<loginID>xyz</loginID>
	<password>123test</password>
</user>

则在XPath中其典型的查询语句如下:

//users/user[loginID/text()='xyz'and password/text()='123test']

正常用户传入 login 和 password,例如 loginID = 'xyz' 和 password = '123test',则该查询语句将返回 true。但如果恶意用户传入类似 ' or 1=1 or ''=' 的值,那么该查询语句也会得到 true 返回值,因为 XPath 查询语句最终会变成如下代码:

//users/user[loginID/text()=''or 1=1 or ''='' and password/text()='' or 1=1 or ''='']

脆弱代码:

public int risk(HttpServletRequest request, 
		Document doc, XPath xpath ,org.apache.log4jLogger logger) {
	int len = 0;
	String path = request.getParameter("path");
	try {
		XPathExpression expr = xpath.compile(path);
		Object result = expr.evaluate(doc, XPathConstants.NODESET);
		NodeList nodes = (NodeList) result;
		len = nodes.getLength();
	} catch (XPathExpressionException e) {
		logger.warn("Exception", e);
	}
	return len;
}

解决方案:

public int fix(HttpServletRequest request, 
		Document doc, XPath xpath ,org.apache.log4j.Logger logger) {
	int len = 0;
	String path = request.getParameter("path");
	try {
		// 使用过滤函数
		String filtedXPath = filterForXPath(path);
		XPathExpression expr = xpath.compile(filtedXPath);
		Object result = expr.evaluate(doc, XPathConstants.NODESET);
		NodeList nodes = (NodeList) result;
		len = nodes.getLength();
	} catch (XPathExpressionException e) {
		logger.warn("Exception", e);
	}
	return len;
}
// 限制用户的输入数据,尤其应限制特殊字符
public String filterForXPath(String input) {
	if (input == null) {
		return null;
	}
	StringBuilder out = new StringBuilder();
	for (int i = 0; i < input.length(); i++) {
		char c = input.charAt(i);
		if (c >= 'A' && c <= 'Z') {
			out.append(c);
		} else if (c >= 'a' && c <= 'z') {
			out.append(c);
		} else if (c >= '0' && c <= '9') {
			out.append(c);
		} else if (c == '_' || c == '-') {
			//限制特殊字符的使用
			out.append(c);
		} else if (c >= 0x4e00 && c <= 0x9fa5) {
			//允许汉字使用
			out.append(c);
		}
	}
	return out.toString();
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant