在現代資安測試與 DevOps 實踐中,技術測試資料的管理與報告生成往往耗費大量時間與人力。測試人員不僅需要執行各種掃描與檢測工具,更需要將分散的測試結果整合為清晰易讀的專業報告。傳統的手動處理方式不僅效率低落,更容易因人為疏失導致資料遺漏或格式不一致的問題。

本文將介紹如何運用 Bash 腳本作為核心整合工具,結合 Nmap 網路掃描、jq 進行 JSON 資料解析、SQLite 提供輕量級資料庫儲存,以及 LaTeX 實現專業級報告排版。透過這套完整的自動化流程,不僅能有效管理技術測試過程中產生的大量資料,更能確保報告的一致性與專業度。

技術測試資料管理的核心挑戰

在進行技術測試時,測試人員經常面臨多個層面的挑戰。首先是資料來源的多樣性,不同的掃描工具會產生不同格式的輸出結果,例如 Nmap 產生 XML 格式報告,而現代的 Web 掃描工具則多採用 JSON 格式。這些異質性的資料格式需要個別處理與解析,增加了資料整合的複雜度。

其次是資料量的問題。在大規模網路環境中執行掃描時,可能會產生數千甚至數萬筆掃描記錄。如何有效儲存、查詢與分析這些資料,成為測試效率的關鍵因素。傳統使用文字檔或試算表的方式,在面對大量資料時顯得力不從心。

最後是報告生成的品質要求。專業的技術測試報告需要包含詳細的測試結果、漏洞描述、風險評估與修復建議。報告的格式需要統一且美觀,內容必須準確完整。手動編寫這樣的報告不僅耗時,更難以維持一致的品質標準。

網路掃描資料收集與解析

Nmap 作為業界標準的網路掃描工具,能夠提供豐富的主機與服務資訊。在實際應用中,Nmap 會將掃描結果輸出為 XML 格式,其中包含了主機狀態、開放埠號、服務版本等詳細資訊。要有效利用這些資料,首先需要理解 XML 報告的結構組成。

@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

package "Nmap XML 報告結構" {
  [nmaprun] as root
  [scaninfo] as info
  [verbose] as verb
  [debugging] as debug
  [host] as host
  [status] as status
  [address] as addr
  [hostnames] as names
  [ports] as ports
  [port] as port
  [state] as state
  [service] as service
  [script] as script
}

root --> info
root --> verb
root --> debug
root --> host
host --> status
host --> addr
host --> names
host --> ports
ports --> port
port --> state
port --> service
port --> script

@enduml

Nmap 的 XML 輸出採用階層式結構,根元素為 nmaprun,其下包含掃描資訊、詳細程度設定、除錯資訊等全域配置。每個被掃描的主機都以 host 元素表示,其中記錄了主機的狀態資訊、IP 位址、主機名稱與埠號資訊。埠號資訊又進一步細分為埠號狀態、服務辨識結果以及可能的腳本掃描輸出。

要從 XML 格式中提取所需資訊,可以使用 xmlstarlet 工具。這個工具提供了類似 XPath 的查詢語法,能夠精確定位並提取 XML 文件中的特定欄位。例如要取得所有 IPv4 位址,可以執行以下指令。這個指令會遍歷整個 XML 文件,找出所有類型為 ipv4 的 address 元素,並提取其 addr 屬性值。

xmllint --xpath "//host/address[@addrtype='ipv4']/@addr" nmap.xml

除了傳統的 XML 格式外,現代的掃描工具越來越多採用 JSON 格式輸出結果。JSON 格式具有更好的可讀性與程式處理便利性,特別適合與自動化腳本整合。以 HTTP/HTTPS 指紋掃描為例,工具通常會產生包含時間戳記、埠號、URL、網頁標題、協定類型、Web 伺服器類型與狀態碼等資訊的 JSON 物件。

@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

object "httpx.json" as root {
  timestamp
  port
  url
  title
  scheme
  webserver
  status_code
}

root : timestamp = "2025-11-20T10:30:00Z"
root : port = 443
root : url = "https://example.com"
root : title = "範例網站"
root : scheme = "https"
root : webserver = "nginx/1.24.0"
root : status_code = 200

@enduml

處理 JSON 格式資料時,jq 工具是最佳選擇。jq 提供了強大的查詢與轉換功能,能夠輕鬆提取巢狀物件中的特定欄位。例如要檢視整個 JSON 結構,可以使用簡單的點運算子。這個指令會將 JSON 內容格式化輸出,方便人工檢視與分析。

cat httpx.json | jq .

當需要提取特定欄位時,jq 支援使用路徑表達式。假設要取得 Web 伺服器的類型資訊,可以直接指定欄位路徑。這種語法不僅直觀,更能處理複雜的巢狀結構。

cat httpx.json | jq -r '.webserver'

對於包含陣列的 JSON 結構,jq 提供了陣列操作符號。使用方括號配合索引值可以存取特定位置的元素,而使用空方括號則會遍歷整個陣列。這種彈性的語法設計,使得 jq 能夠應對各種複雜的資料結構。

JSON 資料深層解析技術

在處理真實世界的技術測試資料時,JSON 結構往往比簡單範例複雜許多。巢狀物件、多層陣列、混合型態的資料結構都是常見的情況。要有效處理這些複雜資料,需要深入理解 jq 的查詢語法與操作方式。

假設我們面對一個包含家族樹狀結構的 JSON 資料,其中包含父節點、子節點以及兄弟節點的資訊。這種結構在實際應用中很常見,例如組織架構、網路拓撲或是系統相依關係等場景。

{
    "parent": {
        "name": "Family Tree",
        "child": {
            "name": "John",
            "age": 10
        },
        "siblings": [
            {
                "child": {
                    "name": "Emma",
                    "age": 8
                }
            },
            {
                "child": {
                    "name": "Michael",
                    "age": 12
                }
            }
        ]
    }
}

要從這樣的巢狀結構中提取資訊,需要運用 jq 的多種查詢技巧。首先是基本的物件導航,使用點運算子可以逐層深入物件結構。例如要取得父節點的名稱,可以使用 parent.name 路徑。這種方式直觀且易於理解,適合處理單純的物件階層。

echo "$json_data" | jq '.parent.name'

當遇到陣列結構時,jq 提供了陣列迭代器。使用方括號配合空白可以遍歷陣列中的所有元素。結合物件導航與陣列迭代,就能提取深層巢狀資料。例如要取得所有兄弟節點的名稱,需要先進入 siblings 陣列,再逐一存取每個元素的 child 物件。

echo "$json_data" | jq '.parent.siblings[].child.name'

jq 的強大之處在於能夠組合多個查詢表達式。使用逗號運算子可以同時提取多個欄位,這在需要建立資料集合時特別有用。例如要同時取得直接子節點與所有兄弟節點的年齡資訊,可以將兩個查詢表達式合併。

echo "$json_data" | jq '.parent.child.age, .parent.siblings[].child.age'

在實際的自動化腳本中,通常需要將 JSON 解析邏輯封裝為可重用的函式。這樣不僅能提高程式碼的可讀性,更便於維護與除錯。以下是一個完整的 Bash 函式範例,展示如何整合 jq 進行資料提取。

#!/usr/bin/env bash

# 解析 JSON 資料並提取關鍵欄位
parse_json() {
    local json_file=$1
    local json_content=$(cat "$json_file")
    
    # 提取使用者名稱
    local user_name=$(echo "$json_content" | jq -r '.user_name // "未指定"')
    
    # 提取第一個技術標籤
    local first_tech=$(echo "$json_content" | jq -r '.technologies[0] // "無"')
    
    # 提取所有技術標籤
    local all_techs=$(echo "$json_content" | jq -r '.technologies[]' | tr '\n' ', ')
    
    # 輸出解析結果
    echo "使用者名稱: $user_name"
    echo "主要技術: $first_tech"
    echo "所有技術: ${all_techs%,}"
}

# 執行解析函式
parse_json "data.json"

這個函式展示了幾個重要的技巧。首先是使用 jq 的替代運算子(//)來處理欄位不存在的情況,避免程式因資料缺失而中斷。其次是結合 tr 指令進行後處理,將陣列元素轉換為逗號分隔的字串。最後是使用參數擴展(${all_techs%,})移除尾端的逗號,確保輸出格式正確。

SQLite 輕量級資料庫建置

當測試資料量增加到一定規模時,單純使用文字檔或 JSON 檔案進行儲存與管理會變得不切實際。資料的查詢、更新與分析都需要更有效率的解決方案。SQLite 作為一個自包含的嵌入式資料庫引擎,為這個問題提供了理想的答案。

SQLite 的最大優勢在於其簡潔性與可攜性。整個資料庫就是一個檔案,不需要額外的伺服器程序,也不需要複雜的設定程序。這種設計特別適合自動化腳本的應用場景,因為可以直接透過指令列工具進行所有操作。同時 SQLite 完整支援 SQL 語法,提供了強大的查詢與資料處理能力。

在建立資料庫之前,需要先規劃資料表的結構。對於 Nmap 掃描結果,我們需要記錄 IP 位址、主機名稱、埠號、協定類型、服務名稱、版本資訊、掃描時間以及可能的漏洞描述。這些欄位共同構成了完整的掃描記錄。

#!/usr/bin/env bash

# 定義資料庫檔案名稱
DB_NAME="pentest_results.db"

# 建立資料庫並定義資料表結構
sqlite3 $DB_NAME <<EOF
CREATE TABLE IF NOT EXISTS nmap_scans (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    ip_address TEXT NOT NULL,
    hostname TEXT,
    port INTEGER NOT NULL,
    protocol TEXT NOT NULL,
    service TEXT,
    version TEXT,
    scan_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    vulnerability TEXT,
    UNIQUE(ip_address, port, protocol)
);

-- 建立索引以加速查詢
CREATE INDEX IF NOT EXISTS idx_ip_address ON nmap_scans(ip_address);
CREATE INDEX IF NOT EXISTS idx_port ON nmap_scans(port);
CREATE INDEX IF NOT EXISTS idx_scan_date ON nmap_scans(scan_date);
EOF

echo "資料庫建立完成: $DB_NAME"

這段腳本使用了 Bash 的 heredoc 語法將 SQL 指令傳遞給 SQLite。資料表定義中使用了多個重要的 SQL 特性。PRIMARY KEY AUTOINCREMENT 確保每筆記錄都有唯一的識別碼,NOT NULL 約束保證關鍵欄位不會是空值,DEFAULT CURRENT_TIMESTAMP 自動記錄資料建立時間,UNIQUE 約束則防止相同 IP 位址與埠號的重複記錄。

除了基本的資料表定義外,建立適當的索引對於查詢效能至關重要。索引能夠大幅加速資料檢索速度,特別是在資料量龐大時。在這個範例中,我們為經常用於查詢條件的欄位建立了索引,包括 IP 位址、埠號與掃描日期。

將 Nmap 掃描結果匯入資料庫需要解析 XML 格式並轉換為 SQL INSERT 陳述式。這個過程可以透過 xmlstarlet 工具配合 Bash 迴圈完成。以下腳本展示了完整的匯入流程。

#!/usr/bin/env bash

DB_NAME="pentest_results.db"
NMAP_XML_FILE="$1"

# 檢查檔案是否存在
if [ ! -f "$NMAP_XML_FILE" ]; then
    echo "錯誤: 找不到檔案 $NMAP_XML_FILE"
    exit 1
fi

# 使用 xmlstarlet 解析 XML 並格式化輸出
xmlstarlet sel -t -m "//host" \
    -v "address/@addr" -o "|" \
    -v "hostnames/hostname/@name" -o "|" \
    -m "ports/port" \
    -v "@portid" -o "|" \
    -v "@protocol" -o "|" \
    -v "service/@name" -o "|" \
    -v "service/@version" -n \
    "$NMAP_XML_FILE" | while IFS='|' read -r ip hostname port protocol service version; do
    
    # 處理空值情況
    hostname="${hostname:-未知主機}"
    service="${service:-未知服務}"
    version="${version:-未知版本}"
    
    # 插入資料到資料庫,使用 INSERT OR IGNORE 避免重複
    sqlite3 $DB_NAME <<SQL
    INSERT OR IGNORE INTO nmap_scans (ip_address, hostname, port, protocol, service, version)
    VALUES ('$ip', '$hostname', '$port', '$protocol', '$service', '$version');
SQL
    
    # 顯示進度
    echo "已匯入: $ip:$port ($service)"
done

echo "資料匯入完成"

這個匯入腳本包含了完善的錯誤處理與資料驗證機制。首先檢查輸入檔案是否存在,避免因檔案不存在而導致錯誤。xmlstarlet 的輸出格式使用管線符號(|)作為欄位分隔符號,方便 Bash 進行欄位分割。在插入資料前,腳本會檢查並處理空值情況,確保資料庫中不會出現空字串。使用 INSERT OR IGNORE 語法能夠優雅地處理重複記錄,避免插入失敗。

資料匯入完成後,往往需要根據進一步的分析結果更新漏洞資訊。SQLite 的 UPDATE 陳述式提供了靈活的資料更新能力。以下是一個更新漏洞描述的範例。

#!/usr/bin/env bash

DB_NAME="pentest_results.db"
IP_ADDRESS="192.168.1.100"
PORT=80
VULNERABILITY="SQL Injection 漏洞:應用程式未正確過濾使用者輸入,導致可能的資料庫注入攻擊"

# 更新指定記錄的漏洞描述
sqlite3 $DB_NAME <<SQL
UPDATE nmap_scans 
SET vulnerability = '$VULNERABILITY' 
WHERE ip_address = '$IP_ADDRESS' 
  AND port = $PORT 
  AND (vulnerability IS NULL OR vulnerability = '');
SQL

# 檢查更新結果
UPDATED_ROWS=$(sqlite3 $DB_NAME "SELECT changes();")
echo "已更新 $UPDATED_ROWS 筆記錄"

這個更新腳本展示了如何安全地更新資料庫記錄。WHERE 子句確保只有符合特定條件的記錄會被更新,避免意外修改其他資料。透過檢查 vulnerability 欄位是否為空,可以避免覆寫已存在的漏洞描述。使用 changes() 函式能夠取得實際更新的記錄數量,提供操作回饋。

資料查詢與格式化輸出

將資料儲存在 SQLite 資料庫後,下一步是建立查詢與顯示機制。雖然可以直接使用 sqlite3 指令列工具執行查詢,但為了提供更好的使用者體驗,需要對輸出進行格式化處理。以下是一個完整的查詢腳本範例。

#!/usr/bin/env bash

DB_NAME="pentest_results.db"

# 字串截斷函式,確保每個欄位不超過指定長度
truncate_string() {
    local string="$1"
    local max_length="$2"
    
    if [ ${#string} -gt $max_length ]; then
        echo "${string:0:$((max_length-3))}..."
    else
        printf "%-${max_length}s" "$string"
    fi
}

# 列印表格標題
print_header() {
    printf "%-16s | %-20s | %-6s | %-10s | %-18s | %-25s | %s\n" \
        "IP 位址" "主機名稱" "埠號" "協定" "服務" "版本" "漏洞描述"
    printf "%s\n" "$(printf '=%.0s' {1..130})"
}

# 查詢並格式化輸出
display_results() {
    print_header
    
    sqlite3 -separator "|" "$DB_NAME" \
        "SELECT ip_address, hostname, port, protocol, service, version, vulnerability 
         FROM nmap_scans 
         ORDER BY ip_address, port;" |
    while IFS='|' read -r ip hostname port protocol service version vulnerability; do
        # 處理空值顯示
        hostname="${hostname:-N/A}"
        service="${service:-N/A}"
        version="${version:-N/A}"
        vulnerability="${vulnerability:-尚未發現}"
        
        # 截斷過長的字串
        ip=$(truncate_string "$ip" 16)
        hostname=$(truncate_string "$hostname" 20)
        port=$(truncate_string "$port" 6)
        protocol=$(truncate_string "$protocol" 10)
        service=$(truncate_string "$service" 18)
        version=$(truncate_string "$version" 25)
        vulnerability=$(truncate_string "$vulnerability" 30)
        
        # 輸出格式化的資料列
        printf "%-16s | %-20s | %-6s | %-10s | %-18s | %-25s | %s\n" \
            "$ip" "$hostname" "$port" "$protocol" "$service" "$version" "$vulnerability"
    done
    
    echo ""
    echo "查詢完成"
}

# 執行查詢
display_results

這個查詢腳本包含了完整的格式化邏輯。truncate_string 函式負責處理過長的字串,確保每個欄位都能整齊對齊。當字串超過指定長度時,會截斷並加上省略符號,讓使用者知道還有更多內容。print_header 函式輸出表格標題與分隔線,提供清晰的視覺結構。

@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

start

:查詢 SQLite 資料庫;
:取得掃描記錄;

while (還有記錄?) is (是)
  :讀取記錄欄位;
  :處理空值;
  :截斷過長字串;
  :格式化輸出;
endwhile (否)

:顯示統計資訊;

stop

@enduml

在實際應用中,可能需要根據不同條件進行查詢。例如只顯示特定 IP 範圍的記錄,或是只列出存在漏洞的主機。透過修改 SQL 查詢語句,可以輕鬆實現這些需求。

# 只顯示存在漏洞的記錄
sqlite3 -separator "|" "$DB_NAME" \
    "SELECT ip_address, hostname, port, vulnerability 
     FROM nmap_scans 
     WHERE vulnerability IS NOT NULL AND vulnerability != ''
     ORDER BY ip_address;"

# 統計每個 IP 位址的開放埠號數量
sqlite3 -header -column "$DB_NAME" \
    "SELECT ip_address AS 'IP 位址', 
            COUNT(*) AS '開放埠號數量',
            GROUP_CONCAT(port, ', ') AS '埠號列表'
     FROM nmap_scans 
     GROUP BY ip_address 
     ORDER BY COUNT(*) DESC;"

# 找出特定服務的所有實例
sqlite3 -header -column "$DB_NAME" \
    "SELECT ip_address, port, version 
     FROM nmap_scans 
     WHERE service LIKE '%ssh%'
     ORDER BY ip_address;"

這些進階查詢展示了 SQL 的強大功能。GROUP_CONCAT 函式能夠將多筆記錄的資料合併為單一字串,COUNT 函式提供統計功能,LIKE 運算子支援模糊比對。透過組合這些功能,可以進行複雜的資料分析。

LaTeX 專業報告生成

技術測試報告的品質直接影響客戶對測試工作的評價。一份專業的報告不僅需要包含完整的測試結果,更需要清晰的結構、一致的格式與美觀的排版。LaTeX 作為學術界與專業領域廣泛使用的文件排版系統,為這些需求提供了完美的解決方案。

LaTeX 的核心優勢在於將內容與格式分離。撰寫者只需專注於內容的邏輯結構,格式排版由 LaTeX 引擎自動處理。這種方式特別適合自動化生成報告的場景,因為可以透過程式產生 LaTeX 原始碼,再由 LaTeX 編譯為精美的 PDF 文件。

一份基本的 LaTeX 文件包含文件類別宣告、套件載入、文件屬性設定與實際內容。以下是一個技術測試報告的基本框架。

\documentclass[12pt,a4paper]{article}

% 載入必要套件
\usepackage[utf8]{inputenc}
\usepackage{xeCJK}  % 支援中文
\usepackage{geometry}  % 版面設定
\usepackage{fancyhdr}  % 頁首頁尾
\usepackage{graphicx}  % 圖片支援
\usepackage{listings}  % 程式碼區塊
\usepackage{xcolor}  % 顏色支援
\usepackage{longtable}  % 跨頁表格

% 設定中文字型
\setCJKmainfont{Microsoft JhengHei UI}

% 版面配置
\geometry{
    left=2.5cm,
    right=2.5cm,
    top=3cm,
    bottom=3cm
}

% 頁首頁尾設定
\pagestyle{fancy}
\fancyhf{}
\fancyhead[L]{技術測試報告}
\fancyhead[R]{\today}
\fancyfoot[C]{\thepage}

% 文件開始
\begin{document}

\title{技術測試報告}
\author{資安團隊}
\date{\today}
\maketitle

\section{執行摘要}
本次技術測試針對目標系統進行全面性的安全評估...

\section{測試範圍}
測試範圍包含以下網段與系統...

\section{測試結果}
以下為詳細的測試發現...

\end{document}

要將 SQLite 資料庫中的資料整合到 LaTeX 報告,需要查詢資料庫並產生對應的 LaTeX 表格語法。以下腳本展示了如何自動產生包含掃描結果的 LaTeX 文件。

#!/usr/bin/env bash

DB_NAME="pentest_results.db"
OUTPUT_FILE="report.tex"

# 產生 LaTeX 文件標頭
cat > "$OUTPUT_FILE" <<'EOF'
\documentclass[12pt,a4paper]{article}
\usepackage[utf8]{inputenc}
\usepackage{xeCJK}
\usepackage{geometry}
\usepackage{longtable}
\usepackage{booktabs}
\usepackage{xcolor}

\setCJKmainfont{Microsoft JhengHei UI}
\geometry{left=2cm, right=2cm, top=2.5cm, bottom=2.5cm}

\begin{document}

\title{網路掃描技術測試報告}
\author{資安測試團隊}
\date{\today}
\maketitle

\section{掃描結果彙總}

以下表格呈現網路掃描的詳細結果。

\begin{longtable}{|p{3cm}|p{3cm}|p{1.5cm}|p{2cm}|p{2.5cm}|p{3cm}|}
\hline
\textbf{IP 位址} & \textbf{主機名稱} & \textbf{埠號} & \textbf{協定} & \textbf{服務} & \textbf{版本} \\
\hline
\endfirsthead

\multicolumn{6}{c}{\textit{接續上頁}} \\
\hline
\textbf{IP 位址} & \textbf{主機名稱} & \textbf{埠號} & \textbf{協定} & \textbf{服務} & \textbf{版本} \\
\hline
\endhead

\hline
\multicolumn{6}{r}{\textit{接續下頁}} \\
\endfoot

\hline
\endlastfoot

EOF

# 查詢資料庫並產生表格內容
sqlite3 -separator "|" "$DB_NAME" \
    "SELECT ip_address, 
            COALESCE(hostname, 'N/A'), 
            port, 
            protocol, 
            COALESCE(service, 'N/A'), 
            COALESCE(version, 'N/A')
     FROM nmap_scans 
     ORDER BY ip_address, port;" |
while IFS='|' read -r ip hostname port protocol service version; do
    # 跳脫特殊字元
    hostname="${hostname//_/\\_}"
    service="${service//_/\\_}"
    version="${version//_/\\_}"
    
    # 產生表格列
    echo "$ip & $hostname & $port & $protocol & $service & $version \\\\" >> "$OUTPUT_FILE"
    echo "\\hline" >> "$OUTPUT_FILE"
done

# 產生文件結尾
cat >> "$OUTPUT_FILE" <<'EOF'
\end{longtable}

\section{漏洞發現}

以下為測試過程中發現的安全漏洞。

EOF

# 產生漏洞表格
sqlite3 -separator "|" "$DB_NAME" \
    "SELECT ip_address, 
            port, 
            service,
            vulnerability
     FROM nmap_scans 
     WHERE vulnerability IS NOT NULL AND vulnerability != ''
     ORDER BY ip_address;" |
while IFS='|' read -r ip port service vulnerability; do
    echo "\\subsection{$ip:$port - $service}" >> "$OUTPUT_FILE"
    echo "" >> "$OUTPUT_FILE"
    echo "$vulnerability" >> "$OUTPUT_FILE"
    echo "" >> "$OUTPUT_FILE"
done

# 完成文件
echo "\\end{document}" >> "$OUTPUT_FILE"

echo "LaTeX 報告已產生: $OUTPUT_FILE"
echo "執行以下指令編譯 PDF:"
echo "xelatex $OUTPUT_FILE"

這個報告產生腳本整合了資料庫查詢與 LaTeX 文件產生。腳本首先建立 LaTeX 文件的標頭部分,包含必要的套件載入與版面設定。接著查詢資料庫並將每筆記錄轉換為 LaTeX 表格的一列。使用 COALESCE 函式處理空值,確保表格中不會出現空白欄位。

在產生表格內容時,需要注意 LaTeX 的特殊字元跳脫。底線(_)在 LaTeX 中是特殊字元,需要使用反斜線進行跳脫。腳本使用 Bash 的字串替換功能自動處理這個問題。

產生 LaTeX 原始碼後,需要使用 LaTeX 編譯器將其轉換為 PDF 文件。由於文件包含中文內容,應使用支援 Unicode 的 XeLaTeX 編譯器。

# 編譯 LaTeX 文件為 PDF
xelatex report.tex

# 如果文件包含參考文獻或目錄,需要執行多次
xelatex report.tex
xelatex report.tex

編譯完成後會產生 report.pdf 檔案,其中包含格式化的掃描結果與漏洞資訊。這個 PDF 文件可以直接提供給客戶或管理階層,作為正式的技術測試報告。

完整自動化工作流程整合

將前述的各個元件整合為完整的自動化工作流程,需要一個主控腳本來協調各個步驟的執行。這個主控腳本負責執行掃描、解析結果、更新資料庫、產生報告等所有操作。

#!/usr/bin/env bash

# 工作流程設定
PROJECT_NAME="技術測試專案"
TARGET_NETWORK="192.168.1.0/24"
WORKSPACE="./pentest_workspace"
DB_NAME="$WORKSPACE/results.db"
NMAP_OUTPUT="$WORKSPACE/nmap_scan.xml"
REPORT_OUTPUT="$WORKSPACE/report.tex"

# 建立工作目錄
mkdir -p "$WORKSPACE"

echo "=========================================="
echo "$PROJECT_NAME - 自動化測試流程"
echo "=========================================="
echo ""

# 步驟一:執行網路掃描
echo "[步驟 1/5] 執行 Nmap 網路掃描"
echo "目標網段: $TARGET_NETWORK"
nmap -sV -sC -oX "$NMAP_OUTPUT" "$TARGET_NETWORK" || {
    echo "錯誤: Nmap 掃描失敗"
    exit 1
}
echo "掃描完成,結果已儲存至 $NMAP_OUTPUT"
echo ""

# 步驟二:建立資料庫
echo "[步驟 2/5] 初始化 SQLite 資料庫"
./create_database.sh "$DB_NAME" || {
    echo "錯誤: 資料庫建立失敗"
    exit 1
}
echo "資料庫建立完成: $DB_NAME"
echo ""

# 步驟三:匯入掃描結果
echo "[步驟 3/5] 匯入掃描結果至資料庫"
./import_nmap_results.sh "$NMAP_OUTPUT" "$DB_NAME" || {
    echo "錯誤: 資料匯入失敗"
    exit 1
}
echo "掃描結果已成功匯入資料庫"
echo ""

# 步驟四:顯示掃描摘要
echo "[步驟 4/5] 產生掃描結果摘要"
echo ""
sqlite3 -header -column "$DB_NAME" \
    "SELECT 
        COUNT(DISTINCT ip_address) as '主機數量',
        COUNT(*) as '開放埠號總數',
        COUNT(DISTINCT service) as '服務類型數量'
     FROM nmap_scans;"
echo ""

# 步驟五:產生 LaTeX 報告
echo "[步驟 5/5] 產生技術測試報告"
./generate_latex_report.sh "$DB_NAME" "$REPORT_OUTPUT" || {
    echo "錯誤: 報告產生失敗"
    exit 1
}
echo "報告原始檔已產生: $REPORT_OUTPUT"
echo ""

# 編譯 PDF 報告
echo "正在編譯 PDF 報告..."
cd "$WORKSPACE" && xelatex "$(basename $REPORT_OUTPUT)" > /dev/null 2>&1
if [ $? -eq 0 ]; then
    echo "PDF 報告產生成功: $WORKSPACE/report.pdf"
else
    echo "警告: PDF 編譯失敗,請檢查 LaTeX 安裝"
fi
cd - > /dev/null

echo ""
echo "=========================================="
echo "自動化測試流程執行完畢"
echo "=========================================="
echo ""
echo "工作目錄: $WORKSPACE"
echo "資料庫: $DB_NAME"
echo "報告: $WORKSPACE/report.pdf"

這個主控腳本展示了完整的自動化流程設計。腳本開頭定義了所有必要的設定參數,包括專案名稱、目標網段、工作目錄等。每個步驟都包含清晰的狀態訊息輸出,讓使用者了解目前的執行進度。

錯誤處理是自動化腳本的重要環節。腳本在每個關鍵步驟後檢查執行結果,如果發生錯誤立即終止並顯示錯誤訊息。這種設計能夠避免錯誤累積,確保每個步驟都成功完成後才繼續下一步。

@startuml
!define PLANTUML_FORMAT svg
!theme _none_

skinparam dpi auto
skinparam shadowing false
skinparam linetype ortho
skinparam roundcorner 5
skinparam defaultFontName "Microsoft JhengHei UI"
skinparam defaultFontSize 16
skinparam minClassWidth 100

start

:建立工作目錄;

:執行 Nmap 網路掃描;
note right
  掃描目標網段
  產生 XML 格式報告
end note

if (掃描成功?) then (是)
  :建立 SQLite 資料庫;
  
  if (資料庫建立成功?) then (是)
    :解析 XML 報告;
    :匯入資料至資料庫;
    
    if (匯入成功?) then (是)
      :查詢資料庫;
      :產生統計摘要;
      :產生 LaTeX 報告;
      
      if (報告產生成功?) then (是)
        :編譯 PDF 文件;
        
        if (編譯成功?) then (是)
          :顯示完成訊息;
        else (否)
          :顯示編譯警告;
        endif
      else (否)
        :顯示錯誤: 報告產生失敗;
      endif
    else (否)
      :顯示錯誤: 資料匯入失敗;
    endif
  else (否)
    :顯示錯誤: 資料庫建立失敗;
  endif
else (否)
  :顯示錯誤: 掃描失敗;
endif

stop

@enduml

進階功能與擴充建議

基本的自動化流程建立完成後,可以根據實際需求進行各種擴充與優化。以下是幾個常見的進階功能方向。

首先是多種掃描工具的整合。除了 Nmap 之外,實際的技術測試可能還會使用其他專用工具,例如 Web 應用程式掃描器、漏洞掃描器等。可以擴充資料庫結構以支援不同類型的測試結果,並開發相應的匯入腳本。

# 擴充資料表結構以支援 Web 掃描結果
sqlite3 $DB_NAME <<EOF
CREATE TABLE IF NOT EXISTS web_scans (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    url TEXT NOT NULL,
    status_code INTEGER,
    title TEXT,
    server TEXT,
    technologies TEXT,
    scan_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    UNIQUE(url)
);

CREATE TABLE IF NOT EXISTS vulnerabilities (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    scan_id INTEGER,
    scan_type TEXT,
    severity TEXT,
    title TEXT,
    description TEXT,
    recommendation TEXT,
    discovered_date DATETIME DEFAULT CURRENT_TIMESTAMP,
    FOREIGN KEY(scan_id) REFERENCES nmap_scans(id)
);
EOF

其次是報告模板的客製化。不同的客戶或專案可能有不同的報告格式要求。可以開發多個 LaTeX 模板,讓使用者根據需求選擇適合的樣式。模板可以包含公司標誌、特定的色彩配置、客製化的頁首頁尾等元素。

% 企業版報告模板
\documentclass[12pt,a4paper]{report}

\usepackage{xeCJK}
\usepackage{graphicx}
\usepackage{fancyhdr}
\usepackage[colorlinks=true,linkcolor=blue]{hyperref}

% 載入公司標誌
\usepackage{eso-pic}
\AddToShipoutPictureBG{%
  \AtPageUpperLeft{%
    \raisebox{-\height}{%
      \includegraphics[width=5cm]{company_logo.png}%
    }%
  }%
}

% 定義色彩主題
\definecolor{primary}{RGB}{0,70,127}
\definecolor{secondary}{RGB}{0,122,204}

% 客製化章節標題樣式
\usepackage{titlesec}
\titleformat{\chapter}[display]
  {\normalfont\huge\bfseries\color{primary}}
  {\chaptertitlename\ \thechapter}{20pt}{\Huge}

第三是自動化漏洞修復建議。可以在資料庫中建立漏洞知識庫,包含常見漏洞的描述、風險等級與修復建議。當發現特定漏洞時,自動匹配對應的修復建議並納入報告中。

# 建立漏洞知識庫表格
sqlite3 $DB_NAME <<EOF
CREATE TABLE IF NOT EXISTS vulnerability_kb (
    id INTEGER PRIMARY KEY AUTOINCREMENT,
    cve_id TEXT UNIQUE,
    title TEXT NOT NULL,
    severity TEXT NOT NULL,
    description TEXT,
    remediation TEXT,
    references TEXT
);

-- 插入範例資料
INSERT INTO vulnerability_kb (cve_id, title, severity, description, remediation) VALUES
('CVE-2024-1234', 'SQL 注入漏洞', '高',
 '應用程式未正確驗證使用者輸入,導致可能的 SQL 注入攻擊',
 '實作參數化查詢,使用準備陳述式(Prepared Statements),並驗證所有使用者輸入'),
('CVE-2024-5678', '跨站腳本攻擊', '中',
 '應用程式未正確過濾輸出內容,可能導致 XSS 攻擊',
 '對所有輸出內容進行編碼,實作內容安全政策(CSP)');
EOF

第四是報告的多語言支援。對於國際化的測試專案,可能需要產生多種語言版本的報告。可以將報告中的固定文字抽取為語言檔案,透過腳本參數選擇輸出語言。

最後是與其他系統的整合。可以開發 API 介面,讓其他系統能夠查詢測試結果。或是實作通知機制,當發現高風險漏洞時自動發送警示郵件。這些擴充功能能夠讓自動化系統更好地融入整體的安全運營流程。

實務應用考量與最佳實踐

在實際部署這套自動化系統時,有幾個重要的考量點需要注意。首先是資料安全性。技術測試結果通常包含敏感資訊,包括系統漏洞、網路架構等。資料庫檔案應該妥善保護,設定適當的檔案權限,避免未授權存取。

# 設定資料庫檔案權限,僅允許擁有者讀寫
chmod 600 "$DB_NAME"

# 設定工作目錄權限
chmod 700 "$WORKSPACE"

# 加密敏感資料
# 可以使用 gpg 或其他加密工具保護報告檔案
gpg --symmetric --cipher-algo AES256 report.pdf

其次是效能考量。當掃描範圍擴大時,資料量可能會急遽增加。需要定期維護資料庫,清理過時的測試記錄,確保查詢效能。可以實作資料歸檔機制,將歷史資料移轉到長期儲存。

# 清理超過三個月的舊資料
sqlite3 $DB_NAME <<EOF
DELETE FROM nmap_scans 
WHERE scan_date < datetime('now', '-3 months');

-- 執行資料庫最佳化
VACUUM;
EOF

# 備份資料庫
BACKUP_FILE="$WORKSPACE/backup_$(date +%Y%m%d).db"
cp "$DB_NAME" "$BACKUP_FILE"
gzip "$BACKUP_FILE"

第三是錯誤記錄與除錯。自動化腳本應該實作完善的日誌記錄機制,記錄每個步驟的執行狀況與可能的錯誤訊息。這對於問題診斷與系統維護非常重要。

# 設定日誌檔案
LOG_FILE="$WORKSPACE/automation.log"

# 記錄函式
log_message() {
    local level=$1
    shift
    echo "[$(date '+%Y-%m-%d %H:%M:%S')] [$level] $*" | tee -a "$LOG_FILE"
}

# 使用範例
log_message "INFO" "開始執行網路掃描"
log_message "ERROR" "掃描失敗: 目標主機無回應"
log_message "SUCCESS" "報告產生完成"

第四是版本控制。自動化腳本與報告模板應該納入版本控制系統,追蹤變更歷史。這不僅有助於團隊協作,更能在發生問題時快速回溯到穩定版本。

最後是文件維護。完整的使用說明與技術文件是系統長期維護的基礎。文件應該包含系統架構說明、各個腳本的功能與參數、故障排除指南等內容。

透過這套完整的自動化系統,技術測試人員能夠更專注於分析與評估工作,而非繁瑣的資料處理與報告撰寫。系統不僅提升了工作效率,更確保了測試結果的一致性與報告的專業度。隨著持續的優化與擴充,這個自動化平台能夠成為技術測試工作流程中不可或缺的基礎設施。