Rust 語言以其高效能和安全性,成為建構漏洞掃描器的理想選擇。本文著重於使用 Rust 實作 HTTP 模組,以掃描常見 Web 漏洞,例如 Kibana 未授權存取和目錄列表洩露。程式碼範例展示瞭如何利用非同步特性提升掃描效率,並透過正規表示式精確識別漏洞特徵。此外,文章也引入了非同步測試方法,確保程式碼品質,並結合 GitHub Actions 實作 CI 自動化測試流程,提升開發效率。更進一步,本文也探討了網路爬蟲技術、OSINT 資訊收集方法以及搜尋引擎原理,並介紹了 Google Dorks 等實用技巧,幫助讀者全面掌握漏洞掃描的相關知識。
使用Rust開發高效的漏洞掃描器
在現代網路安全領域,漏洞掃描器扮演著至關重要的角色。本文將探討如何使用Rust程式語言開發一個高效的漏洞掃描器,涵蓋其設計原理、實作細節以及測試方法。
4.6 實作HTTP模組
在開發漏洞掃描器的過程中,我們首先需要實作HTTP模組。這些模組負責掃描特定的漏洞,例如Kibana未經身份驗證的存取和目錄列表洩露。
4.6.2 Kibana未經身份驗證的存取
Kibana是一個流行的日誌分析和視覺化工具,但如果組態不當,可能會允許未經身份驗證的存取。以下是一個使用Rust實作的Kibana未經身份驗證存取掃描模組的範例:
#[async_trait]
impl HttpModule for KibanaUnauthenticatedAccess {
async fn scan(
&self,
http_client: &Client,
endpoint: &str,
) -> Result<Option<HttpFinding>, Error> {
let url = format!("{}", &endpoint);
let res = http_client.get(&url).send().await?;
if !res.status().is_success() {
return Ok(None);
}
let body = res.text().await?;
if body.contains(r#"</head><body kbn-chrome id="kibana-body"><kbn-initial-state"#)
|| body.contains(r#"<div class="ui-app-loading"><h1><strong>Kibana</strong><small> is loading."#)
|| body.contains(r#"<div class="kibanaWelcomeLogo"></div></div></div><div class="kibanaWelcomeText">Loading Kibana</div></div>"#) {
return Ok(Some(HttpFinding::KibanaUnauthenticatedAccess(url)));
}
Ok(None)
}
}
#### 內容解密:
此段程式碼實作了一個名為KibanaUnauthenticatedAccess
的HTTP模組,用於掃描Kibana未經身份驗證的存取漏洞。
scan
函式是非同步的,接受一個http_client
和一個endpoint
作為引數。- 它首先向指定的
endpoint
傳送一個GET請求,並檢查回應狀態碼是否成功(200-299)。 - 如果回應成功,則讀取回應體並檢查是否包含特定的Kibana HTML標籤或字串,以判斷是否存在未經身份驗證的存取漏洞。
- 如果發現漏洞,則傳回
HttpFinding::KibanaUnauthenticatedAccess
,包含受影響的URL。
4.6.2.7 目錄列表洩露
目錄列表洩露是另一個常見的組態錯誤,可能導致伺服器上的檔案被未經授權的存取。以下是使用Rust實作的目錄列表洩露掃描模組的範例:
impl DirectoryListingDisclosure {
pub fn new() -> Self {
DirectoryListingDisclosure {
dir_listing_regex: Regex::new(r"<title>Index of .*</title>")
.expect("compiling http/directory_listing regexp"),
}
}
async fn is_directory_listing(&self, body: String) -> Result<bool, Error> {
let dir_listing_regex = self.dir_listing_regex.clone();
let res = tokio::task::spawn_blocking(move || dir_listing_regex.is_match(&body)).await?;
Ok(res)
}
}
#[async_trait]
impl HttpModule for DirectoryListingDisclosure {
async fn scan(
&self,
http_client: &Client,
endpoint: &str,
) -> Result<Option<HttpFinding>, Error> {
let url = format!("{}/", &endpoint);
let res = http_client.get(&url).send().await?;
if !res.status().is_success() {
return Ok(None);
}
let body = res.text().await?;
if self.is_directory_listing(body).await? {
return Ok(Some(HttpFinding::DirectoryListingDisclosure(url)));
}
Ok(None)
}
}
#### 內容解密:
此段程式碼實作了一個名為DirectoryListingDisclosure
的HTTP模組,用於掃描目錄列表洩露漏洞。
DirectoryListingDisclosure
結構體包含一個正規表示式,用於匹配目錄列表頁面的標題。is_directory_listing
函式檢查給定的HTML回應體是否包含目錄列表的特徵。- 在
scan
函式中,首先向指定的endpoint
傳送GET請求,並檢查回應狀態碼。 - 如果回應成功,則讀取回應體並使用
is_directory_listing
函式檢查是否存在目錄列表洩露。 - 如果發現漏洞,則傳回
HttpFinding::DirectoryListingDisclosure
,包含受影響的URL。
4.7 測試
在開發漏洞掃描器的過程中,測試是至關重要的環節。良好的測試可以確保程式碼的正確性和可靠性。
4.7.1 非同步測試
Rust提供了對非同步測試的良好支援。以下是一個非同步測試的範例:
#[cfg(test)]
mod tests {
use super::DirectoryListingDisclosure;
#[tokio::test]
async fn is_directory_listing() {
let module = DirectoryListingDisclosure::new();
let body = String::from("Content <title>Index of kerkour.com</title> test");
let body2 = String::from(">ccece> Contrnt <tle>Index of kerkour.com</title> test");
let body3 = String::from("");
let body4 = String::from("test test test test test< test> test <title>Index</title> test");
assert_eq!(true, module.is_directory_listing(body).await.unwrap());
assert_eq!(false, module.is_directory_listing(body2).await.unwrap());
assert_eq!(false, module.is_directory_listing(body3).await.unwrap());
assert_eq!(false, module.is_directory_listing(body4).await.unwrap());
}
}
#### 內容解密:
此段程式碼展示瞭如何為DirectoryListingDisclosure
模組編寫非同步測試。
- 使用
tokio::test
宏來標記非同步測試函式。 - 建立了多個不同的HTML回應體範例,用於測試
is_directory_listing
函式。 - 使用
assert_eq!
宏來驗證is_directory_listing
函式的輸出是否符合預期。
4.7.2 自動化測試
為了提高開發效率,應該將測試自動化。持續整合(CI)系統可以在每次程式碼提交時自動執行測試。
以下是一個GitHub Actions CI工作流程的範例:
name: CI
on:
push:
branches:
- main
- 'feature-**'
jobs:
test_phaser:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v2
- name: Update local toolchain
run: |
rustup update
rustup component add clippy
rustup install nightly
- name: Toolchain info
run: |
cargo --version --verbose
rustc --version
cargo clippy --version
- name: Lint
run: |
cd phaser
cargo fmt -- --check
cargo clippy -- -D warnings
- name: Test
run: |
cd phaser
cargo check
cargo test --all
- name: Build
run: |
cd phaser
cargo build --release
#### 內容解密:
此CI工作流程在每次推播程式碼到指定分支時自動執行。
- 更新Rust工具鏈並安裝必要的元件。
- 顯示工具鏈版本資訊。
- 執行程式碼格式檢查和Lint檢查。
- 編譯並執行所有測試。
- 以釋出模式編譯專案。
4.8 其他掃描器
在開發自己的漏洞掃描器時,可以參考現有的開源掃描器,例如:
- KubiScan:用於掃描Kubernetes叢集中的漏洞。
- SQLMap:用於檢測和利用SQL注入漏洞。
- 其他在GitHub上搜尋到的相關專案。
第5章 網路爬蟲與公開來源情報(OSINT)
5.1 公開來源情報(OSINT)簡介
公開來源情報(OSINT,Open Source Intelligence)是指利用公開可用的資訊來支援情報分析的技術和方法。值得注意的是,這裡的「Open Source」與開源軟體中的「Open Source」含義不同。
OSINT 的核心是從大量公開資料中提取有意義的資訊,因此自動化是 OSINT 過程中不可或缺的一部分。隨著資料量的指數級增長,手動收集和處理資訊變得越來越困難,因此開發自動化工具和指令碼來輔助 OSINT 工作顯得尤為重要。
5.2 OSINT 工具
Maltego 是 OSINT 領域中最知名的工具之一,它提供了一個功能強大的桌面應用程式,能夠視覺化、指令碼化和自動化調查過程。然而,Maltego 的專業版價格較高,可能不適合偶爾使用的使用者。此外,Maltego 的 SDK 僅支援少數幾種程式語言,這使得與某些程式語言(如 Rust)的整合變得困難。
// 使用 Rust 語言編寫的簡單網頁爬蟲範例
use reqwest;
async fn fetch_url(url: &str) -> Result<String, reqwest::Error> {
let response = reqwest::get(url).await?;
let body = response.text().await?;
Ok(body)
}
#[tokio::main]
async fn main() {
let url = "https://example.com";
match fetch_url(url).await {
Ok(body) => println!("Fetched content: {}", body),
Err(err) => println!("Error fetching URL: {}", err),
}
}
內容解密:
這段 Rust 程式碼展示瞭如何使用 reqwest
函式庫來非同步抓取網頁內容。fetch_url
函式接收一個 URL 字串,並傳回該 URL 的內容。主函式使用 Tokio 執行非同步操作,並列印抓取到的網頁內容或錯誤訊息。
相比之下,使用簡單的 Markdown 筆記和自製指令碼可以提供更大的靈活性。指令碼的結果可以貼入 Markdown 報告,或匯出為 CSV 或 JSON 檔案。所有資料都備份在 Git 儲存函式庫中。
利用 Pandoc 這類別工具,可以將 Markdown 報告匯出為多種格式,如 PDF、HTML、Docx、Epub、PPTX 和 Latex 等。此外,還可以使用 markmap 將 Markdown 檔案轉換為思維導圖。
其他有用的 OSINT 工具包括:
- Sherlock:用於在社交網路上搜尋特定使用者名稱的工具。
- theHarvester:用於收集電子郵件、子網域和姓名的工具。
- phoneinfoga:針對電話號碼的情報收集和 OSINT 框架。
- gitrob:針對 GitHub 組織的偵察工具。
5.3 搜尋引擎原理
搜尋引擎的主要功能是將海量的資料轉換為可搜尋和可操作的資訊。一個搜尋引擎通常由以下幾個部分組成:
- 爬蟲(Crawlers):負責遍歷資料海洋並將其轉換為結構化資料。
- 索引(Index):用於儲存爬蟲提取的結構化資料。
- 搜尋介面(Search Interface):允許使用者查詢索引中的資料。
graph LR A[爬蟲] -->|提取資料|> B[索引] B -->|提供資料|> C[搜尋介面] C -->|查詢|> B
圖表翻譯: 此圖示展示了搜尋引擎的基本架構。爬蟲負責從網路上提取資料,並將其存入索引中。搜尋介面允許使用者查詢索引,從而取得所需資訊。
OSINT 的本質是建立一個針對特定目標的專用搜尋引擎:從其他資料函式庫中爬取資料,並只索引與目標相關的有意義資訊,以便稍後進行搜尋。無論是使用 Markdown 報告、Maltego 還是傳統的資料函式庫(如 PostgreSQL),其背後的原理都是類別似的。
5.3.1 Google 搜尋引擎
Google 是全球最大的搜尋引擎,因此大部分所需資訊都可以在 Google 上找到。
5.3.1.1 Google 運算元
Google 提供了多種搜尋運算元來幫助使用者精確查詢,例如:
site:kerkour.com
:限制搜尋範圍在特定網站內。intitle:"Index of"
:搜尋標題中包含特定字串的頁面。intext:kerkour
:搜尋頁面內容中包含特定字串的頁面。inurl:hacking
:搜尋 URL 中包含特定字串的頁面。
5.3.1.2 Google dorks
Google dorks 是一些特殊的搜尋查詢,利用 Google 運算元來發現潛在的安全漏洞。例如:
intitle:"index of" ".env"
:用於發現洩露的.env
檔案。intitle:"Index of" "DCIM/camera"
:用於發現私人圖片。inurl:"/app/kibana" intitle:"Kibana"
:用於發現開放的 Kibana 控制檯。
這些查詢可以幫助發現潛在的安全問題,但也需要謹慎使用,以免觸犯法律。
5.4 物聯網與網路搜尋引擎
除了傳統的網頁搜尋引擎,還有一些專門用於物聯網和網路裝置的搜尋引擎,例如:
- Shodan
- Censys
這些搜尋引擎允許使用者輸入 IP 位址、網域名稱或服務名稱,然後傳回相關的裝置或服務資訊。
5.5 社交媒體
社交媒體的選擇通常取決於目標區域。常見的社交媒體平台包括 Facebook、Twitter、VK、Instagram 和 Reddit 等。
5.6 地圖資訊
地圖資訊(如 Google Maps)可以用來進行物理層面的情報收集。例如,透過定位目標附近的餐廳,可能能夠發現目標公司的員工,並進一步收集相關資訊。
5.7 影片資訊
隨著影片格式的興起,每天都有越來越多的敏感資訊透過影片洩露。YouTube 和 Twitch 是兩個主要的影片平台。在分析目標公司的影片時,需要注意以下三點:
- 誰出現在影片中?
- 影片是在哪裡拍攝的?背景中有什麼建築或標誌?
- 背景中有沒有洩露敏感資訊,例如憑證或組織結構圖?
5.8 政府公開記錄
幾乎所有國家都有關於企業、專利、商標等的公開記錄,這些資訊可以幫助調查人員連線不同的資訊點,從而獲得更全面的情報。
總之,OSINT 是一項綜合性的技術,需要結合多種工具和方法來收集和分析公開可用的資訊。透過自動化指令碼和適當的工具,可以大大提高 OSINT 的效率和效果。