搜尋全站文章

沒有找到相關文章

試試其他關鍵字或檢查拼寫

找到 0 篇文章 • 包含部落格、筆記、旅遊文章

Medium GitHub LinkedIn

【XSS】前端的其他XSS攻擊方式

作者頭像
Sam

最近發佈

5分鐘閱讀

【XSS】前端的其他XSS攻擊方式

:::note 這邊是《Beyond XSS:探索網頁前端資安宇宙》的第五章讀書會筆記。 :::

5-1: Click Jacking

Click Jacking 是一種網站攻擊技術,透過 iframe 將目標網站隱藏在一個看不見的網頁中,並將 iframe 設定為透明,當使用者點擊透明的 iframe 時,實際上是點擊了目標網站的按鈕。

防範方式

1. Frame busting:透過 JavaScript 來檢查是否在 iframe 中,如果是則將頁面導向到原始網站。

if (top === self) { dociment.documentElement.style.display = 'block'; } else { top.location = self.location; }

self:代表當前的 window,top:代表最上層的 window。

2. iframesandbox 屬性:可以限制 iframe 的行為,例如:禁止表單提交、禁止腳本執行等。

3. X-Frame-Options:透過 HTTP Header 來限制網站是否可以被 iframe。

不過 X-Frame-Options 在實作時,瀏覽器不會每一層都去檢查是否同源,因此可以被 nested 繞過,目前已經被 CSP 取代。

example.com/A.html --> attacker.com ---> example.com/A.html ---> example.com/B.html

4. CSP:frame-ancestors 指令可以限制 iframe 的來源。

Content-Security-Policy: frame-ancestors 'self' example.com
  1. none: 不允許任何 iframe 載入。

  2. self: 只允許同源的 iframe 載入。

  3. URI:只允許特定的網站載入。

防禦總結

  1. 使用 CSP:不允許 iframe 載入其他網站。
  2. 只允許同源的 iframe 載入。
Content-Security-Policy: frame-ancestors 'self' Content-Security-Policy: frame-ancestors 'self' example.com

無法防禦的 Click Jacking

  • 例如 Facebook widget 的 分享 按鈕,這些按鈕是透過 iframe 載入的,因此無法防禦 Click Jacking。

5-2:MIME Sniffing

MIME Sniffing 是一種瀏覽器的行為,當瀏覽器無法判斷資源的 MIME Type 時,會透過檔案的內容來判斷 MIME Type,這樣的行為容易被攻擊者利用。

:::note MIME type (Multipurpose Internet Mail Extensions,多用途網際網路郵件擴展) 是一種網際網路標準,最初設計用於擴展電子郵件的功能,使其能夠傳輸非 ASCII 字元的文字、非文字格式的附件(例如圖片、聲音、影片等),以及由多個部分組成的訊息。後來,MIME type 也被 HTTP 協議廣泛採用,用於標識在網路上傳輸的資料類型。 :::

const express = require('express'); const app = express(); app.get('/', (req, res) => { res.write('<h1>hello</h1>'); res.end(); }); // compare1 app.get('/', (req, res) => { res.write('<h2>hello</h2>'); res.end(); }); // compare2 app.get('/', (req, res) => { res.write('hi', '<h1>hello</h1>'); res.end(); }); app.listen(3000, () => { console.log('server is running on port 3000'); });

某些時候可以繞過 MIME Sniffing 的方式:

  • chrome:不一定會檢查

  • firefox:會檢查附檔名,如果附檔名是 html,則會將 Content-Type 設定為 text/html

被攻擊會怎麼樣

  • 有上傳的功能
  • 但是沒有檢查內容物

:::note 備註:這些是主要瀏覽器支援的 content-type,可以執行 JavaScript 的 MIME Type:

  1. text/html
  2. application/xhtml+xml
  3. application/xml
  4. text/xml
  5. image/svg+xml

:::

例如可以上傳一個 svg 檔案,然後在 svg 檔案中寫入 JavaScript。

<svg xmlns="http://www.w3.org/2000/svg"> <script> alert('XSS'); </script> </svg>

防範方式

1. 使用 X-Content-Type-Options

這個 Header 會告訴瀏覽器不要做 MIME Sniffing,直接使用 Server 回傳的 Content-Type。

X-Content-Type-Options: nosniff

如果不做防禦會怎麼樣

情境:

  1. 有上傳的功能,但是沒有檢查內容物
  2. 有 CSP 但是只限制同源的 JavaScript 執行

5-3 前端供應鏈攻擊

前端供應鏈攻擊是一種攻擊方式,攻擊者會透過第三方套件來攻擊網站,例如:event-streamlodashaxios 等等。

範例:cdnjs

CDN 可以根據使用者的地理位置,將資源分發到最近的伺服器,這樣可以加速網站的載入速度。

使用 cdn 的原因

  1. 偷懶
  2. 開發速度快、節省成本

如果 CDN 被攻擊,則下游的網站也會受到影響。

攻擊方式

  1. 利用 cdn 寫入特定路徑
檔名:../../lodash.js CDN:https://cdnjs.cloudflare.com/ajax/libs/lodash.js
  1. symbolic link

symbolic link 是一種特殊的檔案,可以指向另一個檔案或目錄,這樣可以達到攻擊的目的。

ln -s /etc/passwd /var/www/html/passwd
  • 在 Git 倉庫中新增 symbolic link,並讓 test.js 指向 /etc/passwd
  • 觸發 Git 自動更新,cdnjs 複製並公開該檔案,公開內容為 /etc/passwd 的內容。
  • 攻擊者可以透過 CDN 的 URL 來取得 /etc/passwd 的內容。

防範方式

  1. 使用瀏覽器的 Integrity 檢查

Integrity 是一個屬性,可以檢查資源是否被竄改。可以自動記憶上一個(假設是安全版本的 CDN)

  1. 使用自有的 CDN

5-5:XSLeaks 旁路攻擊

:::note 待補充 :::

const express = require('express'); ​​​​​​​​​​​​const app = express(); ​​​​​​​​​​​​app.get('/200', (req, res) => { ​​​​​​​​​​​​ res.writeHead(200, { ​​​​​​​​​​​​ 'Content-Type': 'text/html', ​​​​​​​​​​​​ 'Cross-Origin-Resource-Policy': 'same-origin', ​​​​​​​​​​​​ }); ​​​​​​​​​​​​ res.write('<h1>hlelo</h1>'); ​​​​​​​​​​​​ res.end(); ​​​​​​​​​​​​}); ​​​​​​​​​​​​app.get('/400', (req, res) => { ​​​​​​​​​​​​ res.writeHead(400, { 'Cross-Origin-Resource-Policy': 'same-origin' }); ​​​​​​​​​​​​ res.end(); ​​​​​​​​​​​​}); ​​​​​​​​​​​​app.get('/', (req, res) => { ​​​​​​​​​​​​ res.writeHead(200, { ​​​​​​​​​​​​ 'Content-Type': 'text/html', ​​​​​​​​​​​​ }); ​​​​​​​​​​​​ res.write( ​​​​​​​​​​​​ '<script src="/200" onerror=alert("200_error") onload=alert("200_load")></script>' ​​​​​​​​​​​​ ); ​​​​​​​​​​​​ res.write( ​​​​​​​​​​​​ '<script src="/400" onerror=alert("400_error") onload=alert("400_load")></script>' ​​​​​​​​​​​​ ); ​​​​​​​​​​​​ res.end(); ​​​​​​​​​​​​}); ​​​​​​​​​​​​app.listen(5555, () => { ​​​​​​​​​​​​ console.log('Server is running on port 5555'); ​​​​​​​​​​​​});

:::note

loacl 版為了避免 Same Site 的問題, 改由上傳檔案的方式來執行

<script src="http://localhost:5555/200" onerror=alert("200_error") onload=alert("200_load")></script> <script src="http://localhost:5555/400" onerror=alert("400_error") onload=alert("400_load")></script>

:::

探索更多精彩內容

繼續閱讀,了解更多技術與個人經歷的精彩文章。