🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付

一個簡單的腳本——一個微不足道的視覺效果——會為你的應用程式帶來風險嗎?

哦,是的。而且你可能根本意識不到是怎麼回事。

更糟的是,看似不起眼的小程式碼片段,竟然可以變成閃閃發光的計時炸彈。這怎麼可能?

讓我告訴你一個假設的故事。


❄️ 雪開始下了

想像一下,你開發了一個網站、一個網店或一個網頁應用程式。

十二月來臨了。到處都是彩燈、聖誕樹和裝飾品。節日的氣氛開始瀰漫開來。

您(或您的某個利害關係人)要求加入一些當季的小裝飾。

「也許會下雪?」❄️

你很興奮,立刻投入這項極具創意的任務。

但是等等。

積壓的工作堆積如山,截止日期迫在眉睫。突然,你想起了一件重要的事:

你太懶了。 😉

你顯然不會從零開始寫這篇文章。

所以你就做了我們所有人都會做的事:

你打開 CodePen、GitHub,或是 Stack Overflow……然後複製一段隨機的程式碼片段。


❄️《純潔的雪》劇本

<script>
  /**
   * ❄️ Simple snow effect
   * Source: random blog / CodePen
   */
  const snowflakes = ["❄️", "❅", "❆"];

  for (let i = 0; i < 40; i++) {
    const el = document.createElement("div");
    el.className = "snowflake";

    // ❌ copied straight from the internet
    el.innerHTML =
      snowflakes[Math.floor(Math.random() * snowflakes.length)];

    el.style.left = Math.random() * 100 + "vw";
    el.style.fontSize = 12 + Math.random() * 24 + "px";
    el.style.animationDuration = 5 + Math.random() * 5 + "s";

    document.body.appendChild(el);
  }
</script>

五分鐘後——砰——美麗的雪花飄落效果就出現了。

JavaScript 雪花飄落,標題為“節日快樂”

你甚至都沒把它提交上來進行正規的程式碼審查。

或者有人會匆匆瞥一眼,因為——這只是視覺效果,對吧?

安全測試?

誰會去測試飄落的雪花呢?


🎁 恭喜你——你剛剛發布了一個 XSS 漏洞。

問題就在這裡:

el.innerHTML = snowflake;

XSS(跨站腳本攻擊)是指將不受信任的資料以允許其作為 HTML 或 JavaScript 執行的方式註入 DOM 中。

重要澄清:目前,這段程式碼還不是活躍的 XSS 漏洞,因為snowflake來自一個硬編碼的、完全可信的陣列。

然而,危險的模式已經形成——這使得它變成了一顆定時炸彈。

目前來看,一切平安無事。

一切看起來都正常。


⏳ 時光流逝…

一月到了。管理階層決定是時候關閉視覺特效了。

“但別把它拿走!”

“我們明年就需要它了!”

或許更早──春天就要來了,所以與其飄落雪花,不如讓花瓣飄落吧🌸。

一項新任務被加入到待辦事項清單中。

另一位開發者拿起它,心想:

“我不會每隔幾個月就切換一次這個設定。”

讓管理層自己掌控——甚至可以讓他們選擇圖標。 」

所以他們新增了配置項。

或許透過內容管理系統(CMS),或許透過遠端端點。


🌐 “小改進”

function fetchSeasonalConfig() {
  return Promise.resolve({
    enabled: true,
    snowflake: "❄️"
  });
}

fetchSeasonalConfig().then(config => {
  if (!config.enabled) return;

  for (let i = 0; i < 30; i++) {
    const el = document.createElement("div");
    el.className = "snowflake";

    // ❌ still innerHTML
    el.innerHTML = config.snowflake;

    document.body.appendChild(el);
  }
});

現在大門已經敞開了。

此時,該值跨越了信任邊界:它不再來自程式碼中定義的常數,而是來自可以獨立於應用程式邏輯而改變的外部來源。

攻擊者不需要任何花俏的東西:

  • CMS帳戶被盜用

  • 角色配置錯誤

  • 以及一個所見即所得編輯器

  • 從 Notion 或電子郵件複製的片段

  • 被攔截或修改的 API 回應

例如:

snowflake: '<img src=x onerror="alert(\'XSS 🎄\')">'

就這樣。

您的應用程式存在完整的 XSS 漏洞。


🤔 “但我使用的是現代框架!”

你們當中有些人現在可能在想:

“拜託。這適用於舊的 jQuery 網站。”

我使用現代框架——React/Angular/Vue——它可以保護我免受XSS攻擊。

事實並非如此。


⚠️ 框架僅保護它們渲染的內容。

React 和 Angular 預設會對內容進行轉義——但僅限於它們的渲染系統內部。

你使用時的那一刻:

  • innerHTML

  • dangerouslySetInnerHTML (React)

  • [innerHTML]bypassSecurityTrustHtml (Angular)

  • 或在框架之外執行的純 JS 腳本

……你只能靠自己了。

你猜怎麼著?

那個雪景腳本?

它通常位於框架之外,在index.html中,作為“小型視覺效果”加載。

框架不會對隨機的 JavaScript 檔案進行沙盒隔離。


✅ 這件事原本可能有不同的發展方向

這一切原本都可以透過一個簡單的改變來避免:

el.textContent = snowflake;

或透過:

  • 明確建立 DOM 節點,而不是注入 HTML

  • 使用維護良好的程式庫(例如 DOMPurify,並進行正確配置,設定嚴格的允許清單)對 HTML 進行清理。

  • 明確界定安全邊界:所有外在事物均不可信。

  • 將「小型使用者介面功能」與核心功能採取相同的安全策略

內容安全策略 (CSP) 等縱深防禦措施也可以減少影響,但它們無法修復不安全的 DOM API。


🎄 結語

這件事真的發生過嗎?

不 😉

我聽過幾十個非常相似的例子嗎?

絕對地。

記住:任何功能都不能忽略程式碼審查和安全測試。

細節決定成敗。


🎁 節日快樂

祝您假期快樂平安!

只要稍微注意一下從網路上複製的內容,就能為自己帶來這種好處❄️✨


原文出處:https://dev.to/sylwia-lask/a-five-minute-ui-feature-that-became-an-xss-time-bomb-f5i


精選技術文章翻譯,幫助開發者持續吸收新知。

共有 0 則留言


精選技術文章翻譯,幫助開發者持續吸收新知。
🏆 本月排行榜
🥇
站長阿川
📝13   💬9   ❤️4
346
🥈
我愛JS
📝1   💬7   ❤️2
56
評分標準:發文×10 + 留言×3 + 獲讚×5 + 點讚×1 + 瀏覽數÷10
本數據每小時更新一次
🔧 阿川の電商水電行
Shopify 顧問、維護與客製化
💡
小任務 / 單次支援方案
單次處理 Shopify 修正/微調
⭐️
維護方案
每月 Shopify 技術支援 + 小修改 + 諮詢
🚀
專案建置
Shopify 功能導入、培訓 + 分階段交付