OWASP Top 10 概覽

是什麼?

OWASP(Open Worldwide Application Security Project)是一個非營利的 Web 應用安全社群。OWASP Top 10 是每隔幾年更新一次的十大 Web 應用安全風險清單,是業界公認的安全基準線。

ℹ️最新版本

目前最新是 OWASP Top 10:2021 版本。和 2017 版相比,新增了「不安全的設計(Insecure Design)」和「軟體及資料完整性失敗(Software and Data Integrity Failures)」等類別。

核心觀念

常見誤區

⚠️常見誤區

  • OWASP Top 10 就夠了:Top 10 只是最常見的風險,不代表涵蓋所有安全問題。它是起點不是終點
  • 只在開發完成後才做安全檢查:安全應該融入開發流程(Security by Design),不是事後補救
  • 用了框架就安全了:框架提供預設防護(如 CSRF Token),但開發者可能無意間繞過這些防護

流程/步驟

1

了解 Top 10 風險

團隊所有人都要知道這十種風險是什麼

2

威脅建模

分析系統可能受到哪些 Top 10 攻擊

3

安全編碼

開發時遵循安全編碼規範,使用框架內建防護

4

自動化掃描

在 CI/CD Pipeline 中加入 SAST/DAST 掃描

5

Penetration Testing

定期進行滲透測試,模擬攻擊者行為

6

持續監控

監控安全事件、定期更新有漏洞的依賴

流程解讀:安全不是一個階段而是一個持續的循環。從團隊安全意識培養開始,威脅建模識別風險,安全編碼預防漏洞,自動化掃描持續檢查,滲透測試驗證防禦,監控追蹤異常行為。

程式碼範例

C# 版本

csharp
// A01: Broken Access Control — 正確的授權檢查
[HttpPut("api/orders/{id}")]
[Authorize]
public async Task<IActionResult> UpdateOrder(int id, UpdateOrderDto dto)
{
    var order = await _orderService.GetByIdAsync(id);
    if (order == null) return NotFound();
 
    // 關鍵:檢查這筆訂單是否屬於當前使用者
    var userId = User.FindFirst(ClaimTypes.NameIdentifier)?.Value;
    if (order.UserId.ToString() != userId)
        return Forbid(); // 403 — 不是你的訂單
 
    await _orderService.UpdateAsync(id, dto);
    return NoContent();
}
 
// A02: Cryptographic Failures — 正確的密碼 Hash
using BCrypt.Net;
 
public string HashPassword(string password)
    => BCrypt.Net.BCrypt.HashPassword(password, workFactor: 12);
 
public bool VerifyPassword(string password, string hash)
    => BCrypt.Net.BCrypt.Verify(password, hash);
 
// A05: Security Misconfiguration — 生產環境設定
if (app.Environment.IsProduction())
{
    app.UseHsts();
    app.UseExceptionHandler("/error"); // 不顯示詳細錯誤
}
app.UseHttpsRedirection();

TypeScript 版本

typescript
// A03: Injection — 參數化查詢防止 SQL Injection
// 錯誤示範
// const query = `SELECT * FROM users WHERE id = ${req.params.id}`; // 危險!
 
// 正確做法
const user = await db.query("SELECT * FROM users WHERE id = $1", [req.params.id]);
 
// A06: Vulnerable Components — 自動掃描依賴漏洞
// package.json scripts:
// "audit": "npm audit --production",
// "audit:fix": "npm audit fix"
 
// A09: Logging — 記錄安全事件
app.post("/auth/login", async (req, res) => {
  const { email, password } = req.body;
  const user = await userService.findByEmail(email);
 
  if (!user || !await verifyPassword(password, user.passwordHash)) {
    // 記錄失敗的登入嘗試(安全事件)
    logger.warn("Failed login attempt", {
      email,
      ip: req.ip,
      userAgent: req.headers["user-agent"],
      timestamp: new Date().toISOString(),
    });
    return res.status(401).json({ error: "Invalid credentials" });
  }
 
  logger.info("Successful login", { userId: user.id, ip: req.ip });
  // ...
});

Python 版本

python
# A07: Authentication Failures — 安全的 Session 管理
from fastapi import FastAPI, Depends, HTTPException
from fastapi.security import HTTPBearer
 
# 密碼複雜度驗證
def validate_password(password: str) -> bool:
    if len(password) < 12:
        return False
    if not any(c.isupper() for c in password):
        return False
    if not any(c.isdigit() for c in password):
        return False
    if not any(c in "!@#$%^&*" for c in password):
        return False
    return True
 
# A04: Insecure Design — Rate Limiting 防暴力破解
from slowapi import Limiter
limiter = Limiter(key_func=get_remote_address)
 
@app.post("/auth/login")
@limiter.limit("5/minute")  # 每分鐘最多 5 次登入嘗試
async def login(request: Request, credentials: LoginDto):
    user = await authenticate(credentials.email, credentials.password)
    if not user:
        raise HTTPException(status_code=401, detail="Invalid credentials")
    return {"access_token": create_token(user)}
 
# A10: SSRF — 驗證 URL 防止存取內部資源
from urllib.parse import urlparse
import ipaddress
 
def is_safe_url(url: str) -> bool:
    parsed = urlparse(url)
    hostname = parsed.hostname
    if not hostname:
        return False
    try:
        ip = ipaddress.ip_address(hostname)
        return not (ip.is_private or ip.is_loopback)  # 禁止內部 IP
    except ValueError:
        return hostname not in ["localhost", "127.0.0.1", "0.0.0.0"]

架構圖/概念圖

Attacker
brute force login
A01: Access Control
unauthorized access
A03: Injection
steals data
A07: Auth Failures
gains access
Web Application
Sensitive Data

攻擊者從多個角度嘗試入侵。Auth Failures 讓攻擊者取得合法身份、Injection 讓攻擊者直接存取資料、Broken Access Control 讓攻擊者越權操作。每個 OWASP Top 10 風險都是一個潛在的攻擊路徑。

實戰補充

Q: 面試被問到 OWASP Top 10 怎麼答?

A: 不需要背全部 10 個。記住前三名(Access Control、Cryptographic Failures、Injection)並能舉具體例子和防禦方式。例如:「A03 Injection 最常見的是 SQL Injection,防禦方式是用參數化查詢,永遠不要拼接使用者輸入到 SQL 字串中。」

Q: 怎麼在團隊中推動安全意識?

A: (1) 每月一次 Security Lunch & Learn,講解一個 Top 10 風險。(2) 在 CI/CD Pipeline 加入 npm audit / dotnet list package --vulnerable。(3) Code Review 時有安全 Checklist。(4) 用 OWASP ZAP 做定期自動化掃描。

Q: SAST 和 DAST 是什麼?

A: SAST(Static Application Security Testing):掃描源碼找漏洞,不需要執行程式。如 SonarQube、CodeQL。DAST(Dynamic Application Security Testing):對運行中的程式發送攻擊請求找漏洞。如 OWASP ZAP、Burp Suite。兩者互補,都應該在 Pipeline 中使用。

理解測驗

🤔 OWASP Top 10:2021 中排名第一的安全風險是什麼?

🤔 以下哪個做法可以防禦 A05: Security Misconfiguration?

🤔 A06: Vulnerable Components 的防禦策略是什麼?

重點整理

💡一句話記住

OWASP Top 10 = Web 安全的基本體檢表,不是全部但是起點。 口訣:「前三記牢:權限、加密、注入」

| 排名 | 風險 | 一句話描述 | |------|------|-----------| | A01 | Broken Access Control | 使用者做了不該做的事 | | A02 | Cryptographic Failures | 敏感資料未加密或加密太弱 | | A03 | Injection | 惡意輸入被當作程式碼執行 | | A04 | Insecure Design | 架構層級的安全缺陷 | | A05 | Security Misconfiguration | 設定錯誤暴露弱點 | | A06 | Vulnerable Components | 依賴套件有已知漏洞 | | A07 | Auth Failures | 認證機制不安全 | | A08 | Integrity Failures | 軟體供應鏈未驗證 | | A09 | Logging Failures | 安全事件沒記錄 | | A10 | SSRF | 伺服器被利用存取內部資源 |

你可能也想看

Injection 注入攻擊

按 ← → 鍵切換課程