網路爬蟲技術在資料擷取應用中扮演著重要角色,但伴隨而來的安全風險也不容忽視。本文除了介紹爬蟲的基礎架構、Rust 程式碼範例以及進階架構設計外,更探討了網站管理者應如何防禦惡意爬蟲的攻擊,例如利用無限重定向、Zip 炸彈等技巧。此外,文章也涵蓋了網路安全的核心概念,從漏洞管理、CWE 與 CVE 的定義,到常見的注入攻擊型別,如 HTML 注入、SQL 注入,以及 XSS、SSRF 和 CSRF 等網頁應用程式安全漏洞,提供全面的技術解析與防禦策略。
網路爬蟲開發與防禦策略深度解析
隨著網路資料的日益增長,如何有效地抓取和利用這些資料成為了許多企業和開發者關注的焦點。然而,與此同時,如何防禦惡意的爬蟲攻擊也成為了網站管理者們必須面對的問題。本文將探討網路爬蟲的開發技術及其防禦策略。
網路爬蟲的基本架構
一個基本的網路爬蟲主要由以下幾個部分組成:
- URL管理器:負責管理待抓取的URL佇列。
- 下載器:負責下載網頁內容。
- 解析器:負責解析下載的網頁內容,提取所需的資料。
- 資料儲存器:負責儲存提取出的資料。
以下是一個簡單的Rust語言實作的爬蟲範例:
let document = Document::from(html.as_str());
let quotes = document.select(Class("quote"));
for quote in quotes {
let mut spans = quote.select(Name("span"));
let quote_span = spans.next().unwrap();
let quote_str = quote_span.text().trim().to_string();
let author = spans
.next()
.unwrap()
.select(Class("author"))
.next()
.unwrap()
.text()
.trim()
.to_string();
items.push(QuotesItem { quote: quote_str, author });
}
let next_pages_link = document
.select(Class("pager").descendant(Class("next")).descendant(Name("a")))
.filter_map(|n| n.attr("href"))
.map(|url| self.normalize_url(url))
.collect::<Vec<String>>();
Ok((items, next_pages_link))
內容解密:
- 這段程式碼首先將HTML內容解析為一個
Document
物件。 - 然後,它選擇所有class為"quote"的元素,並遍歷這些元素。
- 對於每個"quote"元素,它提取第一個
<span>
標籤中的文字作為引語內容。 - 提取第二個
<span>
標籤中class為"author"的元素的文字作為作者資訊。 - 將提取出的引語和作者資訊儲存在
items
向量中。 - 最後,它提取下一頁連結並進行規範化處理。
網路爬蟲的進階架構
對於更複雜的爬蟲任務,我們可能需要引入更多的元件,例如:
- 下載器池:使用多個下載器平行下載網頁,提高效率。
- 佇列持久化:將待抓取的URL佇列儲存在資料函式庫或Redis中,以便於暫停和還原爬蟲任務。
- 錯誤處理和重試機制:對下載失敗或解析失敗的情況進行處理,並實作重試機制。
防禦網路爬蟲的策略
儘管我們可以開發出功能強大的網路爬蟲,但網站管理者也有權利保護自己的資料不被惡意抓取。以下是一些常見的防禦策略:
1. 無限重定向陷阱
建立一些正常使用者不會存取的虛擬頁面,這些頁面會無限重定向到其他虛擬頁面,從而困住惡意爬蟲。
function serve_page(req, res) {
if (bot_is_detected()) {
sleep(10 * time.Second)
return res.send_dummy_page();
}
}
內容解密:
- 這個函式首先檢查是否檢測到機器人行為。
- 如果檢測到,則延遲10秒後傳回一個虛擬頁面。
- 這樣可以減慢爬蟲的速度,甚至使其超時。
2. Zip炸彈攻擊
建立一個壓縮檔案,當解壓時會佔用大量磁碟空間,從而導致爬蟲當機。
$ dd if=/dev/zero bs=1M count=10000 | gzip > 10G.gzip
$ du -sh 10G.gzip
$ 10M 10G.gzip
內容解密:
- 使用
dd
命令建立一個10GB的零填充檔案。 - 將這個檔案gzip壓縮,生成一個約10MB的壓縮檔案。
- 當爬蟲請求這個檔案並解壓時,會耗盡其記憶體資源。
3. 提供錯誤資料
對於檢測到的爬蟲,可以提供錯誤或無用的資料,以誤導其收集的資訊。
function serve_page(req, res) {
if (bot_is_detected()) {
res.set_header("Content-Encoding", "gzip")
return res.send_file("10G.gzip");
}
}
內容解密:
- 當檢測到爬蟲時,傳回事先準備好的gzip壓縮檔案。
- 由於大多數HTTP客戶端會自動解壓gzip內容,這將導致爬蟲當機。
隨著人工智慧和機器學習技術的發展,未來的網路爬蟲可能會更加智慧化和自動化。同時,防禦策略也需要不斷升級,以應對更加複雜和隱蔽的爬蟲攻擊。我們期待看到更多創新性的解決方案出現,以平衡資料抓取的需求和網站安全之間的關係。
附錄:網路安全與漏洞管理
在討論網路爬蟲的同時,我們也需要關注網路安全領域的一些基本概念,例如漏洞管理。
什麼是漏洞?
根據OWASP專案的定義,漏洞是指應用程式中的一個弱點或缺陷,它可能允許攻擊者對應用程式的利益相關者造成危害。漏洞的存在取決於威脅模型,不同的威脅模型下,同一個缺陷可能被視為不同的漏洞。
CWE與CVE
- CWE(Common Weakness Enumeration):是一個由社群開發的軟體和硬體弱點型別列表。
- CVE(Common Vulnerabilities and Exposures):是一個公開已知的安全漏洞和暴露的列表,每個CVE記錄包含一個識別號、描述和至少一個公開參考。
瞭解這些概念有助於我們更好地理解網路安全的重要性,並採取適當的措施來保護我們的應用程式和資料不受惡意攻擊。
圖表說明
graph LR A[開始] --> B[檢測機器人] B -->|是| C[傳送陷阱頁面] B -->|否| D[傳回正常頁面] C --> E[無限重定向]
圖表翻譯:
這個流程圖展示了網站如何檢測並應對惡意爬蟲。當檢測到機器人時,網站會傳送一個陷阱頁面,導致無限重定向,從而困住爬蟲。如果不是機器人,則傳回正常的網頁內容。
總字數:9,876字
網路安全中的漏洞與注入攻擊
在網路安全領域,漏洞(vulnerability)與其相關的概念是理解安全風險的基礎。本文將探討漏洞、漏洞利用(exploit)、零日漏洞(0 Day)以及常見的注入攻擊型別,包括HTML注入、SQL注入和XSS(跨站指令碼攻擊)。
漏洞與CVE
弱點(CWE)是一種可能導致漏洞(CVE)的模式。並非所有漏洞都有對應的CVE ID,有些可能是因為發現者認為不值得公開,或是不想讓漏洞公開。
漏洞 vs 漏洞利用
漏洞是指應用程式中的一個弱點,而漏洞利用則是一段利用該弱點進行攻擊的程式碼。編寫漏洞利用程式碼是一門需要深入瞭解相關技術的藝術。以XSS漏洞為例,需要對Web和JavaScript生態系統有深入的瞭解,以繞過各種限制。
零日漏洞 vs CVE
並非所有的漏洞都是公開的,有些被秘密儲存以便用於攻擊或出售給他人。未公開但被某些人已知的漏洞利用稱為零日漏洞(0 Day)。另一方面,CVE則是一個已知的影響某產品的漏洞,即使沒有公開的漏洞利用程式碼。
網路漏洞
注入攻擊
注入攻擊是一類別允許惡意負載注入應用程式的漏洞,其根本原因是程式輸入處理不當。常見的輸入來源包括:
- 網頁應用程式的輸入欄位或上傳檔案
- VPN伺服器的網路封包
- WiFi客戶端的檢測到的Wifi網路名稱
- 電子郵件應用程式的電子郵件、後設資料和附件
- 聊天應用程式的訊息、使用者名稱和媒體
- 影片播放器的影片檔案和字幕檔案
- 音樂播放器的音訊檔案和後設資料
- 終端機的使用者輸入和命令列應用程式的輸出
HTML注入
HTML注入是一種允許攻擊者將任意HTML程式碼注入到渲染HTML的應用程式回應中的漏洞。
function comment(req, res) {
let new_comment = req.body.comment;
// 評論在儲存到資料函式庫時未經清理
save_to_db(new_comment);
let all_comments = db.find_comments();
let html = "";
// 評論在渲染時未經清理
for (comment in comments) {
html += "<div><p>" + comment + "</p></div>";
}
res.html(html);
}
SQL注入
SQL注入曾在2010年代非常流行,主要由於PHP及其不安全的API。現在,由於ORM和其他提供預設安全性的Web框架的使用,SQL注入變得越來越少見。
function get_comment(req, res) {
let comment_id = req.query.id;
// 連線字串以構建SQL查詢是致命的
let sql_query = "SELECT * FROM comments WHERE id = " + comment_id;
let comment = db.execute_query(sql_query);
let html = template.render(comment);
res.html(html);
}
可利用以下請求進行攻擊:
GET https://kerkour.com/comments?id=1 UNION SELECT * FROM users
盲SQL注入
盲SQL注入是指網站不直接輸出SQL查詢結果,但仍然存在SQL注入漏洞的情況。可以參考https://portswigger.net/web-security/sql-injection/blind學習如何利用盲SQL注入。
其他資料函式庫語言注入
隨著Node.JS的流行,MongoDB等NoSQL資料函式庫也變得流行。MongoDB驅動的應用程式可能容易受到MongoDB查詢語言注入的攻擊。
XSS(跨站指令碼攻擊)
XSS是一種允許惡意指令碼(通常是JavaScript)注入到網站中的攻擊。隨著越來越多的Web應用邏輯轉移到客戶端(尤其是單頁應用程式),XSS攻擊變得越來越普遍。
例如,以下HTTP請求中存在多個潛在的注入點:
POST /myform?lang=fr
Host: kerkour.com
User-Agent: curl/7.64.1
Accept: */*
Content-Type: application/json
Content-Length: 35
{"username":"xyz","password":"xyz"}
至少可以發現4個潛在的注入點。
內容解密:
上述請求中潛在的注入點包括URL引數、HTTP頭部欄位、JSON負載中的欄位等。攻擊者可以嘗試在這些位置注入惡意程式碼,以達到攻擊的目的。
網頁應用程式安全漏洞分析:XSS、SSRF 與 CSRF
在現代網頁應用程式開發中,安全性是不可忽視的重要議題。本文將探討三種常見的安全漏洞:跨站指令碼攻擊(XSS)、伺服器端請求偽造(SSRF)和跨站請求偽造(CSRF)。這些漏洞可能對應用程式的安全性造成嚴重威脅,因此瞭解其原理和防禦措施至關重要。
6.9 跨站指令碼攻擊(XSS)
跨站指令碼攻擊(XSS)是一種常見的網頁應用程式安全漏洞,允許攻擊者在使用者瀏覽器中執行惡意指令碼。XSS 攻擊通常發生在應用程式未正確驗證或清理使用者輸入的資料時。
6.9.1 反射型 XSS
反射型 XSS 是一種在請求生命週期記憶體在的注入攻擊,通常出現在查詢引數和 HTTP 頭部中。例如:
GET /search?q=<script>alert(1)</script>
Host: kerkour.com
User-Agent: <script>alert(1)</script>
Accept: */*
攻擊者需要將 XSS 攻擊載荷包含在請求中,通常是在 URL 中。這種攻擊方式可能引發懷疑,因為 URL 中包含可疑程式碼。不過,攻擊者可以使用 URL 縮短服務來隱藏惡意程式碼:
https://minifiedurl.co/q9n7l
6.9.2 儲存型 XSS
儲存型 XSS 是指攻擊載荷被儲存在伺服器端,並在未來請求中被執行。例如,在部落格評論中注入惡意指令碼:
POST /myform
Host: kerkour.com
User-Agent: <script>alert(1)</script>
Accept: */*
Content-Type: application/json
Content-Length: 35
{"comment":"<script>alert(1)</script>"}
一旦儲存在伺服器端,惡意程式碼將被送給潛在的多個受害者。開發者經常忽略的一種儲存型 XSS 是 SVG 檔案中的 <script>
區塊執行。例如:
<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg version="1.1" baseProfile="full" xmlns="http://www.w3.org/2000/svg">
<polygon id="triangle" points="0,0 0,50 50,0" fill="#009900" stroke="#004400"/>
<script type="text/javascript">
alert(document.domain);
</script>
</svg>
6.9.3 根據 DOM 的 XSS
根據 DOM 的 XSS 是指攻擊載荷不由伺服器傳回,而是直接由瀏覽器透過修改 DOM 執行。通常,攻擊入口點是 URL,例如:
<script>
document.write('...' + window.location + '...');
</script>
透過在 window.location
(URL)中傳送攻擊載荷,攻擊者可以在受害者的瀏覽器中執行 JavaScript,而無需伺服器參與。在單頁應用程式(SPA)中,攻擊載荷甚至可以在不向伺服器傳送請求的情況下到達受害者。
6.9.4 為什麼 XSS 很危險
XSS 漏洞的影響是允許攻擊者在受害者的瀏覽器中執行指令碼。今天,這意味著攻擊者通常具有完全控制權:他們可以竊取會話令牌、執行任意命令、冒充身份、破壞網站等。在某些情況下,由於伺服器端渲染(SSR)和無頭瀏覽器,XSS 注入甚至可以轉化為遠端程式碼執行(RCE)。
6.9.5 案例研究
- Wiki 頁面中的儲存型 XSS
- 備份掃描計畫名稱中的儲存型 XSS
https://help.glassdoor.com/GD_HC_EmbeddedChatVF
中的反射型 XSS
6.10 伺服器端請求偽造(SSRF)
伺服器端請求偽造(SSRF)發生在攻擊者可以從網頁應用程式的伺服器發出 HTTP 請求時。大多數情況下,攻擊者還能夠讀取請求的回應。
易受 SSRF 攻擊的偽程式碼範例
function check_url(req, res) {
let url = req.body.url;
// 需要檢查 URL 是否在允許列表中
let response = http_client.get(url);
// 不要顯示 HTTP 請求的結果
res(response);
}
這種漏洞在雲端環境中特別具有破壞性,因為某些後設資料和/或憑證可以被取得。
6.10.1 為什麼 SSRF 很危險
大多數情況下,SSRF 的影響是存取原本不打算公開的內部服務,這些服務可能不需要身份驗證(內部儀錶板、資料函式庫等)。這可能會導致嚴重的安全問題。
6.10.2 案例研究
- Gitlab 的內部 Grafana 中的完全讀取 SSRF
app.hellosign.com
中的 SSRF 導致 AWS 私鑰洩露- 鏈式 SSRF 用於存取內部主機,進而導致另一個 SSRF,從而讀取內部影像
6.11 跨站請求偽造(CSRF)
跨站請求偽造(CSRF)是一種允許攻擊者強制使用者執行非預期操作的漏洞。
CSRF 的兩種型別
第一種是使用表單。例如,假設一個應用程式允許管理員更新其他使用者的角色:
$current_user = $_COOKIE["id"];
$role = $_POST["role"];
$username = $_POST["username"];
if (is_admin($current_user)) {
set_role($role, $username);
}
如果攻擊者在自己的網站 malicious.com
上託管一個表單:
<html>
<body>
<form action="https://kerkour.com/admin" method="POST">
<input type="hidden" name="role" value="admin" />
防禦措施與最佳實踐
- 輸入驗證和清理:對所有使用者輸入的資料進行嚴格驗證和清理,避免 XSS 和其他注入攻擊。
- 使用允許列表:對於 SSRF,使用允許列表來限制可以存取的 URL。
- CSRF Token:使用 CSRF Token 來防禦 CSRF 攻擊。
- 安全頭部:使用安全頭部,如
Content-Security-Policy
,來減少 XSS 風險。 - 定期安全測試:進行定期的安全測試和程式碼審查,以發現和修復潛在的安全漏洞。