概述#
Web server 最簡單的定義是一個回應 HTTP 請求並回傳 HTML 頁面的電腦程式。但現代 web server 的功能遠不止於此——它們能動態生成網頁 HTML、從資料庫載入內容,並執行伺服器端程式碼。本章探討開發者如何在 web server 中組織程式碼與資源,並指出常見的安全弱點。
Static 與 Dynamic Resources#
Web server 回應 HTTP 請求時提供兩種類型的內容:
- Static resource:HTML 檔案、圖片或其他檔案,web server 不經修改直接回傳
- Dynamic resource:程式碼、腳本或模板,web server 在回應 HTTP 請求時執行或解譯
Web server 根據 URL 中的路徑決定回傳哪種資源,並透過設定檔將 URL pattern 對應到特定資源。
Static Resources#
早期的網站#
在網際網路早期,網站幾乎完全由 static resources 組成:
- 開發者手動編寫 HTML 檔案
- 「部署」意味著將 HTML 檔案複製到 web server 並重啟服務
- 每個網頁對應伺服器上的一個 HTML 檔案
- 1996 年電影 Space Jam 的網站(spacejam.com)就是這種模式的典型例子
URL Resolution#
現代 web server 處理 static resources 的方式與早期類似:
- 瀏覽器在 URL 中包含資源名稱,web server 從磁碟回傳對應檔案
- 現代 web server 允許將任何 URL 對應到任意 static resource,URL 不必與實際檔案路徑一致
- 這種解耦讓開發者有更大的自由度來組織程式碼
現代 Web Server 的額外處理#
回傳 static resource 時,現代 web server 通常會進行額外處理:
- 使用 gzip 演算法壓縮大型資源檔案以減少頻寬
- 在 HTTP response 中加入 caching headers,指示瀏覽器快取資源
- 這些措施提升網站回應速度並降低伺服器負載
Static resources 本身不太容易產生安全漏洞,但 URL 解析到檔案的過程可能引入漏洞。如果使用者指定某些檔案為私有(例如上傳的圖片),需要在 web server 上定義 access control 規則。

Figure 4-1: 靜態資源範例
Content Delivery Networks (CDN)#
Content Delivery Network (CDN) 是一種提升 static resource 傳輸速度的技術:
- 在全球各地的資料中心儲存 static resources 的副本
- 從離使用者最近的節點傳送資源
- 常見的 CDN 服務包括 Cloudflare、Akamai、Amazon CloudFront
- 讓小公司也能在不需大量伺服器支出的情況下提供高效能網站
使用 CDN 也會引入安全考量——你實際上是讓第三方在你的安全憑證下提供內容,因此需要確保 CDN 整合的安全設定正確。
Content Management Systems (CMS)#
許多以 static content 為主的網站使用 Content Management System (CMS) 來建構:
- CMS 提供編寫工具,不需技術背景即可撰寫內容
- 統一網站風格,允許管理員直接在瀏覽器中編輯內容
- CMS plug-in 可提供分析、客戶管理、線上商店等功能
- 常見的第三方服務整合:Google Analytics、Facebook Login、Zendesk
使用第三方程式碼雖然理論上更安全(因為這些服務有專業安全團隊),但它們的普及性也使其成為駭客的目標。例如,許多自架的 WordPress 實例(最流行的 CMS)很少更新安全修補。使用第三方程式碼時,必須持續關注安全公告並及時部署修補。

Figure 4-2: 透過搜尋引擎找到未受保護的 WordPress 實例
Dynamic Resources#
為何需要 Dynamic Resources#
手動編寫個別 HTML 檔案既費時又不實際。想像零售網站每新增一件商品就得手寫一個新網頁——這完全不可擴展。
大多數現代網站使用 dynamic resources:
- 程式碼從 database 載入資料來填充 HTTP response
- 通常輸出 HTML,但也可回傳其他內容類型
- 允許零售網站用單一產品頁面展示各種商品——從 URL 提取產品代碼,從資料庫載入價格、圖片和描述,再插入 HTML
Dynamic resources 的其他應用場景包括銀行網站(顯示帳戶資訊)、搜尋引擎(回傳搜尋結果)、社群媒體(為每位使用者動態建構不同的 HTML)。
Dynamic resources 雖然實用,但也帶來新的安全漏洞。動態內容插入 HTML 的過程容易受到攻擊,例如惡意 JavaScript injection(詳見 Chapter 7)或跨站請求(詳見 Chapter 8)。
Templates#
早期的 dynamic resources 是簡單的腳本檔案(通常用 Perl 撰寫),在使用者造訪特定 URL 時由 web server 執行。但這種方式的程式碼難以閱讀和維護。
Templates 解決了這個問題:
- 主要是 HTML,但其中穿插了程式邏輯指令
- 邏輯通常做三件事之一:
- 從資料庫或 HTTP request 提取資料並插入 HTML
- 條件性地顯示 HTML 模板的某些區段
- 迴圈遍歷資料結構(如列表)來重複生成 HTML 區塊
- 所有現代 web framework 都使用 template 檔案,因為將程式碼片段插入 HTML 讓程式碼更乾淨、更易讀
Databases#
Web server 執行 dynamic resource 的程式碼時,通常需要從 database 載入資料。資料庫在現代網站中無處不在——儲存使用者資訊、產品資料、認證憑證等。Web server 與資料庫之間的介面是駭客經常攻擊的目標。
最常用的兩種資料庫類型是 SQL 和 NoSQL。
SQL Databases#
SQL(Structured Query Language)資料庫是最常見的關聯式資料庫:
- Relational(關聯式):將資料儲存在一個或多個相互關聯的 tables 中
- 每個 table 類似 Excel 試算表,有 rows(資料項目)和 columns(資料欄位)
- Columns 有預定義的資料型別(文字、數字、日期等)
關聯式資料庫的關鍵概念:
- Primary key:每一行的唯一數字識別碼
- Foreign key:引用其他 table 中特定行的 primary key,建立表之間的關聯
- Data integrity constraints:防止資料損壞的規則(如 unique 約束、non-null 約束)
- Transactional:一組 SQL 語句作為一個 batch 執行,全部成功或全部失敗(all or nothing)
- Consistent:任何成功的 transaction 都將資料庫從一個有效狀態帶到另一個有效狀態
SQL 資料庫中的資料通常非常敏感,駭客經常以竊取資料庫內容為目標,並利用不安全的 SQL 語句進行攻擊(詳見 Chapter 6)。
NoSQL Databases#
NoSQL 資料庫因效能考量而日漸流行,它犧牲了嚴格的 data integrity 要求以獲得更大的可擴展性:
- 通常是 schemaless(無結構定義),可以自由新增欄位
- 資料常以 key-value 形式或 JSON 格式儲存
- 優先考慮大規模資料複製,保證 eventual consistency(最終一致性)而非絕對一致性
- 儲存非結構化或半結構化資料很容易,但查詢較為複雜
NoSQL 資料庫同樣容易受到 injection 攻擊,儘管攻擊者需要正確猜測資料庫類型才能成功發動攻擊。
Distributed Caches#
Dynamic resources 也可以從記憶體中的 distributed caches 載入資料:
- Caching:將資料副本儲存在容易取得的位置以加速存取
- Distributed caches(如 Redis、Memcached)讓不同伺服器和程序能跨語言共享資料結構
- 適合儲存頻繁存取的資料,避免每次都從資料庫查詢
大型網站通常將技術架構實作為一系列 microservices——簡單、模組化的服務,各自執行一個動作。這些服務透過 distributed cache 溝通:
- Queues(佇列):將任務放入等待狀態,由 worker processes 逐一處理
- Publish-subscribe channels:讓多個程序註冊對某類事件的興趣,事件發生時批量通知
Distributed caches 與資料庫一樣容易受到攻擊,但 Redis 和 Memcached 開發時安全最佳實踐已經較為成熟,因此其 SDK 中通常已內建安全措施。
Web Programming Languages#
Web server 在處理 dynamic resources 時需要執行程式碼。多種程式語言都可以用來撰寫 web server 程式碼,每種語言有不同的安全考量。
Ruby (on Rails)#
- Ruby 在 1990 年代中期於日本發明,直到 Ruby on Rails 平台推出後才廣泛流行
- Rails 內建許多建構大型 web application 的最佳實踐,設定需求極少
- Rails 社群重視安全,是最早內建 cross-site request forgery 防護的 web framework 之一
- 但 Rails 的普及也使其成為駭客目標,曾發現多個重大安全漏洞
- Microframeworks(如 Sinatra)作為 Rails 的輕量替代方案也越來越受歡迎
Python#
- Python 在 1980 年代末發明,以簡潔語法和豐富模組聞名
- 廣泛用於資料科學和科學計算
- Web 開發方面有 Django 和 Flask 等成熟的 web server 框架
- Web server 框架的多樣性本身也是一種安全優勢——駭客較難針對特定平台
JavaScript 和 Node.js#
- JavaScript 最初是瀏覽器端的簡單腳本語言,後來發展為伺服器端語言
- Node.js 執行在 V8 JavaScript engine 之上(與 Google Chrome 使用的相同引擎)
- 前後端使用相同語言是 Node 快速增長的主因
- 最大安全風險來自其快速增長的 module 生態系統——每天都有數百個新模組加入,使用第三方程式碼時需格外謹慎
PHP#
- PHP 從一組 C binaries 發展為完整的程式語言,主要用於 Linux 上的動態網站
- 語言設計的演進並非計劃性的,導致不一致性(如變數名稱大小寫敏感,但函式名稱不敏感)
- 儘管有這些怪異之處,PHP 仍然驅動約 10% 的網站
如果你正在維護 PHP 程式碼,很可能是在維護 legacy 系統。較舊的 PHP framework 展示了一些最嚴重的安全漏洞——command execution、directory traversal、buffer overflow 等問題都曾困擾 PHP 開發者。應儘快更新為現代程式庫。
Java#
- Java 和 Java Virtual Machine (JVM) 在企業領域廣泛使用
- 可跨多個作業系統執行編譯後的 bytecode,在需要效能時是可靠選擇
- 從安全角度看,Java 受其過去的流行度所累——大量 legacy 程式碼執行在舊版本上
- JVM 上的其他語言:Clojure(Lisp 方言)、Scala(靜態型別函數式語言)、Kotlin(向後相容 Java 的物件導向語言)
C##
- C# 由 Microsoft 作為 .NET 計畫的一部分設計
- 使用 Common Language Runtime (CLR) 虛擬機
- 比 Java 更接近作業系統層級,可與 C++ 程式碼混合使用
- 大多數使用 C# 的公司部署在 Windows server 上
Windows 在安全方面有著不光彩的歷史——例如它是最常見的病毒目標平台。任何考慮採用 .NET 作為平台的人都需要意識到這些風險。
Client-Side JavaScript#
在瀏覽器端執行的程式碼只有一個選擇:JavaScript。
現代瀏覽器中的 JavaScript#
JavaScript 在瀏覽器中的功能已遠超早期的表單驗證和動畫小工具:
- 複雜網站(如 Facebook)使用 JavaScript 在使用者互動時重繪頁面區域
- 不需重新整理整個頁面即可實現動態 UI(如點擊顯示選單、開啟對話框)
- 可在背景事件發生時更新介面(如新增通知標記)
Client-Side JavaScript Frameworks#
實現動態 UI 需要 client-side JavaScript 在記憶體中管理大量狀態。主要的 framework 包括:
Angular(由 Google 開源釋出):
- 借鑑 server-side 範式,使用 client-side templates 渲染頁面
- Template engine 在瀏覽器中執行,解析伺服器提供的 HTML 並處理 directives
- 可直接操作 DOM,當記憶體狀態改變時自動重新渲染
React(由 Facebook 開源釋出):
- 鼓勵開發者直接在 JavaScript 中撰寫類 HTML 標籤
- 使用 JSX(JavaScript XML)檔案,經過 preprocessor 編譯為 JavaScript
- 將 HTML 作為 JavaScript 語法的一等元素
直接操作 DOM 的 JavaScript 程式碼容易產生新型安全漏洞:DOM-based cross-site scripting attacks(詳見 Chapter 7)。
其他編譯為 JavaScript 的語言#
雖然瀏覽器只能執行 JavaScript,但開發者可以使用 CoffeeScript 或 TypeScript 等語言撰寫程式碼,在 build 過程中 transpile(轉譯)為 JavaScript。這些語言與 JavaScript 有相同的安全漏洞。
總結#
- Web server 回應 HTTP 請求時提供兩種內容:static resources(如圖片)和 dynamic resources(執行自訂程式碼)
- Static resources 可從檔案系統或 CDN 直接提供;使用 CMS 的網站通常由非技術人員在瀏覽器中編輯
- Dynamic resources 通常是以 templates 定義的 HTML,其中穿插程式邏輯,從 database 或 cache 讀取資料
- 最常見的資料庫是 SQL 資料庫(表格式、嚴格規則);較大型網站也使用 NoSQL 資料庫(放鬆約束以獲得更高可擴展性)
- Dynamic resources 使用各種 web programming languages 撰寫,每種語言有其安全特性
- 瀏覽器端程式碼只能使用 JavaScript,現代 client-side framework(如 Angular、React)帶來了新的安全考量