在現代資安測試與 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
@endumlNmap 的 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" "報告產生完成"
第四是版本控制。自動化腳本與報告模板應該納入版本控制系統,追蹤變更歷史。這不僅有助於團隊協作,更能在發生問題時快速回溯到穩定版本。
最後是文件維護。完整的使用說明與技術文件是系統長期維護的基礎。文件應該包含系統架構說明、各個腳本的功能與參數、故障排除指南等內容。
透過這套完整的自動化系統,技術測試人員能夠更專注於分析與評估工作,而非繁瑣的資料處理與報告撰寫。系統不僅提升了工作效率,更確保了測試結果的一致性與報告的專業度。隨著持續的優化與擴充,這個自動化平台能夠成為技術測試工作流程中不可或缺的基礎設施。