XSS - Cross-site scripting
xss其实就是html的注入问题,攻击者的输入没有经过严格的控制进入数据库,最终显示给来访的用户,导致可以在来访用户 的浏览器里以浏览器用户的身份执行html代码,数据的流程如下: 攻击者的html输入->web程序->进入数据库->web程序->用户浏览器。
检查方法
><script>alert(document.cookie)</script>
='><script>alert(document.cookie)</script>
"><script>alert(document.cookie)</script>
<script>alert(document.cookie)</script>
<script>alert(vulnerable)</script>
%3Cscript%3Ealert('XSS')%3C/script%3E
<script>alert('XSS')</script>
<img src="javascript:alert('XSS')">
<img src="http://xxx.com/yyy.png" onerror="alert('XSS')">
<div style="height:expression(alert('XSS'),1)" />(这个仅限 IE 有效)
<script>aler</script>
<script>t(vuln</script>
<script>erable)</script>
等等
攻击手段和目的
攻击者使被攻击者在浏览器中执行脚本后,如果需要手机来自被攻击者的数据(如cookie或其他敏感信息),可以自行架设一个网站,让被攻击攻击者通过javascript等方式把收集好的数据作为参数提交,随后以数据库等形式记录在攻击者自己的服务器上。
- 盗用cookie,获取敏感信息
- 利用植入Flash,通过crossdomain权限进行进一步获取更高的权限;或者利用java等得到类似的操作
- 利用 iframe、frame、XMLHttpRequest或上述Flash等方式,以(被攻击)用户的身份执行一些管理动作,或执行一些一般的如发微博、加好友、发私信等操作。
- 利用可被攻击的域受到其他域信任的特点,以受信任来源的身份请求一些平时不允许的操作,如进行不当的投票活动
- 在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDoS攻击的效果。
漏洞的防御和利用
避免XSS的方法之一主要是将用户提供的内容进行过滤,许多语言都有提供对html的过滤
php:
htmlentities()
htmlspecialchars()
pyton:
cgi.escae()
Node.js:
node-validator
使用HTTP头制定类型:
很多时候可以使用HTTP头制定内容的类型,使得输出内容避免被作为HTML解析。
php:
header('Content-Type: text/javascript; charset=utf-8');
即可强行指定输出内容为文本/JavaScript脚本(顺便指定了内容编码),而非可以引发攻击的HTML。
CSRF
CSRF是跨站伪造(Cross-site request forgery)的英文缩写。CSRF 顾名思义,是伪造请求,冒充用户在站内的正常操作。我们知道,绝大多数网站是通过 cookie 等方式辨识用户身份(包括使用服务器端 Session 的网站,因为 Session ID 也是大多保存在 cookie 里面的),再予以授权的。所以要伪造用户的正常操作,最好的方法是通过 XSS 或链接欺骗等途径,让用户在本机(即拥有身份 cookie 的浏览器端)发起用户所不知道的请求。
要完成一次CSRF攻击,受害者必须依次完成两个步骤。
1.登录受新人的网站A,并在本地生成Cookie。
2.在不登出A的情况下,访问危险网站B。
一个CSRF攻击是如何工作的?
在他们的钓鱼站点,攻击者可以通过创建一个AJAX按钮或者表单来针对你的网站创建一个请求:
<form action="https://my.site.com/me/something-destructive" method="POST">
<button type="submit">Click here for free money!</button>
</form>
如何减轻CSRF攻击
只使用JSON api
使用JavaScript发起AJAX请求是限制跨域的。
不能通过一个简单的<form>
来发送JSON
,
所以,通过只接收JSON,你可以降低发生上面那种情况的可能性。
禁用CORS
第一种减轻CSRF攻击的方法是禁用cross-origin requests(跨域请求)。
如果你希望允许跨域请求,那么请只允许 OPTIONS, HEAD, GET
方法,因为他们没有副作用。
不幸的是,这不会阻止上面的请求由于它没有使用JavaScript(因此CORS不适用)。
检验referrer头部
不幸的是,检验referrer头部很麻烦,
但是你可以阻止那些referrer头部不是来自你的页面的请求。
这实在不值得麻烦。
举个例子,你不能加载session如果这个请求的referrer头部不是你的服务器。
GET总是幂等的
确保你的GET
请求不会修改你数据库中的相关数据。
这是一个初学者常犯的错误,使得你的应用不仅是易于遭受CSRF攻击。
避免使用POST
因为<form>
只能用GET
或是POST
,
而不能使用别的方法,例如PUT
, PATCH
, DELETE
,
攻击者很难有方法攻击你的网站。
不要复写方法
许多应用程序使用复写方法来在一个常规表单中使用PUT
, PATCH
, 和DELETE
请求。
这会使得原先不易受攻击的方法变得易受攻击。
不要兼容旧浏览器
旧的浏览器不支持CORS或是其他安全政策。
通过不兼容旧浏览器
(那些不懂技术的人用的越多,我们越容易被攻击),
你可以最小化受到攻击的可能性。
CSRF Tokens
最终的解决办法是使用CSRF tokens。
CSRF tokens是如何工作的呢?
- 服务器发送给客户端一个token。
- 客户端提交的表单中带着这个token。
- 如果这个token不合法,那么服务器拒绝这个请求。
攻击者需要通过某种手段获取你站点的CSRF token,
他们只能使用JavaScript来做。
所以,如果你的站点不支持CORS,
那么他们就没有办法来获取CSRF token,
降低了威胁。
确保CSRF token不能通过AJAX访问到!
不要创建一个/CSRF
路由来获取一个token,
尤其不要在这个路由上支持CORS!
token需要是不容易被猜到的,
让它很难被攻击者尝试几次得到。
它不需要是密码安全的。
攻击来自从一个未知的用户的一次或者两次的点击,
而不是来自一台服务器的暴力攻击。
结论
因为web正在向JSON API转移,并且浏览器变得更安全,有更多的安全策略,
CSRF正在变得不那么值得关注。
阻止旧的浏览器访问你的站点,并尽可能的将你的API变成JSON API,
然后你将不再需要CSRF token。
但是为了安全起见,你还是应该尽量允许他们尤其是当难以实现的时候。
参考资料