前端安全之XSS和CSRF

2024-04-11 15:25:10

XSS:跨站脚本攻击(Cross-site scripting)

原理

攻击者通过在目标网站上注入恶意脚本代码,当其他用户访问该网站时,这些恶意脚本代码会被执行,从而可能导致用户数据被盗取、会话被劫持或其他恶意行为。

侧重点

千方百计的注入并执行恶意脚本。

注入方式

一切可以输入的地方,都是XSS攻击的用武之地。所以对于前端来说,用户的输入都是不安全的。主要通过URL参数注入输入框注入

分类

反射型XSS

恶意脚本代码直接包含在网页的URL中,当用户点击该链接时,浏览器会执行这些恶意脚本。由于需要用户主动打开恶意的URL才能生效,攻击者往往会结合多种手段诱导用户点击。

存储型XSS

恶意脚本被存储在服务器端,如数据库中,每当用户访问包含这些数据的页面时,浏览器就会执行这些脚本。

DOM型XSS

利用客户端的DOM解析来执行恶意代码,不需要服务器的参与,直接在浏览器端完成攻击。

危害

窃取cookie

在网页浏览中我们常常涉及到用户登录,登录完毕之后服务端会返回一个cookie值。这个cookie值相当于一个令牌,拿着这张令牌就等同于证明了你是某个用户。

如果你的cookie值被窃取,那么攻击者很可能能够直接利用你的这张令牌不用密码就登录你的账户。如果想要通过script脚本获得当前页面的cookie值,通常会用到document.cookie。

试想下如果空间说说中能够写入xss攻击语句,那岂不是看了你说说的人,他们的号你都可以登录(不过重要的cookie一般设置了HttpOnly不能被js获取)。

劫持流量

这个很简单,就是在网页中想办法插入一句像这样的语句:

<script>location.href = 'https://www.baidu.com'</script>

那么所访问的网站就会被跳转到百度的首页。

植入广告

如果想要在XSS攻击中植入广告,可以在XSS攻击的攻击载荷中添加相应的广告代码:

<script>
var xssPayload = document.createElement('div');
xssPayload.innerHTML = '<a href="http://evil.com" target="_blank"><img src="http://evil.com/ad.jpg"></a>';
document.body.appendChild(xssPayload);
</script>

创建一个新的div元素,并设置其innerHTML为一个包含图片广告的超链接。这段代码会在受害者的网页上显示一个广告,点击广告会跳转到一个恶意网站。

DDoS攻击

DDoS攻击可以具体分成两种形式:带宽消耗型以及资源消耗型。它们都是透过大量合法或伪造的请求占用大量网络以及器材资源,以达到瘫痪网络以及系统的目的。如果使用跨站脚本攻击的方式ddos,那么被请求一方则需要被广泛的脚本访问数据。2011年,某互联网公司通过直接引入爱好者制作的脚本实现了12306抢票功能,但由于抢票插件直接引用了来自github托管的数据文件,大量用户的请求客观上实现了DDoS攻击,导致GitHub停止响应数分钟。

在访问量极大的一些页面上的XSS可以攻击一些小型网站,实现DDoS攻击的效果。

防御

  • 对用户的输入进行验证和编码。
  • 使用内容安全策略(CSP)来限制哪些资源可以被加载和执行。
  • 使用自动编码的框架和库来处理用户输入,以防止XSS和其他注入攻击。
  • 启用浏览器的HttpOnly特性来阻止客户端脚本访问cookie。

CSRF:跨站请求伪造(Cross-site request forgery)

原理

  1. 用户正常登录A网站,登录成功后,A网站将cookie保存在用户浏览器中;
  2. 黑客通过散发信息,诱导用户访问恶意网站B;
  3. 在恶意网站B中,使用诱导信息,诱导用户点击链接或者按钮,触发发送恶意指令给A网站的操作;
  4. 浏览器携带着当前用户在A网站的身份认证信息,向A网站发送用户并未授权的恶意指令;
  5. 服务器在收到信息后,不会分辨也无法分辨是否是用户真实的指令,便执行了恶意指令;
  6. 至此攻击成功。

侧重点

不注入恶意脚本,侧重于伪造请求,借刀杀人,在用户不知情的情况下,借用户的名义干坏事。

攻击

对于GET请求,直接放到<img>就能神不知鬼不觉地请求跨域接口,还可以放到<a>标签里。

对于POST请求,很多例子都使用form表单提交:

<form action="https://bank.com/transfer.do" method="POST">
  <input type="hidden" name="acct" value="MARIA" />
  <input type="hidden" name="amount" value="100000" />
  <input type="submit" value="View my pictures" />
</form>

以上都不会报跨域问题,因为你无法用js直接操作获得的结果。

另外,还有一个用途就是用于用户追踪。

比如,Facebook在第三方网站插入一张看不见的图片。

<img src="facebook.com" style="visibility:hidden;">

浏览器加载上面代码时,就会向Facebook发出带有Cookie的请求,从而Facebook就会知道你是谁,访问了什么网站。

防御

  • 严格的跨域请求限制:验证HTTP Referer字段,判断页面来源(判断是不是来源于自己的网站)。
  • 为cookie设置SameSite=Strict表示禁止跨域请求。
  • 关键接口使用短信验证码等双重验证。
  • 将token置于请求头中。
  • 在HTTP头中自定义属性并验证。
表情
Ctrl + Enter