XPATH 注入的介绍与代码防御

0x01 介绍
软件未正确对 XML 中使用的特殊元素进行无害化处理,导致攻击者能够在终端系统处理 XML 的语法、内容或命令之前对其进行修改。在 XML 中,特殊元素可能包括保留字或字符,例如“<”、“>”、“"”和“&”,它们可能用于添加新数据或修改 XML 语法。我们发现用户可控制的输入并未由应用程序正确进行无害化处理,就在 XPath 查询中使用。例如,假定 XML 文档包含“user”名称的元素,每个元素各包含 3 个子元素 -“name”、“password”和 “account”。这时下列 XPath 表达式会产生名称为“jsmith”、密码为“Demo1234”的用户的帐号(如果没有这样的用户,便是空字符串):
string(//user[name/text()=‘jsmith‘ and password/text()=‘Demo1234‘]/account/text())
以下是应用程序的示例(采用 Microsoft ASP.NET 和 C#):
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.Load("...");
...
XPathNavigator nav = XmlDoc.CreateNavigator();
XPathExpression expr = nav.Compile("string(//user[name/text()=‘"+TextBox1.Text+"‘ and password/text()=‘"+TextBox2.Text+"‘]/account/text())");
String account=Convert.ToString(nav.Evaluate(expr));
if (account=="")
{
// name+password pair is not found in the XML document - login failed.
}
else
{
// account found -> Login succeeded. Proceed into the application
}
使用此类代码时,攻击者可以注入 XPath 表达式(非常类似 SQL 注入),例如,提供以下值作为用户名:
‘ or 1=1 or ‘‘=‘
此数据会导致原始 XPath 的语义发生更改,使其始终返回 XML 文档中的第一个帐号。
这意味着虽然攻击者未提供任何有效用户名或密码,但仍将登录(作为 XML 文档中列出的第一个用户)。
0x02 主要修复思路
未对用户输入正确执行危险字符清理,可能导致恶意攻击者可以访问存储在敏感数据资源中的信息。缓解修复:
假设所有输入都是恶意的。使用黑名单和白名单的适当组合以确保系统仅处理有效和预期的输入。
0x03 Asp.Net
我们可以使用验证控件,将输入验证添加到“Web 表单”页面。验证控件提供适用于所有常见类型的标准验证的易用机制 - 例如,测试验证日期是否有效,或验证值是否在范围内 - 以及进行定制编写验证的方法。此外,验证控件还使我们能够完整定制向用户显示错误信息的方式。验证控件可搭配“Web 表单”页面的类文件中处理的任何控件使用,其中包括 HTML 和 Web 服务器控件。
为了确保用户输入仅包含有效值,我们可以使用以下其中一种验证控件:
a. “RangeValidator”:检查用户条目(值)是否在指定的上下界限之间。 您可以检查配对数字、字母字符和日期内的范围。
b. “RegularExpressionValidator”:检查条目是否与正则表达式定义的模式相匹配。 此类型的验证使您能够检查可预见的字符序列,如社会保险号码、电子邮件地址、电话号码、邮政编码等中的字符序列。
重要注意事项:验证控件不会阻止用户输入或更改页面处理流程,它们只会设置错误状态,并产生错误消息。程序员的职责是,在执行进一步的应用程序特定操作前,测试代码中控件的状态。有两种方法可检查用户输入的有效性:
1. 测试常规错误状态
在您的代码中,测试页面的 IsValid 属性。该属性会将页面上所有验证控件的 IsValid 属性值汇总(使用逻辑 AND)。如果将其中一个验证控件设置为无效,那么页面属性将会返回 false。
2. 测试个别控件的错误状态
在页面的“验证器”集合中循环,该集合包含对所有验证控件的引用。然后,您就可以检查每个验证控件的 IsValid 属性。
0x03 J2EE
1 输入数据验证
虽然为了用户的方便,可以提供“客户端”层的数据验证,但必须在“服务器”层(也就是 Servlet)执行数据验证。客户端验证本身就不安全,因为这些验证可轻易绕过,例如,通过禁用 JavaScript。一份好的设计通常需要 Web 应用程序框架,以提供服务器端实用程序例程,从而验证以下内容:[1] 必需字段[2] 字段数据类型(缺省情况下,所有 HTTP 请求参数都是“字符串”)[3] 字段长度[4] 字段范围[5] 字段选项[6] 字段模式[7] cookie 值[8] HTTP 响应好的做法是将以上例程作为“验证器”实用程序类中的静态方法实现。以下部分描述验证器类的一个示例。
[1] 必需字段“始终”检查字段不为空,并且其长度要大于零,不包括行距和后面的空格
以下是如何验证必需字段的示例:
<span style="font-size:14px;"> // Java example to validate required fields
public Class Validator {
...
public static boolean validateRequired(String value) {
boolean isFieldValid = false;
if (value != null && value.trim().length() > 0) {
isFieldValid = true;
}
return isFieldValid;
}
}
String fieldValue = request.getParameter("fieldName");
if (Validator.validateRequired(fieldValue)) {
// fieldValue is valid, continue processing request
}
</span>
[2] 输入的 Web 应用程序中的字段数据类型和输入参数欠佳
所有 HTTP 请求参数或 cookie 值的类型都是“字符串”。开发者负责验证输入的数据类型是否正确。使用 Java 基本包装程序类,来检查是否可将字段值安全地转换为所需的基本数据类型。以下是验证数字字段(int 类型)的方式的示例:
<span style="font-size:14px;"> // Java example to validate that a field is an int number
public Class Validator {
...
public static boolean validateInt(String value) {
boolean isFieldValid = false;
try {
Integer.parseInt(value);
isFieldValid = true;
} catch (Exception e) {
isFieldValid = false;
}
return isFieldValid;
}
...
}
...
// check if the HTTP request parameter is of type int
String fieldValue = request.getParameter("fieldName");
if (Validator.validateInt(fieldValue)) {
// fieldValue is valid, continue processing request
...
}
</span>
好的做法是将所有 HTTP 请求参数转换为其各自的数据类型。例如,开发者应将请求参数的“integerValue”存储在请求属性中,并按以下示例所示来使用:
<span style="font-size:14px;"> // Example to convert the HTTP request parameter to a primitive wrapper data type
// and store this value in a request attribute for further processing
String fieldValue = request.getParameter("fieldName");
if (Validator.validateInt(fieldValue)) {
// convert fieldValue to an Integer
Integer integerValue = Integer.getInteger(fieldValue);
// store integerValue in a request attribute
request.setAttribute("fieldName", integerValue);
}
// Use the request attribute for further processing
Integer integerValue = (Integer)request.getAttribute("fieldName");
</span>
以下是应用程序应处理的主要 Java 数据类型(如上所述):
- Byte
- Short
- Integer
- Long
- Float
- Double
- Date
[3] 字段长度“始终”确保输入参数(HTTP 请求参数或 cookie 值)有最小长度和/或最大长度的限制
以下是验证 userName 字段的长度是否在 8 至 20 个字符之间的示例:
<span style="font-size:14px;"> // Example to validate the field length
public Class Validator {
...
public static boolean validateLength(String www.wxinxin.cc value, int minLength, int maxLength) {
String validatedValue = value;
if (!validateRequired(value)) {
validatedValue = "";
}
return (validatedValue.length() >= minLength &&
validatedValue.length(www.lxinyul.cc) <= maxLength);
}
...
}
...
String userName = request.getParameter("userName");
if (Validator.validateRequired(userName)) {
if (Validator.validateLength(userName, 8, 20)) {
// userName is valid, continue further processing
...
}
}
</span>
[4] 字段范围
始终确保输入参数是在由功能需求定义的范围内。以下是验证输入 numberOfChoices 是否在 10 至 20 之间的示例:
<span style="font-family:Arial;"><span style="line-height: 26px; white-space: pre-wrap;"><span style="font-size:14px;"> // Example to validate the field range
public Class Validator {
public static boolean validateRange(int www.ycyc66.cn value, int min, int max) {
return (value >= min && value <= max);
}
}
String fieldValue = request.getParameter("numberOfChoices");
if (Validator.validateRequired(fieldValue)) {
if (Validator.validateInt(fieldValue)) {
int numberOfChoices = Integer.parseInt(fieldValue);
if (Validator.validateRange(numberOfChoices, 10, 20)) {
// numberOfChoices is valid, continue processing request.
}
}
}
</span></span><p style="word-wrap: break-word;"><span style="font-family:Arial;"><span style="line-height: 26px; white-space: pre-wrap;"></span></span></span></p>
[5] 字段选项
Web 应用程序通常会为用户显示一组可供选择的选项(例如,使用 SELECT HTML 标记),但不能执行服务器端验证以确保选定的值是其中一个允许的选项。请记住,恶意用户能够轻易修改任何选项值。始终针对由功能需求定义的受允许的选项来验证选定的用户值。以下是针对允许的选项列表来验证用户选择的示例:
<span style="font-size:14px;"> // Example to validate www.ludipt77.cn user selection against a list of options
public Class Validator {
...
public static boolean validateOption(Object[] options, Object value) {
boolean isValidValue = false;
try {
List list = Arrays.asList(options);
if (list != null) {
isValidValue = list.contains(value);
}
} catch (Exception e) {
}
return isValidValue;
}
}
// Allowed options
String[] options = {"option1", "option2", www.yinb666.cn "option3");
// Verify that the user selection is one of the allowed options
String userSelection = request.getParameter("userSelection");
if (Validator.validateOption(options, userSelection)) {
// valid user selection, continue processing request
<p> }</p><p></span></p>

[6] 字段模式
始终检查用户输入与由功能需求定义的模式是否匹配。例如,如果 userName 字段应仅允许字母数字字符,且不区分大小写,那么请使用以下正则表达式:^[a-zA-Z0-9]*$。 Java 1.3 或更早的版本不包含任何正则表达式包。建议将“Apache 正则表达式包”(请参阅以下“资源”)与 Java 1.3 一起使用,以解决该缺乏支持的问题。以下是执行正则表达式验证的示例:
<span style="font-size:14px;"> // Example to validate that a given value matches a specified pattern
// using the Apache regular expression package
import org.apache.regexp.RE;
import org.apache.regexp.RESyntaxException;
public Class Validator {
...
public static boolean matchPattern(String value, String expression) {
boolean match = false;
if (validateRequired(expression)) {
RE r = new RE(expression);
match = r.match(value);
}
return match;
}
}
// Verify that the userName request parameter is alpha-numeric
String userName = request.getParameter("userName");
if (Validator.matchPattern(userName, "^[a-zA-Z0-9]*$")) {
// userName is valid, continue processing request
}
</span>
Java 1.4 引进了一种新的正则表达式包(java.util.regex)。以下是使用新的 Java 1.4 正则表达式包的 Validator.matchPattern 修订版:
<span style="font-family:Arial;"><span style="line-height: 26px; white-space: pre-wrap;"><span style="font-size:14px;"> // Example to validate that a given value matches a specified pattern
// using the Java 1.4 regular expression package
import java.util.regex.Pattern;
import java.util.regexe.Matcher;
public Class Validator {
public static boolean matchPattern(String value, String expression) {
boolean match = false;
if (validateRequired(expr www.yxin7.com ession)) {
match = Pattern.matches(expression, value);
}
return match;
}
</span></span><p style="font-family: Arial; line-height: 26px; white-space: pre-wrap;"> }
</span></p>
<h3 style="margin: 0px; padding: 0px; font-family: Arial; line-height: 26px; widows: 1;"><span style="font-size: 14px;">
<pre code_snippet_id="1915297" snippet_file_name="blog_20161007_8_9629753" class="httpMessage" name="code" style="white-space: pre-wrap; word-wrap: break-word; font-size: 14px; line-height: 26px; widows: 1; background-color: rgb(255, 255, 255);"></span></h3>

[7] cookie 值
使用 javax.servlet.http.Cookie 对象来验证 cookie 值。适用于 cookie 值的相同的验证规则(如上所述)取决于应用程序需求(如验证必需值、验证长度等)。以下是验证必需 cookie 值的示例:
<span style="font-size:14px;"> // Example to validate a required cookie value
// First retrieve all available cookies submitted in the HTTP request
Cookie[] cookies = request.getCookies();
if (cookies != null) {
// find the "user" cookie
for (int i=0; i<cookies.length; ++i) {
if (cookies[i].getName().equals("user")) {
// validate the cookie value
if (Validator.validateRequired(cookies[i].getValue()) {
// valid www.tyff688.com cookie value, continue processing request
}
}
}
}
<p style="font-family: Arial; line-height: 26px;"></span>
</p>

[8] HTTP 响应
[8-1] 过滤用户输入要保护应用程序免遭跨站点脚本编制的攻击,开发者应通过将敏感字符转换为其对应的字符实体来清理 HTML。这些是 HTML 敏感字符:< > " ‘ % ; ) ( & +以下为以下示例通过将敏感字符转换为其对应的字符实体来过滤指定字符串:
<span style="font-size:14px;"> // Example to filter sensitive data to prevent cross-site scripting
public Class Validator {
...
public static String filter(String value) {
if (value == null) {
return null;
}
StringBuffer result = new StringBuffer(value.length());
for (int i=0; i<value.length(); ++i) {
switch (value.charAt(i)) {
case ‘<‘:
result.append("&lt;");
break;
case ‘>‘:
result.append("&gt;");
break;
case ‘"‘:
result.append("&quot;");
break;
case ‘\‘‘:
result.append("'");
break;
case ‘%‘:
result.append("%");
break;
case ‘;‘:
result.append(";");
break;
case ‘(‘:
result.append("(");
break;
case ‘)‘:
result.append(")");
break;
case ‘&‘:
result.append("&amp;");
break;
case ‘+‘:
result.append("+");
break;
default:
result.append(value.charAt(i));
break;
}
return result;
}
...
}
...
// Filter the HTTP response using Validator.filter
PrintWriter out = response.getWriter();
// set output response
out.write(Validator.filter(response));
out.close();
</span>
Java Servlet API 2.3 引进了“过滤器”,它支持拦截和转换 HTTP 请求或响应。以下为使用 Validator.filter 来用“Servlet 过滤器”清理响应的示例:
<span style="font-size:14px;"> // Example to filter all sensitive characters in the HTTP response using a Java Filter.
// This example is for illustration purposes since it will filter all content in the response, including HTML tags!
public class SensitiveCharsFilter implements Filter {
...
public void doFilter(ServletRequest request,
ServletResponse response,
FilterChain chain)
throws IOException, ServletException {

PrintWriter out = response.getWriter();
ResponseWrapper wrapper = new ResponseWrapper((HttpServletResponse)response);
chain.doFilter(request, wrapper);

CharArrayWriter caw = new CharArrayWriter();
caw.write(Validator.filter(wrapper.toString()));

response.setContentType("text/html");
response.setContentLength(caw.toString().length());
out.write(caw.toString());
out.close();
}
public class CharResponseWrapper extends HttpServletResponseWrapper {
private CharArrayWriter output;

public String toString() {
return output.toString();
}
public CharResponseWrapper(HttpServletResponse response){
super(response);
output = new CharArrayWriter();
}
public PrintWriter getWriter(){
return new PrintWriter(output);
}
}
}
}
</span>
[8-2] 保护 cookie
在 cookie 中存储敏感数据时,确保使用 Cookie.setSecure(布尔标志)在 HTTP 响应中设置 cookie 的安全标志,以指导浏览器应该使用安全协议(如 HTTPS 或 SSL)发送 cookie。
以下为保护“用户”cookie 的示例:
<span style="font-size:14px;"> // Example to secure a cookie, i.e. instruct the browser to
// send the cookie using a secure protocol
Cookie cookie = new Cookie("user", "sensitive");
cookie.setSecure(true);
response.addCookie(cookie);
</span>

0x04 PHP
1 输入数据验证
虽然为方便用户而在客户端层上提供数据验证,但仍必须始终在服务器层上执行数据验证。客户端验证本身就不安全,因为这些验证可轻易绕过,例如,通过禁用 Javascript。需要 Web 应用程序框架,以提供服务器端实用程序例程
[1] 必需字段
“始终”检查字段不为空,并且其长度要大于零,不包括行距和后面的空格。如何验证必需字段的示例:
<span style="font-size:14px;"> // PHP example to validate required fields
function validateRequired($input) {
$pass = false;
if (strlen(trim($input))>0){
$pass = true;
}
return $pass;
}
if (validateRequired($fieldName)) {
// fieldName is valid, continue processing request
}
</span>
[2] 字段数据类型
输入的 Web 应用程序中的字段数据类型和输入参数欠佳。 例如,所有 HTTP 请求参数或 cookie 值的类型都是“字符串”。开发者负责验证输入的数据类型是否正确。
[3] 字段长度
始终”确保输入参数(HTTP 请求参数或 cookie 值)有最小长度和/或最大长度的限制。
[4] 字段范围
始终确保输入参数是在由功能需求定义的范围内。
[5] 字段选项
Web 应用程序通常会为用户显示一组可供选择的选项(例如,使用 SELECT HTML 标记),但不能执行服务器端验证以确保选定的值是其中一个允许的选项。请记住,恶意用户能够轻易修改任何选项值。始终针对由功能需求定义的受允许的选项来验证选定的用户值。
[6] 字段模式
始终检查用户输入与由功能需求定义的模式是否匹配。例如,如果 userName 字段应仅允许字母数字字符,且不区分大小写,那么请使用以下正则表达式:^[a-zA-Z0-9]+$
[7] cookie 值
适用于 cookie 值的相同的验证规则(如上所述)取决于应用程序需求(如验证必需值、验证长度等)。
[8] HTTP 响应
[8-1] 过滤用户输入要保护应用程序免遭跨站点脚本编制的攻击,开发者应通过将敏感字符转换为其对应的字符实体来清理 HTML。这些是 HTML 敏感字符:< > " ‘ % ; ) ( & +PHP 包含一些自动化清理实用程序函数,如 htmlentities():
<span style="font-size:14px;"> $input = htmlentities($input, ENT_QUOTES, ‘UTF-8‘);
</span>
此外,为了避免“跨站点脚本编制”的 UTF-7 变体,您应该显式定义响应的 Content-Type 头,例如:
<span style="font-size:14px;"> <?php
header(‘Content-Type: text/html; charset=UTF-8‘);
?>
</span>
[8-2] 保护 cookie
在 cookie 中存储敏感数据且通过 SSL 来传输时,请确保先在 HTTP 响应中设置 cookie 的安全标志。这将会指示浏览器仅通过 SSL 连接来使用该 cookie。为了保护 cookie,您可以使用以下代码示例:
<span style="font-size:14px;"> <$php

$value = "some_value";
$time = time()+3600;
$path = "/application/";
$domain = ".example.com";
$secure = 1;

setcookie("CookieName", $value, $time, $path, $domain, $secure, TRUE);

时间: 2024-10-05 05:06:00

XPATH 注入的介绍与代码防御的相关文章

XSS跨站点脚本的介绍和代码防御

0x01 介绍 可能会窃取或操纵客户会话和 cookie,它们可能用于模仿合法用户,从而使黑客能够以该用户身份查看或变更用户记录以及执行事务在以下情况下会发生跨站点脚本编制 (XSS) 脆弱性: [1] 不可信数据进入 Web 应用程序,通常来自 Web 请求. [2] Web 应用程序动态生成了包含此不可信数据的 Web 页面. [3] 页面生成期间,应用程序不会禁止数据包含可由 Web 浏览器执行的内容,例如 JavaScript.HTML 标记.HTML 属性.鼠标事件.Flash 和 A

DOM4J介绍与代码示例(2)-XPath 详解

XPath 详解,总结 XPath简介 XPath是W3C的一个标准.它最主要的目的是为了在XML1.0或XML1.1文档节点树中定位节点所设计.目前有XPath1.0和 XPath2.0两个版本.其中Xpath1.0是1999年成为W3C标准,而XPath2.0标准的确立是在2007年.W3C关于XPath的英文 详细文档请见:http://www.w3.org/TR/xpath20/ . XPath是一种表达式语言,它的返回值可能是节点,节点集合,原子值,以及节点和原子值的混合等.XPath

XPath注入技术综述

一次完整的 XPath 注入攻击应该包括使用特殊构造的查询来提取一个 XML 数据库内的 数据或者信息.作为一门新的技术,XPath 注入在一定程度上和 SQL 注入漏洞有着惊人的相 似之处,通过下面的文字,我们将进一步来了解这种新型渗透技术. 在温习前人的相关研究成果之前,我们将介绍一些理论性的研究背景,这样有助于我们 更好地理解这种手法的关键.首先我们要了解的便是 XML 标准和 XPath 语言(XML 是 The Extensible Markup Language(可扩展标识语言)的简

WEB安全第五篇--其他注入的奇技淫巧:XML注入、Xpath注入、Json注入、CRLF注入

零.前言 最近做专心web安全有一段时间了,但是目测后面的活会有些复杂,涉及到更多的中间件.底层安全.漏洞研究与安全建设等越来越复杂的东东,所以在这里想写一个系列关于web安全基础以及一些讨巧的payload技巧以便于备忘.不是大神.博客内容非常基础,如果真的有人看而且是大牛们,请不要喷我,欢迎指正我的错误(水平有限). 一.XML注入: 1.本质: XML是一种数据组织存储的数据结构方式,安全的XML在用户输入生成新的数据时候应该只能允许用户接受的数据,需要过滤掉一些可以改变XML标签也就是说

WEB安全:XSS漏洞与SQL注入漏洞介绍及解决方案

对web安全方面的知识非常薄弱,这篇文章把Xss跨站攻击和sql注入的相关知识整理了下,希望大家多多提意见. 对于防止sql注入发生,我只用过简单拼接字符串的注入及参数化查询,可以说没什么好经验,为避免后知后觉的犯下大错,专门参考大量前辈们的心得,小小的总结一下,欢迎大家拍砖啊 一.跨站脚本攻击(XSS) 跨站脚本攻击的原理 XSS又叫CSS (Cross Site Script) ,跨站脚本攻击.它指的是恶意攻击者往Web页面里插入恶意脚本代码,而程序对于用户输入内容未过滤,当用户浏览该页之时

XPath注入跟SQL注入差不多,只不过这里的数据库走的xml格式

SQL注入这块不想细聊了,相信很多朋友都听到耳朵长茧,不外乎是提交含有SQL操作语句的信息给后端,后端如果没有做好过滤就执行该语句,攻击者自然可以随意操纵该站点的数据库. 比如有一个图书馆站点book.com,你点进一本书的详情页面,其url是这样的: book.com/book?id=100 说明这本书在数据库中的键值是100,后端收到url参数后就执行了数据库查询操作: select * from booktable where id='100' 那么如果我们把url更改为 book.com

php session_id()函数介绍及代码实例

session_id()功能: 获取设置当前回话ID. 函数说明: string session_id ([ string $id ] ) 参数: 如果指定了参数$id,那么函数会替换当前的回话id. session_id()函数必须在session_start()函数之前调用. 返回值: session_id返回当前会话id字符串.如果当前没有产生会话,则返回空字符串"". 代码示例1: 输出 session_id() 1 2 3 4 <?php     session_sta

看好你的门-攻击数据存储区(4)-XPath注入攻击

首先需要声明,本文纯属一个毫无远见和真才实学的小小开发人员的愚昧见解,仅供用于web系统安全方面的参考. 1.一些多余的话 XPath注入和SQL注入,原理上非常相似 但是XPath注入的对象主要是XML,相对来说,危害性更加大 2.保存用户信息的XML <?xml version="1.0" encoding="utf-8" ?> <root> <user> <id>1</id> <username

ASP.NET MVC 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁

在开发程序的过程中,稍微不注意就会隐含有sql注入的危险.今天我就来说下,ASP.NET mvc 5使用Filter过滤Action参数防止sql注入,让你代码安全简洁.不用每下地方对参数的值都进行检查,看是用户输入的内容是否有危险的sql.如果每个地方都要加有几个缺点: 1.工作量大 2.容易遗漏 3.不容易维护 下面我通过写一个过滤防止sql的特性类,对Action执行前对Action的参数进行处理,如果有其值有sql语句,就会这些非法字符替换为空字符串. 一.sql注入的例子: 上面的输入