iT邦幫忙

2024 iThome 鐵人賽

DAY 25
1
IT 管理

30天從版控到code review的實踐指南系列 第 25

Day 25. Code Review 安全性原則:XSS 篇

  • 分享至 

  • xImage
  •  

在整個前端開發過程中,包括 JavaScript, HTML, CSS 以及與後端的交互作用,安全性的考量在各個層面都至關重要。以下將針對不同語言在程式碼安全性應注意的撰寫原則:

避免跨站指令碼 Cross-Site Scripting(通常簡寫為 XSS)


  1. 輸入檢查與驗證:無論是從使用者輸入還是外部資料源,都應該進行嚴格的檢查與驗證。避免將不受信任的資料直接插入到 HTML 內容中。

  2. 輸出編碼:所有來自不受信任來源的輸出(特別是插入到 HTML、JavaScript、CSS 或 URL 中的資料)應該進行適當的編碼。例如,將 HTML 元素插入前進行 HTML 編碼,將屬性值進行屬性編碼。

    • HTML 編碼:將特殊字符如 <, >, &, ", ' 編碼為 HTML 實體(HTML Character Entity),如 <, >, &, ", ' 等。


      範例:當使用者輸入某些內容並顯示在網頁中時,應該進行編碼。

      <!-- 假設 userInput 是不受信任的使用者輸入 -->
      <!-- 不正確的方式,容易被 XSS 攻擊 -->
      <div>
          User input: <span id="output">[userInput]</span>
      </div>
      
      <!-- 正確的方式,使用 HTML 編碼防止 XSS -->
      <div>
          User input: <span id="output"></span>
      </div>
      
      <script>
          // 假設 userInput 是不受信任的使用者輸入
          const userInput = '<script>alert("XSS")</script>';
      
          // 使用 textContent 可以自動對 <script> 進行編碼,避免執行惡意程式碼。
          document.getElementById('output').textContent = userInput;
      </script>
      
    • JavaScript 編碼:避免將未經處理的數據插入到 JavaScript 中,特別是避免直接在 標籤或事件處理器中插入變數。


      範例:將數據插入 JavaScript 時,如果是有潛在危險的 input 應先進行編碼再拼接。

      <!-- 不正確的方式:容易被 XSS 攻擊 -->
      <script>
          var userInput = "[userInput]"; // 假設 userInput 來自不受信任的來源
          eval(userInput); // 如果 userInput 包含惡意程式碼,將會被執行
      </script>
      
      <!-- 正確的方式:避免使用 eval() 或動態執行程式碼 -->
      <script>
          var userInput = '<script>alert("XSS")</script>'; 
          // 安全地處理輸入
          var safeInput = userInput.replace(/</g, "&lt;").replace(/>/g, "&gt;");
          document.write(safeInput); // 顯示內容而不執行程式碼
      </script>
      
      // html 頁面上顯示:&lt;script&gt;alert("XSS")&lt;/script&gt;
      
    • URL 編碼:將使用者輸入中的特殊字符在 URL 中進行編碼,防止 URL 攻擊。


      範例:防止使用者輸入直接插入 URL 中。

      <!-- 不正確的方式 -->
      <a href="https://example.com/search?q=[userInput]">Search</a>
      
      <!-- 正確的方式 -->
      <a href="https://example.com/search?q=" id="searchLink">Search</a>
      
      <script>
          const userInput = '"><script>alert("XSS")</script>';
          const encodedInput = encodeURIComponent(userInput);
          document.getElementById('searchLink').href += encodedInput;
      </script>
      
  3. 使用安全 API:當需要動態生成 HTML 時,優先使用 textContent 或 innerText,而非 innerHTML。例如:

    	// 不建議使用
    element.innerHTML = "<div>" + userInput + "</div>";
    
    // 建議使用
    element.textContent = userInput;
    
  4. 避免內聯事件處理器:避免使用 onclick、onmouseover 等內聯事件,因為這可能存在 XSS 攻擊點,可使用 addEventListener 替代。

    // 不建議
    <button onclick="alert('Hello!')">Click me</button>
    
    // 建議
    const button = document.querySelector('button');
    button.addEventListener('click', () => alert('Hello!'));
    
  5. 內容安全策略 (Content Security Policy, CSP):CSP 是一種安全機制,通過限制資源(如腳本、樣式表、圖片等)的加載,來防止 XSS 和其他類型的攻擊。可以透過 HTTP header 或 標籤來設置 CSP。

    • CSP 實例:後端可以透過 HTTP header 設置 CSP。

      Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted-scripts.com; object-src 'none';
      
      • default-src 'self':僅允許從與網頁相同的來源加載所有資源。

      • script-src 'self' https://trusted-scripts.com:僅允許從自己的域名和 https://trusted-scripts.com 加載 Script。

      • object-src 'none':禁止使用 , , 元素,防止 Flash 或其他Plugin 帶來的攻擊。

      • 以 C# 為例,在 ASP.NET Core 中設置 CSP:

        public void Configure(IApplicationBuilder app, IHostingEnvironment env)
        {
            // 使用 Middleware 來設置 CSP header
            app.Use(async (context, next) =>
            {
                context.Response.Headers.Add("Content-Security-Policy", "default-src 'self'; script-src 'self' https://trusted-scripts.com; object-src 'none'");
                await next();
            });
        
            // 其他 Middleware...
            app.UseRouting();
            app.UseEndpoints(endpoints =>
            {
                endpoints.MapControllers();
            });
        }
        
    • CSP 實例:使用前端 html 的 tag 設定 CSP。


      <meta http-equiv="Content-Security-Policy" content="default-src 'self'; script-src 'self' https://trusted-scripts.com; object-src 'none';">
      

Summary


今天先介紹 XSS 攻擊樣態,並提供了幾個範例給大家參考,明天的文章將繼續探討程式碼安全性規則,例如:避免 Cross Site Request Forgery(CSRF)、避免使用不安全的 function、檢查第三方程式庫(third party library)安全性等。


上一篇
Day 24. Code Review 可維護性與易讀性:Todo Tree 輔助工具篇
下一篇
Day 26. Code Review 安全性原則:CSRF、其他篇
系列文
30天從版控到code review的實踐指南30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言