Web安全攻击XSS与CSRF攻击简述
摘要:
公司要给近期项目检测安全性,主要针对的是Stored XSS攻击方式,借这次就在这里好好总结一下,什么是XSS攻击,为什么会出现XSS攻击,XSS攻击有哪些种类,XSS攻击有什么危害,以及CFRS攻击。
什么是XSS攻击:
XSS攻击全称Cross Site Scripting即跨站脚本攻击,这里侧重在脚本上,主要是发生在浏览器层面上的攻击方式,XSS攻击方式是针对围绕着网页中的dom元素不做特殊处理导致的脚本执行。
XSS攻击由来:
有一些标签是可以在浏览器渲染页面的时候可以执行脚本的,比如,script、img、iframe等等。如果在这些标签里加入一些可以获取用户信息或者其他不能被暴露出来信息的脚本,这就是XSS攻击。
XSS攻击的种类:
XSS攻击方式有三种:(1)Reflected XSS(2)Stored XSS (3)Dom-based XSS
Reflected XSS:
反射性XSS攻击的攻击方式是依赖于客户端发起请求(该请求url中带有可执行的脚本元素),服务端返回脚本被浏览器执行的方式进行攻击。
栗子:
1 <!doctype html> 2 <html lang="en"> 3 <head> 4 <meta charset="utf-8"> 5 <script type="text/javascript" src="jquery-3.3.1.min.js"></script> 6 </head> 7 <body> 8 <textarea style="width:300px;height:200px;" id='input'></textarea> 9 <button id='button'>Click</button> 10 <div style="width:300px;height:200px;" id='show'></div> 11 <!-- <script src='test.js'></script> --> 12 <script type="text/javascript"> 13 var btn = document.getElementById('button'); 14 btn.addEventListener('click', function (e) { 15 var value = document.getElementById('input').value; 16 var xhr = new XMLHttpRequest(); 17 var url = './get?param=' + value; 18 xhr.onreadystatechange = function () { 19 if (xhr.readyState === 4) { 20 var res = JSON.parse(xhr.responseText).param; 21 document.getElementById('show').innerHTML = res; 22 } 23 } 24 xhr.open('GET', url, true) 25 xhr.send(null) 26 }) 27 </script> 28 </body> 29 </html>
server端代码:
1 var express = require('express'); 2 var path = require('path'); 3 var router = express.Router(); 4 5 6 var app = express(); 7 8 app.use('/', express.static(__dirname)); 9 10 app.get('/get', function (req, res) { 11 res.json(req.query); 12 }) 13 14 app.post('post', function (req, res) { 15 res.json(res); 16 }) 17 18 app.listen(2222, () => console.log('listening on port 2222.')) 19 module.exports = app;
输入脚本:
点击click后的效果:
可以看到事先设置的cookie被打出来了,这就是reflected XSS攻击,可以理解成将输入参数直接通过后台打到了页面上并执行了这段代码。
控制方式:
后台针对前台发送的参数做处理
preg_replace( '/<(.*)s(.*)c(.*)r(.*)i(.*)p(.*)t/i', '', $_GET[ 'name' ] )
解决方案(具体针对后台是什么语言引入特定库)
htmlspecialchars( $_GET[ 'name' ] );
Restored XSS:
持久性的XSS攻击,常见情况就是提交表单元素时带有script、img等标签保存到数据库中,然后在浏览这些信息的页面加载得时候渲染这些dom执行脚本,不过也不是所有的页面都需要我们将标签进行处理,如果当存入的这些带有执行标签的内容以文本形式在浏览器中进行渲染时,是不会执行的,只有一些特别情况,比如innerHTML或者React中的dangerouslySetInnerHTML,可以将字符串当成dom进行加载,这样的就必须处理,不然就会出现Restored XSS攻击漏洞,React对dangerouslySetInnerHTML的警告就是这个道理。
解决方案
HttpOnly禁用:XSS攻击的目的是获取目标用户信息,通过设置HttpOnly禁用掉cookie,能保证XSS攻击拿不到cookie信息导致XSS攻击失效,但是并不是绝对的,毕竟登录信息不只有cookie,还有token等其他信息。
Based-dom XSS:
基于dom的XSS攻击方式完全由客户端完成,不涉及服务器端的配合,加载页面执行脚本的时候就可以发生Based-dom XSS攻击。
栗子:
var value = document.getElementById('input').value; eval(value);
效果:
所以在 js代码里面,尽可能避免使用eval这样的函数。
总结:
如何防止XSS攻击,针对反射性XSS攻击,做好对url以及参数的过滤,针对注入型以及dom型做好足够的标签转义,理论上是可以达到完美的效果。
CSRF攻击
CSRF俗称跨站协议伪造(跨站请求攻击)
过程模拟
user正常发送请求给A,A响应成功之后user生成了cookie,此时此刻user并没有登出A站点,访问到了B站点,由于携带cookie是浏览器默认行为,当请求访问到了B的时候,B发出请求访问第三方站点(A),A在接到这个请求的时候并不知道请求的来源,导致发生CFRS攻击。
模拟攻击场景
get请求:
在CFRS攻击中get请求理论上是没有任何威胁,恶意攻击目的是修改数据(post请求)
我们准备了两个server,A(正常服务器),B(恶意服务器)
A:首先我们在正常服务器生成cookie
恶意服务器B请求处理
在站点A中的cookie 还未失效的情况下我们访问了站点B,站点B让站点A发送了请求
我们看下效果
这时站点A接收到了这个请求,我们可以看到目标服务器端口8888,但是来源是8889(恶意服务器),到这里已经达到了攻击的效果,那么如果我们在模拟更实际的意义的时候(改用post请求)
post请求:
这里为了方便,我们直接在恶意站点B刷新的时候直接攻击站点A
场景1:当我们访问正常A站点,但是带有一个恶意攻击的链接(此场景在正常站中不会给提供,或者出现XSS攻击暴漏在A站点中的链接)点击这个链接进入恶意站点B
场景2:当我们直接访问一个恶意站点B
可以看到A服务接受到了post请求
查看请求cookie
可以看到来自恶意B站点的请求直接访问到了A站点,并且携带了A站点的cookie,这样就达到了B拿到了A的身份并且访问到了A站点,实施相关恶意操作。
防御策略
1.验证 HTTP Referer 字段
截图上可有看到每个请求都带有refer标记请求来源,当后台对请求来源做控制,设置白名单的时候,就可以达到了解决来自其他站点请求的访问权限,从而达到了解决CFRS攻击的目的,但是这个方式是有局限性的。
refer作用是标记http请求来源,当user登录站点A的时候,站点A通过refer锁定请求来源看。接下来的请求比如是同一来源(域名,IP等等)此时此刻如果从B站点再去访问A站点时候,refer发生改变,导致此请求无效。但是并不是一种完美的解决方案,浏览器旧的版本,也可以通过篡改refer来实现恶意攻击,浏览器也同样可以禁用refer,导致再次访问A站点,由于A站点不信任请求从而发生请求失效。
2.使用token
修改A站点的登录信息认证方式——token
访问成功后生成了一个token。
恶意站点B获取token结果
可以明确说明,当一个网站使用了token的时候,就可以直接忽略了CFRS攻击,因为根本获取不到token,也就解决了获取用户信息的渠道。
综合:针对一个站点做关于CFRS防御的时候,我们通常使用的方式就是以上两种,当然可以合并一起使用。
PS:token重点解决问题是单点击登录~