Stored Cross Site Scripting (XSS)

本文深入分析存储型XSS漏洞的四种不同等级,从低级到几乎不可能被攻破的防护措施,详细展示了每种情况下服务端如何处理用户输入,并讨论了潜在的攻击策略。

前言

存储型XSS,  即Stored Cross Site Scripting (XSS),  也可以称为持久性的XSS,  顾名思义就是恶意代码存储在服务器或者数据库中, 恶意代码一般伴随着用户的评论发表、个人信息或者文章发表的地方, 如果没有过滤或者过滤不严格, 这些代码将会被存储在服务器中, 每当用户访问的时候, 恶意代码都会被触发, 造成大量cookie泄露, 甚至蠕虫。

下面对四种不同等级的漏洞进行分析

 

 

  • Low

服务端核心代码:

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
	// Get input
	$message = trim( $_POST[ 'mtxMessage' ] );
	$name    = trim( $_POST[ 'txtName' ] );

	// Sanitize message input
	$message = stripslashes( $message );
	$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

	// Sanitize name input
	$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

	// Update database
	$query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
	$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

	//mysql_close();
}

?>
  • trim() 函数

移除字符串两侧的空白字符或其他预定义字符,字符包括\t、\n、\x0B、\r以及空格,可选参数charlist支持添加额外需要删除的字符。

  • mysql_real_escape_string()函数

对字符串中的特殊符号(\x00,\n,\r,\,‘,“,\x1a)进行转义。

  • stripslashes() 函数

删除字符串中的反斜杠。


首先服务端根据用户是否点击了 btnSign 来发表评论,  若有, 则将参数mtxMessage和txtName的值POST到服务端处理。处理过程中没有作任何过滤。

 

漏洞利用

虽然用了一些对特殊字符的过滤(转义)函数,  但对输入并没有做XSS方面的过滤与检查,且 (评论) 存储在数据库中 ,因此这里存在明显的存储型XSS漏洞。

在评论中注入:

<script>alert(4)</script>

成功弹窗:

  • 危害: 

当其他用户(甚至管理员)访问被xss攻击的页面的时候,  攻击者注入的所有语句会被执行,  由于是存储在数据库中的, 只要不断有用户访问,  这些恶意语句就会不断被执行,  导致用户的cookie被利用、信息泄露等。

 

 

  • Medium 

服务端核心代码:

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
	// Get input
	$message = trim( $_POST[ 'mtxMessage' ] );
	$name    = trim( $_POST[ 'txtName' ] );

	// Sanitize message input
	$message = strip_tags( addslashes( $message ) );
	$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
	$message = htmlspecialchars( $message );

	// Sanitize name input
	$name = str_replace( '<script>', '', $name );
	$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

	// Update database
	$query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
	$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

	//mysql_close();
}

?>
  • strip_tags() 函数

剥去字符串中的HTML、XML以及PHP的标签,但允许使用<b>标签。

  • addslashes() 函数

返回在预定义字符(' 、" 、\、NULL)之前添加反斜杠的字符串。

  • htmlspecialchars() 函数

把一些预定义的字符转换为 HTML 实体。

预定义的字符是:

& (和号) 成为 &amp;

" (双引号) 成为 &quot;

' (单引号) 成为 &#039;

< (小于) 成为 &lt;

> (大于) 成为 &gt;

使用htmlspecialchars函数把预定义的字符&、”、 ’、<、>转换为HTML实体,防止浏览器将其作为HTML元素。

由此可见,  服务端对评论信息(mtxMessage)做了严格的过滤,  但是并没有对用户名进行同样的过滤。

 

漏洞利用

服务端对用户名仅仅做了script标签的过滤,  绕过有很多这里同样介绍三种:

  • 方法一:  大小写绕过

这里需要明白的一点是

  • HTML中对大小写不敏感
  • JS中对大小写敏感

那么我们在name处的注入语句就有:

<Script>alert(5)</sCript>

输入的时候, 发现前段在name的表单限制了输入字符字数:

那么我们可以抓包修改:

forward之后弹窗成功, 并且可以看到在name处注入了:

  • 方法二:  双写绕过

由于对name的内容只用str_place()过滤了一次,  对于多次出现的无法全部匹配完,  所以这里可以用双写绕过:

<s<script>cript>alert('You are attacked!')</script>

  • 方法三:   错误事件img标签绕过
<img src="" onerror="alert(6)">

可以看到,  img标签也同样注入了:

 

 

  • High

服务端核心代码:

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
	// Get input
	$message = trim( $_POST[ 'mtxMessage' ] );
	$name    = trim( $_POST[ 'txtName' ] );

	// Sanitize message input
	$message = strip_tags( addslashes( $message ) );
	$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
	$message = htmlspecialchars( $message );

	// Sanitize name input
	$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );
	$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));

	// Update database
	$query  = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
	$result = mysqli_query($GLOBALS["___mysqli_ston"],  $query ) or die( '<pre>' . ((is_object($GLOBALS["___mysqli_ston"])) ? mysqli_error($GLOBALS["___mysqli_ston"]) : (($___mysqli_res = mysqli_connect_error()) ? $___mysqli_res : false)) . '</pre>' );

	//mysql_close();
}

?>

可以看到,   服务端对name的内容进一步用了正则式并且不区分大小写地过滤所有script标签。

 

漏洞利用

虽然过滤了script标签,  但是还是可以进行其他的标签注入,  比如Medium等级的方法三。

 

 

 

  • Impossible

服务端核心代码:

<?php

if( isset( $_POST[ 'btnSign' ] ) ) {
	// Check Anti-CSRF token
	checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

	// Get input
	$message = trim( $_POST[ 'mtxMessage' ] );
	$name    = trim( $_POST[ 'txtName' ] );

	// Sanitize message input
	$message = stripslashes( $message );
	$message = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $message ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
	$message = htmlspecialchars( $message );

	// Sanitize name input
	$name = stripslashes( $name );
	$name = ((isset($GLOBALS["___mysqli_ston"]) && is_object($GLOBALS["___mysqli_ston"])) ? mysqli_real_escape_string($GLOBALS["___mysqli_ston"],  $name ) : ((trigger_error("[MySQLConverterToo] Fix the mysql_escape_string() call! This code does not work.", E_USER_ERROR)) ? "" : ""));
	$name = htmlspecialchars( $name );

	// Update database
	$data = $db->prepare( 'INSERT INTO guestbook ( comment, name ) VALUES ( :message, :name );' );
	$data->bindParam( ':message', $message, PDO::PARAM_STR );
	$data->bindParam( ':name', $name, PDO::PARAM_STR );
	$data->execute();
}

// Generate Anti-CSRF token
generateSessionToken();

?>

可以看到,通过使用htmlspecialchars函数,解决了XSS,但是要注意的是,如果htmlspecialchars函数使用不当,攻击者就可以通过编码的方式绕过函数进行XSS注入,尤其是DOM型的XSS。

打个比方,

虽然应用了htmlspecialchars函数,  但忽略了一点,  由于编码后处于html标签中, 所以当解析代码的时候, 被过滤编码的字符仍然会被还原来执行。

<think>首先,用户的问题是:“我想了解跨站脚本攻击(XSS)的原理及防范方法 请问Cross site scripting (XSS) 攻击原理 防御措施”。这是一个关于XSS攻击的原理和防御措施的查询。 根据系统级指令: - 所有行内数学表达式必须使用$...$格式,但这里没有数学表达式,所以不需要。 - 独立公式必须使用$$...$$格式并单独成段,同样,这里可能没有数学公式。 - LaTeX语法正确:确保任何数学内容正确使用。 - 使用中文回答:整个回答必须用中文。 - 生成相关问题:在回答结束后,添加“相关问题”部分。 - 回答中引用的段落末尾自然地添加引用标识:例如[^1],参考提供的引用。 用户提供的引用: - [^1]: XSS定义和缩写。 - [^2]: DVWA靶场反射型XSS的代码分析。 - [^3]: XSS攻击类型。 - [^4]: DVWA反射型XSS的源码分析(高难度)。 我需要参考这些引用,并在回答中自然地添加引用标识。例如,当提到某个点时,在末尾加上[^1]等。 回答结构: - 由于用户要求“回答结构清晰,帮助用户逐步解决问题”,我应该组织回答: 1. 介绍XSS攻击。 2. 解释原理。 3. 讨论防御措施。 4. 使用提供的引用支持内容。 关键点从引用: - [^1]: XSS是跨站脚本攻击,缩写为XSS以避免混淆。 - [^2]: 反射型XSS的例子,攻击者注入恶意脚本,受害者浏览器执行。 - [^3]: XSS类型:存储型、反射型、DOM型。 - [^4]: 代码示例,显示如何过滤输入。 用户问题具体是原理和防御措施。 原理: - XSS攻击涉及注入恶意脚本到网页中,当其他用户查看时执行。 - 类型:存储型(持久化在服务器)、反射型(通过URL参数)、DOM型(客户端处理)。 防御措施: - 输入验证和过滤。 - 输出编码。 - 使用内容安全策略(CSP)。 - 从引用中,[^4]提到使用preg_replace过滤脚本标签。 生成相关问题: - 在回答结束后,添加“相关问题”部分,如示例所示。 完整回答结构: 1. 开头介绍XSS。 2. 详细解释原理。 3. 详细讨论防御措施。 4. 添加引用标识。 5. 结束相关问题。 确保语言是中文。 大纲: - 第一部分:XSS原理 - 定义XSS[^1]。 - 攻击流程:攻击者注入脚本 -> 服务器存储或反射 -> 受害者浏览器执行[^2][^3]。 - 类型:存储型、反射型、DOM型[^3]。 - 第二部分:防御措施 - 输入过滤:如使用正则表达式去除脚本标签[^4]。 - 输出编码:确保输出时HTML实体编码。 - 其他:CSP、HTTPOnly标志等。 相关问题: - 如“XSS攻击的常见例子有哪些?”或“如何测试XSS漏洞?”等。 最终输出: - 回答内容。 - §§相关问题§§部分。</think>### 跨站脚本攻击(XSS)原理及防范方法 跨站脚本攻击(Cross-Site Scripting,简称XSS)是一种常见的Web安全漏洞,攻击者通过注入恶意脚本代码到目标网页中,当其他用户(如管理员或普通访客)访问该页面时,脚本会在其浏览器中执行,从而窃取会话cookie、重定向用户或执行其他恶意操作[^1]。XSS攻击的核心在于HTML注入,攻击者利用Web应用程序的输入漏洞(如表单、URL参数)注入JavaScript代码[^2]。以下我将逐步解释XSS的原理和防御措施,确保内容清晰可靠。 #### XSS攻击原理 XSS攻击的原理涉及三个角色:攻击者、目标服务器和受害者的浏览器。攻击过程分为以下步骤: 1. **注入恶意脚本**:攻击者发现Web应用程序的输入点(如搜索框、URL参数),并提交包含恶意脚本的数据。例如,在反射型XSS中,攻击者构造一个URL,其中包含类似`<script>alert('XSS')</script>`的代码[^2][^3]。 2. **服务器处理与响应**:服务器未对输入进行充分过滤或编码,直接将恶意脚本嵌入到HTML响应中。例如,在DVWA靶场的低难度示例中,服务器直接回显用户输入的`name`参数,导致脚本被执行[^2]。 3. **受害者浏览器执行**:当受害者访问包含恶意脚本的页面时,浏览器解析并执行该脚本,攻击者可能窃取cookie、会话令牌或控制用户账户[^3]。 XSS攻击分为三种主要类型: - **反射型XSS(Reflected XSS)**:恶意脚本通过URL参数注入,服务器反射回响应中,受害者点击恶意链接时触发。例如,DVWA中的示例代码未过滤输入,导致脚本直接输出[^2][^4]。 - **存储型XSSStored XSS)**:恶意脚本被存储到服务器数据库(如评论区),所有访问该页面的用户都会执行。 - **DOM型XSS(DOM-based XSS)**:攻击发生在客户端,脚本通过修改DOM结构执行,不涉及服务器响应[^3]。 攻击者利用XSS的常见目标包括窃取用户凭证、发起钓鱼攻击或传播恶意软件。例如,在DVWA的高难度代码中,服务器尝试使用正则表达式过滤脚本标签(如`preg_replace('/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $input)`),但过滤不彻底仍可能导致漏洞[^4]。 #### XSS防御措施 防御XSS的关键在于“输入验证、输出编码”的原则,确保用户输入不被执行为代码。以下措施基于行业最佳实践和引用中的示例: 1. **输入验证与过滤**:对用户输入进行严格检查,移除或转义潜在危险字符。例如,使用正则表达式过滤脚本标签,如引用[^4]中的`preg_replace`函数,但应结合白名单机制(只允许安全字符)。代码示例: ```php $name = preg_replace('/<script.*?>.*?<\/script>/is', '', $_GET['name']); // 过滤script标签 ``` 同时,验证输入格式(如只允许字母数字)能减少风险[^4]。 2. **输出编码**:在将数据输出到HTML时,使用编码函数转换特殊字符。例如,将`<`转义为`<`,`>`转义为`>`,防止浏览器解析为标签。在PHP中,可用`htmlspecialchars()`函数: ```php echo "<pre>Hello " . htmlspecialchars($name, ENT_QUOTES, 'UTF-8') . "</pre>"; // 编码输出 ``` 这确保恶意脚本以文本形式显示,而非执行[^2][^3]。 3. **内容安全策略(CSP)**:通过HTTP头部设置CSP,限制浏览器只加载可信源的脚本。例如: ``` Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; ``` 这能阻止内联脚本和外部恶意资源[^3]。 4. **其他措施**: - 使用HTTPOnly标志:设置Cookie的HTTPOnly属性,防止JavaScript访问会话Cookie。 - 框架安全特性:利用现代Web框架(如React或Angular)的内置XSS防护。 - 定期安全测试:使用工具(如OWASP ZAP)扫描漏洞,模拟DVWA靶场进行反射型XSS测试[^2][^4]。 通过这些防御措施,可显著降低XSS风险。但需注意,XSS漏洞常源于开发疏忽,因此持续教育和代码审计至关重要[^1][^3]。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值