XSS漏洞的基本原理
定义
XSS(Cross Site Script),跨站脚本攻击。它指的是恶意攻击者利用网站漏洞把恶意的脚本代码(通常包括HTML代码和JS脚本)注入到网页之中,当用户浏览该页之时,嵌入其中Web里面的恶意代码会被执行,从而对受害用户可能采取Cookie资料窃取、会话劫持、钓鱼欺骗等各种攻击。
分类及其原理
1.反射型
反射型XSS也被称为非持久性XSS,攻击者在URL中插入XSS代码,服务端将URL中的XSS代码输出到页面上,攻击者只需要通过诱骗或加密变形等方式将存在恶意代码的URL发给用户,用户打开后便会受到XSS攻击。
通过一个简单案例来加深理解:
<html>
<head>
<meta http-equiv="Content_Type" content="text/html;charset=utf-8" />
</head>
<body>
<form action="" method="get">
<input type="text" name="id">
<input type="submit">
</form>
<hr>
<?php
$xss = $_GET['id'];
echo '输入的字符为'.$xss;
?>
</body>
</html>
部署好文件之后,在输入框内输入:
<script>alert('XSS')</script>
点击"submit"之后:
会发现有弹窗产生,查看源代码:
可以看到输入的内容直接插入到了页面中,成为了<script>代码。
总结一下反射型XSS的基本攻击流程:
攻击者->发现存在反射XSS的URL->构造XSS代码->根据情况对XSS代码进行编码、缩短等特殊处理->发送给受害人->受害人打开URL,执行XSS代码->攻击得到相应信息(cookie、IP、浏览器信息等)。
2.存储型
存储型XSS又被称为持久型XSS,因为该类型XSS会将攻击者插入的XSS存储到数据库,当用户访问存在XSS漏洞的页面时,服务端会从数据库中取出数据展示到页面上,导致XSS代码执行,达到攻击效果。
存储型XSS最常见的场景是在留言板、博客或新闻发布系统中,恶意代码的数据信息直接写入文章、评论、留言中,浏览时会执行相应的脚本代码。
通过DVWA靶场的XSS攻击(存储型)进一步理解:
<?php
if( isset( $_POST[ 'btnSign' ] ) ) {
// Get input
$message = trim( $_POST[ 'mtxMessage' ] );
$name = trim( $_POST[ 'txtName' ] );
// Sanitize message input
$message = stripslashes( $message );
$message = mysql_real_escape_string( $message );
// Sanitize name input
$name = mysql_real_escape_string( $name );
// Update database
$query = "INSERT INTO guestbook ( comment, name ) VALUES ( '$message', '$name' );";
$result = mysql_query( $query ) or die( '<pre>' . mysql_error() . '</pre>' );
//mysql_close();
}
?>
代码中的trim()函数是移除字符串两侧的空白字符或其他预定义字符(\0,\t,\n,\x0B,\r),mysql_real_escape_string()函数是转义 SQL 语句中使用的字符串中的特殊字符来预防SQL注入,stripslashes()函数是删除反斜杠。
但是对XSS的输入并没有任何过滤,直接存储到数据库中。
在Message中输入JS脚本:
点击"Sign Guestbook"之后,可以看到弹窗提示:
并且每次访问这个页面,都会出现弹窗。
反射型XSS只是服务端将URL中的XSS代码解析传递给前端,但存储型XSS的XSS代码被服务端存储到了数据库,当有相应请求时,都会解析传递给前端。因为存储型XSS的持久性,在测试中避免使用<script>alert("xss"),容易被人发现,可以使用来测试。
3.DOM型
DOM(Document Object Model,文档对象模型)是一个平台中立和语言中立的接口,使得程序的脚本可以动态访问和更新文档的内容、结构和样式。通过DOM,树中的所有节点均通过JavaScript进行访问。所有HTML元素(节点)均可被修改,也可以创建或删除节点。
DOM型XSS就是攻击者通过修改页面的DOM节点数据信息而形成的XSS跨站脚本攻击,不要与服务端进行交互。
通过一个简单案例来加深理解:
<html>
<head>
<meta http-equiv="Content_Type" content="text/html;charset=utf-8" />
</head>
<body>
<?php
error_reporting(0);
$xss = $_GET["id"];
?>
<input id="text" type="text" value="<?php echo $xss; ?>"/>
<div id="xss"></div>
<script type="text/javascript">
var text = document.getElementById("text");
var xss = document.getElementById("xss");
xss.innerHTML = text.value; //直接获取text的值,并没有过滤机制,造成DOM型XSS
</script>
</body>
</html>
审查元素:
这里的innerHTML把输入的内容返回到了div标签里,并非插到了web页面中,源代码中没有相应内容。而在反射型XSS中,输入的内容是插入到Web页面中的,页面源代码中才会有相应的内容。
防御方法
1.输入过滤:对用户提交的信息进行有效验证、过滤有害的输入(<、>、'、#等敏感字符)
2.输出编码:使用htmlspecialchars()函数将预定义的字符转换为HTML实体、
3.使用特定的类库,如微软开发的Anti-XSS,提供了大量的编码函数用于处理用户的输入。
4.HttpOnly:如果cookie中设置了HttpOnly属性,那么通过JS脚本将无法读取用户的cookie信息。
关于浏览器的同源策略
同源策略由Netscape提出的一个著名的安全策略。所谓同源是指:域名、协议、端口相同。如果一个浏览器的两个tab页中分别打开百度和谷歌的页面,当浏览器的百度tab页执行一个脚本的时候会检查这个脚本是属于哪个页面的,即检查是否同源,只有和百度同源的脚本才会被执行。
因为同源策略的原因,也就导致了XSS Vector(XSS攻击向量)必须在我们希望攻击的同一个域下触发。例如攻击者如果想窃取在www.a.com下的cookie,那就必须在www.a.com这个域下的某一个页面放置XSS代码。
参考链接:
https://www.freebuf.com/articles/web/42727.html