什么是 XSS 攻击?如何防范?

2023年2月9日

💎 加入 E+ 成長計畫 與超過 500+ 位軟體工程師一同在社群中成長,並且獲得更多的軟體工程學習資源

XSS (cross-site scripting) 是很常见的网路攻击。身为网页前端或后端工程师,在面试中,很常会问到 XSS 的问题,因为面试官要确定你对于 XSS 的基本概念需要有所掌握。

什么是 XSS?

XSS 攻击是指当某个恶意用户,从客户端注入攻击脚本来达到某种目的(例如:窃取 Cookie、Session、密码等),导致其他用户受到波及。之所以会说是跨域 (cross-site),是因为这种攻击方式,通常是从可信的来源发出,因此能够绕过同源政策 (same origin policy)。举例来说,某个用户以合法身份进到某个网站,这时因为他是合法身份,网站认为该用户输入的东西是可信任的,所以当该用户注入攻击脚本时,网站也会认为该脚本是可信任的。

最常见的 XSS 攻击是把 JavaScript 的脚本注入到输入框中。例如在某个论坛网站中,恶意用户把攻击脚本注入到输入框,然后变成某篇论坛贴文。这时当其他用户进到论坛时,因为浏览了那篇带有恶意脚本的贴文,所以被攻击。

用户可以输入恶意的 Javascript 语法,让系统出现问题,有兴趣的可以透过这个网站来试试看。

因为 JavaScript 几乎可以做到任何事,所以 XSS 的攻击能做到的事情也是五花八门。举例来说,窃取别的用户的 cookie,然后透过拿到的 cookie 来发送请求;或者是窜改网页内容。下面分享一个早些年直播平台 Twitch 因为防御做得不够完善,被恶搞的例子。这个例子就是透过 XSS 达成的。

XSS 攻击的类型

Stored XSS

被保存在资料库中的 Javascript 引起的攻击称为 Stored XSS,最常见的就是文章、留言等,因为用户可以任意输入内容,若没有检查,则<script> 等标签就会被视为正常的 HTML 做执行。

Reflected XSS

此类型不会被存在资料库中,主要透过用户发出恶意的请求,倘若后端没有过滤而直接将结果回传前端的话,就有可能执行到恶意的代码,举例来说:

Reflected XSS
Reflected XSS

倘若用户填完名字后,显示的代码如下:

<h3> Hi, <?=$_GET['name'] ?> </h3>

则很有可能被用户恶意填写为:

https://websiteA/welcome?name=<script>alert(123)</script>

此种手法通常都用于钓鱼、社交工程等方式诱骗用户点入连结。

DOM-Based XSS

DOM 全名为 Document Object Model,它可以利用 Javascript 动态产生完整的网页,不用透过后端,因此 DOM-Based XSS 是指网页上的 Javascript 在执行过程中,没有检查输入资料,使得操作 DOM 的过程中带入了恶意代码。

DOM-Based XSS
DOM-Based XSS

在同一个网址上,透过 DOM 的方式直接显示在前端页面

<script>
  var hello = function () {
    let name = document.getElementById("name").value;
    document.getElementById("show").innerHTML = name;
  };
</script>
<h3>Hi, <span id="show"></span></h3>
<input id="name" type="text" />
<button onclick="hello();">Go</button>

因此只要将输入的内容写为

<img src="#" onerror="alert(123);" />

则会因为读取不出图片而产生错误,触发 onerror ,并执行 alert(123)

此类型的攻击,或许没办法直接让用户输入语法,但可以搭配 Stored XSS 和 Reflected XSS 制造出内容,再藉由 Javascript 动态产生有效的 DOM 物件来执行恶意代码。

如何防御 XSS?

  1. DOM-Based 防范 - 检查输入栏位。此攻击需要从前端去防范,任何的输入栏位,例如留言栏位、档案上传栏位、表单的栏位等,都要有跳脱的机制,让脚本被转换成字符串。举例来说,如果攻击者输入<script>alert(1)</script> ,我们把< 转成&lt ,在画面上依然是呈现< 但是对程式来说,它不会被当成 HTML 标签来解析。

  2. 确保来自使用者的脚本不会被执行。透过CSP (content security policy) 来设定有哪些网域(domains ) 来的脚本该被浏览器认为是该被执行的,然后浏览器只执行那些该被执行的脚本。举例来说,如果设定只有来自与网站同一个网域的脚本可被执行,那么其他由恶意攻击者注入的脚本,就会被认定成不该执行的,就不会被执行。

  3. Stored、Reflected 防范。这两种都必须由后端进行防范,任何允许用户输入的内容都要检查,删除相关的关键字,像是 <script>onerror 等指令。


相关文章

🧵 如果你想收到最即時的內容更新,可以在 FacebookInstagram 上追蹤我們