1 基础概念
XSS(Cross Site Scripting)攻击全称跨站脚本攻击是为不和层叠样式表(Cascading Style Sheets, CSS)的缩写混淆,故将跨站脚本攻击缩写为XSS,XSS是一种在web应用中的计算机安全漏洞,它允许恶意web用户将代码植入到提供给其它用户使用的页面中。[百度百科]
XSS指恶意攻击者利用网站没有对用户提交数据进行转义处理或者过滤不足的缺点,进而添加一些代码,嵌入到web页面中去。使别的用户访问都会执行相应的嵌入代码。
从而盗取用户资料、利用用户身份进行某种动作或者对访问者进行病毒侵害的一种攻击方式。
XSS攻击的危害包括:
1、盗取各类用户帐号,如机器登录帐号、用户网银帐号、各类管理员帐号
2、控制企业数据,包括读取、篡改、添加、删除企业敏感数据的能力
3、盗窃企业重要的具有商业价值的资料
4、非法转账
5、强制发送电子邮件
6、网站挂马
7、控制受害者机器向其它网站发起攻击
2 原因解析
主要原因:
过于信任客户端提交的数据!
解决办法:
不信任客户端提交的数据,只要是客户端提交的数据就应该先进行相应的过滤处理后方可进行下一步的操作.
进一步分析:
客户端提交的数据本身就是应用所需的,但是恶心攻击者利用网站对客户端提提交数据的信任,在数据中插入一些符号以及JavaScript代码,那么这些数据就会成为应用代码中给的一部分了,那么攻击者就可以肆无忌惮的展开攻击
因此我们绝对不可信任任何客户端提交的数据
3 类型
持久性(存储型)和非持久性(反射型)
持久型
持久型也就是攻击的代码被写入数据库中,这个攻击危害性很大,如果网站访问量很大的话,就会导致大量正常访问的页面,就会导致大量正常访问页面的用户都受到攻击。
最典型的就是留言板的XSS攻击
例子中只是简单的alert(),但是脚本如果很复杂盗用用户的cookie(接口请求获取),账号密码(DOM查询获取)等操作
这种情况如果前后端都没有做防御的话,这段评论就会被存储到数据库中,这样每个打开这个页面的用户都会被攻击
非持久型
非持久型XSS是指发送请求时,XSS代码出现在请求的URL中,作为参数提交到服务器,服务器解析并响应。响应结果中包含XSS代码,最后浏览器解析并执行,从概念上可以看出,反射型XSS代码首先是出现在URL中,然后需要服务端解析,最后需要浏览器之后XSS代码才能攻击
非持久型相比持久性的危害就小了很多,一般通过修改URL参数的方式加入攻击代码,诱导用户访问链接从而进行攻击
http://www.xxx.com?name=<script>alert(1)</script>
<div>{{name}}<div>这时候的name就会取值为alert(1)
但是对于这种攻击,Chrome这类大型浏览器就能自动帮用户防御攻击,但是不代表我们就不需要防御此类攻击。
4 防御方法
通常有两种方式用来防御
1 转义字符
首先,对于用户的输入应该是永远不信任的,最普遍的做法就是转义输入输出的内容,对于括号,尖括号,斜杠进行转义
function escape(str) {
str = str.replace(/&/g, '&')
str = str.replace(/</g, '<')
str = str.replace(/>/g, '>')
str = str.replace(/"/g, '&quto;')
str = str.replace(/'/g, ''')
str = str.replace(/`/g, '`')
str = str.replace(/\//g, '/')
return str
}
通过转义可以将攻击代码 变成
// -> <script>alert(1)</script>
escape('<script>alert(1)</script>')
但是对于显示富文本来说,显然不能通过上面的办法来转义所有字符,因为这样会把需要的格式也过滤掉。对于这种情况,通常采用白名单过滤的办法,当然也可以通过黑名单过滤,但是考虑到需要过滤的标签和标签属性实在太多,更加推荐使用白名单的方式。
const xss = require('xss')
let html = xss('<h1 id="title">XSS Demo</h1><script>alert("xss");</script>')
// -> <h1>XSS Demo</h1><script>alert("xss");</script>
console.log(html)
以上示例使用了 js-xss 来实现,可以看到在输出中保留了 h1 标签且过滤了 script 标签。
2 CSP
内容安全策略 (CSP) 是一个额外的安全层,用于检测并削弱某些特定类型的攻击,包括跨站脚本 (XSS) 和数据注入攻击等。无论是数据盗取、网站内容污染还是散发恶意软件,这些攻击都是主要的手段
CSP 的主要目标是减少和报告 XSS 攻击 ,XSS 攻击利用了浏览器对于从服务器所获取的内容的信任。恶意脚本在受害者的浏览器中得以运行,因为浏览器信任其内容来源,即使有的时候这些脚本并非来自于它本该来的地方。
CSP通过指定有效域——即浏览器认可的可执行脚本的有效来源——使服务器管理者有能力减少或消除XSS攻击所依赖的载体。一个CSP兼容的浏览器将会仅执行从白名单域获取到的脚本文件,忽略所有的其他脚本 (包括内联脚本和HTML的事件处理属性)。
作为一种终极防护形式,始终不允许执行脚本的站点可以选择全面禁止脚本执行
CSP本质上就是建立白名单,开发者明确告诉浏览器哪些外部资源可以进行加载和执行,我们只需要配置规则,如何拦截是由浏览器自己实现的,我们可以通过这种方式来尽量减少XSS攻击
开启CSP的方式(如果使用CSP)
1 你可以使用 Content-Security-Policy HTTP头部 来指定你的策略,像这样:
设置HTTP Header中的Content-Security-Policy: policy
2 设置meta标签的方式
meta http-equiv=“Content-Security-Policy” content=“default-src ‘self’; img-src https://*; child-src ‘none’;”>
常见用例(设置HTTP Header来举例)
一个网站管理者想要所有内容均来自站点的同一个源 (不包括其子域名) 只允许加载本站资源
Content-Security-Policy: default-src ‘self’
一个网站管理者允许内容来自信任的域名及其子域名 (域名不必须与CSP设置所在的域名相同)
Content-Security-Policy: default-src ‘self’ *.trusted.com
一个网站管理者允许网页应用的用户在他们自己的内容中包含来自任何源的图片, 但是限制音频或视频需从信任的资源提供者(获得),所有脚本必须从特定主机服务器获取可信的代码.
Content-Security-Policy: default-src ‘self’; img-src *; media-src media1.com media2.com; script-src userscripts.example.com
只允许加载HTTPS协议图片
Content-Security-Policy: img-src https://*
允许加载任何来源框架
Content-Security-Policy: child-src ‘none’
对于这种方式来说,这要开发者配置了正确的规则,那么即使网站存在漏洞,攻击者也不能执行它的攻击代码,而且CSP的兼容性不错.
CSRF
面试题:什么是CSRF攻击?如何防范CSRF攻击
1 基本概念
CSRF(Cross-site request forgery)跨站请求伪造,也被称为“One Click Attack”或者Session Riding,通常缩写为CSRF或者XSRF,是一种对网站的恶意利用。尽管听起来像跨站脚本(XSS),但它与XSS非常不同,XSS利用站点内的信任用户,而CSRF则通过伪装成受信任用户的请求来利用受信任的网站。与XSS攻击相比,CSRF攻击往往不大流行(因此对其进行防范的资源也相当稀少)和难以防范,所以被认为比XSS更具危险性。
2 原理
原理就是攻击者构造出一个后端请求地址,诱导用户点击或者通过某些途径自动发起请求。如果用户是在登录状态下的话,后端就以为是用户在操作,从而进行相应的逻辑
也就是完成一次CSRF攻击,受害者必须依次完成两个步骤:
1 登录受信任的网站,并在本地生成Cookie
2 在不登出信任网站的情况下,访问危险网站
你也许有疑问:如果我不满足以上两个条件中的一个,我就不会收到CSRF攻击。
的确如此,但是你不能保证以下情况的发生:
1 你不能保证你登录了一个网站后,不再打开一个tab页面并访问其他页面
2 你不能保证你关闭浏览器后,你的本地Cookie立刻过期,你的上次会话已经结束.(事实上,关闭浏览器不能结束一个会话,)
3 危害(CSRF可以做什么)
攻击者盗用了你身份,以你的名义发送恶意请求,CSRF能够做的事情:以你的名义发送邮件,盗取你的账号甚至是购买商品,虚拟货币的转账,个人隐私泄露和财产安全
举个例子:
示例一
有一个小小的东西叫cookie大家应该知道,一般用来处理登录等场景,目的是让服务端知道谁发出的这次请求。如果你请求了接口进行登录,服务端验证通过后会在响应头加入Set-Cookie字段,然后下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中,服务端就能知道这个用户已经登录过了。知道这个之后,我们来看场景:
1.你准备去清空你的购物车,于是打开了买买买网站www.maimaimai.com,然后登录成功,一看,购物车东西这么少,不行,还得买多点。
2.你在看有什么东西买的过程中,你的好基友发给你一个链接www.nidongde.com,一脸yin笑地跟你说:“你懂的”,你毫不犹豫打开了。
3.你饶有兴致地浏览着www.nidongde.com,谁知这个网站暗地里做了些不可描述的事情!由于没有同源策略的限制,它向www.maimaimai.com发起了请求!聪明的你一定想到上面的话“服务端验证通过后会在响应头加入Set-Cookie字段,然后下次再发请求的时候,浏览器会自动将cookie附加在HTTP请求的头字段Cookie中”,这样一来,这个不法网站就相当于登录了你的账号,可以为所欲为了!如果这不是一个买买买账号,而是你的银行账号,那……
这就是传说中的CSRF攻击。
示例二
银行网站A,它以GET请求来完成银行转账的操作,如:http://www.mybank.com/Transfer.php?toBankId=11&money=1000
危险网站B,它里面有一段HTML的代码如下:
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
1
首先,你登录了银行网站A,然后访问危险网站B,噢,这时你会发现你的银行账户少了1000块…
为什么会这样呢?原因是银行网站A违反了HTTP规范,使用GET请求更新资源。在访问危险网站B的之前,你已经登录了银行网站A,而B中的以GET的方式请求第三方资源(这里的第三方就是指银行网站了,原本这是一个合法的请求,但这里被不法分子利用了),所以你的浏览器会带上你的银行网站A的Cookie发出Get请求,去获取资源“http://www.mybank.com/Transfer.php?toBankId=11&money=1000” ,结果银行网站服务器收到请求后,认为这是一个更新资源操作(转账操作),所以就立刻进行转账操作…
示例三
为了杜绝上面的问题,银行决定改用POST请求完成转账操作。
银行网站A的WEB表单如下:
<form action="Transfer.php" method="POST">
<p>ToBankId: <input type="text" name="toBankId" /></p>
<p>Money: <input type="text" name="money" /></p>
<p><input type="submit" value="Transfer" /></p>
</form>
后台处理页面Transfer.php如下:
<?php
session_start();
if (isset($_REQUEST['toBankId'] && isset($_REQUEST['money']))
{
buy_stocks($_REQUEST['toBankId'], $_REQUEST['money']);
}
?>
危险网站B,仍然只是包含那句HTML代码:
<img src=http://www.mybank.com/Transfer.php?toBankId=11&money=1000>
1
和示例二中的操作一样,你首先登录了银行网站A,然后访问危险网站B,结果…和示例1一样,你再次没了1000块~T_T,这次事故的原因是:银行后台使用了REQUEST去获取请求的数据,而 _REQUEST去获取请求的数据,而REQUEST去获取请求的数据,而_REQUEST既可以获取GET请求的数据,也可以获取POST请求的数据,这就造成了在后台处理程序无法区分这到底是GET请求的数据还是POST请求的数据。在PHP中,可以使用GET和 _GET和GET和_POST分别获取GET请求和POST请求的数据。在JAVA中,用于获取请求数据request一样存在不能区分GET请求数据和POST数据的问题。
示例四
经过前面2个惨痛的教训,银行决定把获取请求数据的方法也改了,改用$_POST,只获取POST请求的数据,后台处理页面Transfer.php代码如下:
<?php
session_start();
if (isset($_POST['toBankId'] && isset($_POST['money']))
{
buy_stocks($_POST['toBankId'], $_POST['money']);
}
?>
然而,危险网站B与时俱进,它改了一下代码:
<html>
<head>
<script type="text/javascript">
function steal()
{
iframe = document.frames["steal"];
iframe.document.Submit("transfer");
}
</script>
</head>
<body "steal()">
<iframe name="steal" display="none">
<form method="POST" name="transfer" action="http://www.myBank.com/Transfer.php">
<input type="hidden" name="toBankId" value="11">
<input type="hidden" name="money" value="1000">
</form>
</iframe>
</body>
</html>
如果用户仍是继续上面的操作,很不幸,结果将会是再次不见1000块…因为这里危险网站B暗地里发送了POST请求到银行!
总结一下上面3个例子,CSRF主要的攻击模式基本上是以上的3种,其中以第1,2种最为严重,因为触发条件很简单,一个就可以了,而第3种比较麻烦,需要使用JavaScript,所以使用的机会会比前面的少很多,但无论是哪种情况,只要触发了CSRF攻击,后果都有可能很严重。
理解上面的3种攻击模式,其实可以看出,CSRF攻击是源于WEB的隐式身份验证机制!WEB的身份验证机制虽然可以保证一个请求是来自于某个用户的浏览器,但却无法保证该请求是用户批准发送的!
4 如何防御
防范CSRF攻击可以遵循以下几种规则:
GET请求不对数据进行修改
不让第三方网站访问到Cookie
阻止第三方网站请求接口
请求时附带验证信息,比如验证码或者Token
SameSite
可以对Cookie设置SameSite属性,该属性表示Cookie不随着跨域请求发送,可以很大程度上减少CSRF的攻击,但是该属性目前并不是所有浏览器都兼容
验证 Referer HTTP头部
对于需要防范CSRF的请求,我们可以通过验证Referer来判断请求是否为第三方网站发起的.
Token服务端核对令牌
服务器下发一个服务端核对令牌随机Token,每次发送请求时将Token携带上,服务器验证Token是否有效
验证码
这个方案的思路是:每次的用户提交都需要用户在表单中填写一个图片上的随机字符串,厄…这个方案可以完全解决CSRF,但个人觉得在易用性方面似乎不是太好,还有听闻是验证码图片的使用涉及了一个被称为MHTML的Bug,可能在某些版本的微软IE中受影响。
点击劫持
设计面试题:什么是点击劫持?如何防范点击劫持
1 基本概念
点击劫持(ClickJacking)是一种视觉上的欺骗手段。大概有两种方式,一是攻击者使用一个透明的iframe,覆盖在一个网页上,然后诱使用户在该页面上进行操作,此时用户将在不知情的情况下点击透明的iframe页面;二是攻击者使用一张图片覆盖在网页,遮挡网页原有位置的含义;
2 实例
二种 iframe 和图片覆盖
ifrmae
<!DOCTYPE HTML>
<html>
<meta http-equiv="Content-Type" content="text/html; charset=gb2312" />
<head>
<title>点击劫持</title>
<style>
html,body,iframe{
display: block;
height: 100%;
width: 100%;
margin: 0;
padding: 0;
border:none;
}
iframe{
opacity:0;
filter:alpha(opacity=0);
position:absolute;
z-index:2;
}
button{
position:absolute;
top: 315px;
left: 462px;
z-index: 1;
width: 72px;
height: 26px;
}
</style>
</head>
<body>
那些不能说的秘密
<button>查看详情</button>
<iframe src="http://tieba.baidu.com/f?kw=%C3%C0%C5%AE"></iframe>
</body>
</html>
PS:页面看起来就这样,当然真正攻击的页面会精致些,不像这么简陋。
网址传播出去后,用户手贱点击了查看详情后,其实就会点到关注按钮。
PS:可以把iframe透明设为0.3看下实际点到的东西。
图片覆盖
图片覆盖攻击(Cross Site Image Overlaying),攻击者使用一张或多张图片,利用图片的style或者能够控制的CSS,将图片覆盖在网页上,形成点击劫持。当然图片本身所带的信息可能就带有欺骗的含义,这样不需要用户点击,也能达到欺骗的目的。
PS:这种攻击很容易出现在网站本身的页面
在可以输入HTML内容的地方加上一张图片,只不过将图片覆盖在指定的位置。
<a href="http://tieba.baidu.com/f?kw=%C3%C0%C5%AE">
<img src="XXXXXX" style="position:absolute;top:90px;left:320px;" />
</a>
解决办法
在防御图片覆盖攻击时,需要检查用户提交的HTML代码中,img标签的style属性是否可能导致浮出。
3 如何防御
1 X-FRAME_OPRIONS
X-FRAME_OPRIONS (X-Frame-Options)这个可以说是为了解决ClickJacking而生的
是一个HTTP响应头,在现代的浏览器中有一个较好的支持。它就是为了防御用iframe嵌套的点击劫持攻击
该响应头有三个值可选,分别是
DENY 表示页面不允许通过iframe的方式展示,(浏览器会拒绝当前页面加载的任何iframe)
SAMEORIGIN 表示页面可以在相同域名下通过iframe的方式展示,(frame页面的地址只能为同源域名下的页面)
ALLOW-FROM 表示页面可以在指定来源的iframe中展示
具体的设置方法:
Apache配置:
Header always append X-Frame-Options SAMEORIGIN
nginx配置:
add_header X-Frame-Options SAMEORIGIN;
IIS配置:
<system.webServer>
...
<httpProtocol>
<customHeaders>
<add name="X-Frame-Options" value="SAMEORIGIN" />
</customHeaders>
</httpProtocol>
...
</system.webServer>
JS防御
对于某些远古浏览器来说,并不能支持上面的这种方式,那我们只有通过JS的方式来防御点击劫持
<head>
<style id="click-jack">
html {
display: none !important;
}
</style>
</head>
<body>
<script>
if (self == top) {
var style = document.getElementById('click-jack')
document.body.removeChild(style)
} else {
top.location = self.location
}
</script>
</body>
4 总结
点击劫持算是一种很多人不大关注的攻击,他需要诱使用户与页面进行交互,实施的攻击成本更高。另外开发者可能会觉得是用户犯蠢,不重视这种攻击方式。
中间人攻击
涉及面试题:什么是中间人攻击?如何防范中间人攻击
中间人攻击(Man-in-the-MiddleAttack,简称“MITM攻击”)是一种“间接”的入侵攻击,这种攻击模式是通过各种技术手段将受入侵者控制的一台计算机虚拟放置在网络连接中的两台通信计算机之间,这台计算机就称为“中间人”。
中间人攻击是攻击方同时与服务端和客户端建立起了连接,并让对方认为连接是安全的,但是实际上整个通信过程都被攻击者控制了。攻击者不仅能获得双方的通信信息,还能修改通信信息。
通常来说不建议使用公共的 Wi-Fi,因为很可能就会发生中间人攻击的情况。如果你在通信的过程中涉及到了某些敏感信息,就完全暴露给攻击方了。
当然防御中间人攻击其实并不难,只需要增加一个安全通道来传输信息。HTTPS 就可以用来防御中间人攻击,但是并不是说使用了 HTTPS 就可以高枕无忧了,因为如果你没有完全关闭 HTTP 访问的话,攻击方可以通过某些方式将 HTTPS 降级为 HTTP 从而实现中间人攻击。
网友评论