2025年6月24日 星期二

擁抱 DevSecOps:OWASP Hardened API Suite 實戰指南

 

擁抱 DevSecOps:OWASP Hardened API Suite 實戰指南

DevSecOps 已經成為現代軟體開發不可或缺的一環。如何在開發初期就將安全性融入 API 設計與測試中,是許多團隊面臨的挑戰。本教學文章將帶您深入了解 OWASP Hardened API Suite 專案,一個簡潔而強大的 DevSecOps 範例,它展示了如何構建一個安全的 Laravel API,並結合 FastAPI 測試器來模擬常見的安全威脅。

點這裡前往 GitHub 專案

專案簡介:API 安全的沙盒與測試場

OWASP Hardened API Suite 是一個專為有經驗的開發者設計的 DevSecOps 範例專案。它不僅提供一個具備基礎防禦機制的 Laravel API,更整合了 FastAPI 測試器來模擬 SQL 注入、XSS (跨站腳本攻擊) 和認證漏洞等常見的 API 安全威脅。

核心目標:

  • 提供一個安全的 Laravel API 範例,並支援 Sanctum 認證。

  • 利用 FastAPI 模擬各類 API 攻擊,驗證防禦效果。

  • 支援整合 OWASP ZAP 進行動態安全掃描(DAST),但需自行配置。

  • 可生成簡單的 Markdown 格式安全報告,但需整合報告生成腳本。

注意:本專案只包含核心代碼(如 Laravel 控制器、FastAPI 攻擊模擬器等),不包含完整的 Laravel 框架結構或 create_project.sh 腳本。您需要自行進行環境配置,這為您提供了高度的彈性和學習機會。

核心架構剖析:微服務協同的 DevSecOps 環境

為了理解如何使用這個專案,首先需要了解其預期的系統架構。這是一個容器化的微服務組合,各組件協同工作以實現 API 功能和安全測試。

graph TD
    A[用戶] -->|HTTP 請求 - API 使用| B[Web Service]
    B -->|查詢/寫入| C[MariaDB]
    A -->|訪問 Swagger UI| D[FastAPI Tester]
    D -->|模擬攻擊 - 安全測試| B
    E[OWASP ZAP] -->|掃描 API - 安全測試| B
    D -->|生成 Pytest 報告| F[Report Generator]
    B -->|生成 PHPUnit 報告| F
    E -->|生成 JSON 報告| G[ZAP Reports]
    G --> F
    F -->|生成 Markdown 報告| H[Reports]
    subgraph Docker Network
        B
        C
        D
        E
    end
    subgraph 安全測試流程
        D
        E
        F
        G
        H
    end

各組件角色解析:

  • Web Service:包含 Nginx(處理 HTTP 請求並代理動態請求)、PHP-FPM(執行 PHP 程式碼)和 Laravel API(提供產品查詢與評論功能,並內建 XSS 和 SQL 注入防禦),需自行配置。

  • MariaDB:專案的資料庫,用於儲存資料,需自行設置遷移與種子數據。

  • FastAPI Tester:一個獨立的 Python 服務,作為自動化安全測試客戶端。它會模擬各種攻擊請求發送到 Web Service,並執行 Pytest 測試來驗證 API 的安全性(由開發者或 CI/CD 觸發)。

  • OWASP ZAP:一個業界領先的開源 DAST 工具。它會對運行中的 Web Service 進行動態安全掃描,尋找潛在漏洞,並生成 JSON 格式的報告(需自行設置)。

  • Report Generator:一個 Python 腳本,負責整合來自 PHPUnit、Pytest 和 ZAP 的測試與掃描報告,最終生成一份易於閱讀的 Markdown 格式綜合報告。

  • Docker Network:所有服務都建議在 Docker 網絡中運行,以確保環境一致性與隔離。

環境搭建:從零開始建立您的安全測試平台

由於本專案僅提供核心代碼,您需要親手搭建 Laravel 和 FastAPI 的運行環境。建議使用 Docker 和 Docker Compose,以確保環境的快速部署和一致性。

先決條件

在開始之前,請確保您的系統已安裝以下工具:

  • DockerDocker Compose:用於容器化環境。

  • PHP 8.2+Composer:用於 Laravel 環境。

  • Python 3.9+pip:用於 FastAPI 測試器。

  • Node.js(可選):用於額外工具或測試。

  • 硬體:建議至少 4GB RAM 和 10GB 磁碟空間。

詳細安裝與配置步驟

  1. 複製專案核心代碼:

    首先,將本專案的核心代碼複製到您的本地環境:

    git clone https://github.com/BpsEason/owasp-hardened-api-suite.git
    cd owasp-hardened-api-suite
    
  2. 設置 Laravel API 環境:

    • 初始化 Laravel 專案

      composer create-project laravel/laravel laravel-app
      
    • 複製核心控制器和模型:

      將您下載的倉庫中的 laravel-app/app/Http/Controllers/ProductController.php 和其他核心控制器檔案,以及 app/Models/Product.php 和 app/Models/User.php 複製到您新建的 laravel-app 對應目錄中。

    • 複製 middleware:

      將 laravel-app/app/Http/Middleware/VerifyCsrfToken.php 複製到新建的 laravel-app 對應目錄。

    • 複製路由:

      將 laravel-app/routes/api.php 複製到新建的 laravel-app 對應目錄。

    • 複製測試文件:

      將 laravel-app/tests/Feature/ProductTest.php 複製到新建的 laravel-app 對應目錄。

    • 複製資料庫相關文件:

      將 laravel-app/database/migrations/2014_10_12_000000_create_users_table.php 和 laravel-app/database/migrations/2025_06_24_000000_create_products_table.php 複製到 laravel-app/database/migrations/。

      將 laravel-app/database/seeders/ProductSeeder.php 和 laravel-app/database/seeders/DatabaseSeeder.php 複製到 laravel-app/database/seeders/。

      將 laravel-app/database/factories/UserFactory.php 複製到 laravel-app/database/factories/。

    • 複製 OpenAPI 定義:

      將 laravel-app/public/openapi.json 複製到 laravel-app/public/。

    • 複製 composer.json:

      將 laravel-app/composer.json 複製到新建的 laravel-app 根目錄。

    • 配置 Sanctum:

      進入 laravel-app 目錄並安裝 Laravel Sanctum,並發布配置:

      cd laravel-app
      composer require laravel/sanctum
      php artisan vendor:publish --provider="Laravel\Sanctum\SanctumServiceProvider" --tag="sanctum-config"
      
    • 配置 .env 文件:

      修改 laravel-app/.env 文件,設定資料庫連線資訊(請根據您的 MariaDB 配置進行調整):

      APP_NAME="LaravelHardenedAPI"
      APP_ENV=local
      APP_KEY=
      APP_DEBUG=true
      APP_URL=http://localhost:8000
      
      LOG_CHANNEL=stack
      LOG_LEVEL=debug
      
      DB_CONNECTION=mysql
      DB_HOST=mariadb # 如果使用 Docker,這裡通常是服務名稱
      DB_PORT=3306
      DB_DATABASE=laravel_db
      DB_USERNAME=user
      DB_PASSWORD=password
      # ... (其他 .env 內容)
      
  3. 設置 FastAPI 測試器環境:

    • 複製 FastAPI 目錄:

      將您下載的倉庫中的 fastapi-tester/ 目錄及其所有子文件複製到您的專案根目錄或其他合適位置。

    • 安裝 Python 依賴:

      進入 fastapi-tester 目錄並安裝所需的 Python 依賴:

      cd fastapi-tester
      pip install -r requirements.txt
      
  4. 設置 Docker 環境 (強烈推薦):

    這是最推薦的環境設置方式,能確保一致性和易用性。在專案根目錄下自行創建 docker-compose.yml 文件,並配置 Nginx (nginx/default.conf) 和 PHP-FPM (docker/php-fpm.conf)。

    • 創建 docker-compose.yml:

      version: '3.8'
      services:
        nginx:
          image: nginx:latest
          ports:
            - "8000:80"
          volumes:
            - ./laravel-app:/var/www/html
            - ./nginx/default.conf:/etc/nginx/conf.d/default.conf
          depends_on:
            - php
            - mariadb
          networks:
            - app-network
        php:
          build:
            context: .
            dockerfile: docker/Dockerfile.php
          volumes:
            - ./laravel-app:/var/www/html
          environment:
            - DB_CONNECTION=mysql
            - DB_HOST=mariadb
            - DB_PORT=3306
            - DB_DATABASE=laravel_db
            - DB_USERNAME=user
            - DB_PASSWORD=password
          networks:
            - app-network
        mariadb:
          image: mariadb:10.6
          environment:
            - MARIADB_ROOT_PASSWORD=root_password
            - MARIADB_DATABASE=laravel_db
            - MARIADB_USER=user
            - MARIADB_PASSWORD=password
          volumes:
            - mariadb_data:/var/lib/mysql
          networks:
            - app-network
        fastapi-tester:
          build:
            context: .
            dockerfile: docker/Dockerfile.fastapi
          ports:
            - "8001:8001"
          volumes:
            - ./fastapi-tester:/app
          depends_on:
            - nginx
          networks:
            - app-network
      networks:
        app-network:
          driver: bridge
      volumes:
        mariadb_data:
      
    • 創建 docker/Dockerfile.php:

      FROM php:8.2-fpm-alpine
      
      WORKDIR /var/www/html
      
      # 安裝 PHP 依賴
      RUN apk add --no-cache \
          nginx \
          mysql-client \
          curl \
          git \
          unzip \
          libzip-dev \
          supervisor \
          nodejs \
          npm \
          libpng-dev \
          libxml2-dev
      
      # 安裝 PHP 擴展
      RUN docker-php-ext-install pdo pdo_mysql opcache zip gd mbstring exif pcntl bcmath
      
      # 安裝 Composer
      COPY --from=composer:latest /usr/bin/composer /usr/local/bin/composer
      
      # 清理 Composer Cache
      RUN composer clear-cache
      
      # 將 PHP-FPM 設定複製到容器中
      COPY docker/php-fpm.conf /etc/php8/php-fpm.d/www.conf
      
      # 調整權限
      RUN chown -R www-data:www-data /var/www/html
      RUN chmod -R 775 /var/www/html/storage /var/www/html/bootstrap/cache
      
      EXPOSE 9000
      
      CMD ["php-fpm"]
      
    • 創建 docker/Dockerfile.fastapi:

      FROM python:3.9-slim-buster
      
      WORKDIR /app
      
      COPY requirements.txt .
      
      RUN pip install --no-cache-dir -r requirements.txt
      
      COPY . .
      
      EXPOSE 8001
      
      CMD ["uvicorn", "app.main:app", "--host", "0.0.0.0", "--port", "8001"]
      
    • 創建 nginx/default.conf:

      server {
          listen 80;
          server_name localhost;
          root /var/www/html/public;
          index index.php index.html index.htm;
      
          location / {
              try_files $uri $uri/ /index.php?$query_string;
          }
      
          location ~ \.php$ {
              fastcgi_pass php:9000;
              fastcgi_index index.php;
              include fastcgi_params;
              fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
              fastcgi_param PATH_INFO $fastcgi_path_info;
          }
      
          # 安全 HTTP 頭部
          add_header X-Frame-Options "SAMEORIGIN" always;
          add_header X-XSS-Protection "1; mode=block" always;
          add_header X-Content-Type-Options "nosniff" always;
          add_header Referrer-Policy "no-referrer-when-downgrade" always;
          add_header Content-Security-Policy "default-src 'self' http://nginx:80; script-src 'self' 'unsafe-inline'; style-src 'self' 'unsafe-inline';" always;
          add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
      }
      
    • 創建 docker/php-fpm.conf:

      [www]
      user = www-data
      group = www-data
      listen = 9000
      pm = dynamic
      pm.max_children = 5
      pm.start_servers = 2
      pm.min_spare_servers = 1
      pm.max_spare_servers = 3
      catch_workers_output = yes
      php_flag[display_errors] = on
      php_admin_value[error_log] = /var/www/html/storage/logs/php-fpm.log
      php_admin_flag[log_errors] = on
      
    • 啟動服務:在 docker-compose.yml 所在的目錄執行:

      docker-compose up -d
      
    • 運行資料庫遷移與填充:進入 Laravel 容器執行:

      docker-compose exec php php artisan migrate --seed
      

運行安全測試:驗證您的 API 防禦

一旦環境設定完成並服務啟動,您就可以開始執行安全測試了。

  1. 運行 Laravel PHPUnit 測試:

    在 laravel-app 目錄中執行 Laravel 的單元測試和功能測試。這將生成 laravel-report.xml。

    cd laravel-app
    ./vendor/bin/phpunit
    
  2. 運行 FastAPI Pytest 安全測試:

    進入 fastapi-tester 目錄,執行預設的 Pytest 安全測試。這將模擬 XSS、SQL 注入等攻擊,並生成 pytest-report.xml。

    cd fastapi-tester
    pytest tests/test_security.py
    
  3. 執行 OWASP ZAP 動態安全掃描 (DAST):

    自行設置 ZAP 容器,並透過 ZAP CLI 啟動掃描。ZAP 會利用 Laravel API 提供的 OpenAPI 文件來引導其掃描過程,執行 Spider 和 Active Scan。這將生成 zap_report.json。

    docker run --rm -v $(pwd)/zap-reports:/zap/wrk:rw owasp/zap2docker-stable \
      zap-cli --port 8080 --host 127.0.0.1 -v \
      openapi http://localhost:8000/api/openapi.json \
      spider http://localhost:8000/api \
      active_scan http://localhost:8000/api \
      report /zap/wrk/zap_report.json
    

報告生成與分析:掌握安全態勢

本專案提供了一個方便的腳本來整合所有測試結果,生成一份統一的安全報告。

  1. 複製報告生成腳本:

    將您下載的倉庫中的 scripts/generate_report.py 複製到您的專案根目錄。

  2. 運行報告生成:

    確保您已安裝 Python 依賴(例如 lxml),然後在專案根目錄執行:

    python scripts/generate_report.py
    

    腳本會解析來自 PHPUnit、Pytest 的 JUnit XML 報告和 ZAP 的 JSON 報告。

  3. 查看報告:

    生成的報告將位於 reports/summary.md。您可以打開此 Markdown 文件,查看所有測試的總結、通過/失敗情況以及 ZAP 發現的潛在漏洞警報。這份報告是您評估 API 安全狀況的關鍵依據。

專案亮點:安全防禦與核心代碼解析

這個專案的價值不僅在於自動化測試,更在於其 API 內建的安全防禦機制。

Laravel 產品控制器 (laravel-app/app/Http/Controllers/ProductController.php)

  • XSS 防禦:在 showsearch 方法中,所有返回的 JSON 數據都通過 Response::jsonEscaped() 巨集進行處理。這個巨集會對所有字串進行 HTML 實體轉義,確保任何惡意腳本不會在前端被執行,從而有效防禦 XSS 攻擊。

  • SQL 注入防禦:在 search 方法中,Laravel 的 Eloquent ORM 查詢構建器(如 where('name', 'like', ...))會自動使用參數綁定。這表示用戶輸入的內容不會直接拼接到 SQL 查詢字串中,而是作為安全參數處理,從根本上杜絕了 SQL 注入的風險。

FastAPI 攻擊模擬器 (fastapi-tester/app/api/attack_simulator.py)

  • 這個模組負責模擬真實的攻擊情境,例如 XSS 攻擊。它會發送包含惡意 <script> 標籤的請求,然後檢查 Laravel API 的響應,驗證是否已將這些標籤轉義。如果原始的 <script> 仍然存在於響應中,則表示防禦失敗。

報告生成腳本 (scripts/generate_report.py)

  • 這個 Python 腳本是一個報告聚合器,它能解析不同格式的測試報告 (JUnit XML, JSON),並將關鍵信息(總測試數、失敗數、漏洞警報等)整合到一份易於閱讀的 Markdown 報告中。

常見問題與注意事項

  • 無法直接運行 init.sh:本倉庫不包含 init.sh 或完整的 Laravel 結構。請參考本文檔的「安裝與使用方法」設置環境。

  • 如何設置資料庫遷移?:您需要自行撰寫 database/migrations/database/seeders/ 檔案,可參考 Laravel 官方文件或本倉庫中的範例代碼。

  • FastAPI 測試失敗?:請確保 requirements.txt 依賴已安裝,並檢查 API 是否運行於 http://localhost:8000/api

  • 如何整合 OWASP ZAP?:設置 ZAP 容器,指向 API 的 openapi.json,參考本文檔中「運行安全測試」的 ZAP 命令。

  • CI/CD 流程:若要將此專案整合到 CI/CD 管線(如 GitLab CI/CD),您需要自行撰寫 .gitlab-ci.yml 文件。專案的 buildtestsecurity_scanreport 階段應依序執行。

結語與貢獻

OWASP Hardened API Suite 是一個實用的 DevSecOps 學習與實踐工具。它提供了一個堅實的基礎,讓您可以深入了解 API 安全性、自動化測試以及如何將這些流程整合到您的開發工作流中。

這是一個範例專案,如果您在使用過程中遇到任何問題,或有任何改進建議,歡迎您通過提交 Issue 或 Pull Request 來貢獻您的力量。您的貢獻將有助於專案的成長和完善!

沒有留言:

張貼留言

網誌存檔