關鍵要點
跨站腳本攻擊是互聯網上每天發生的五大安全攻擊之一,您的 PHP 腳本也可能無法倖免。這種攻擊也稱為 XSS,它基本上是一種代碼注入攻擊,由於用戶數據驗證不正確而成為可能,這些數據通常通過 Web 表單或使用更改後的超鏈接插入到頁面中。注入的代碼可以是任何惡意的客戶端代碼,例如 JavaScript、VBScript、HTML、CSS、Flash 等。該代碼用於在服務器上保存有害數據或在用戶的瀏覽器中執行惡意操作。不幸的是,跨站腳本攻擊主要發生是因為開發人員未能提供安全的代碼。每個 PHP 程序員都有責任了解如何對他們的 PHP 腳本進行攻擊以利用可能的安全漏洞。閱讀本文,您將了解有關跨站腳本攻擊的更多信息以及如何在您的代碼中防止它們。
通過示例學習
讓我們來看下面的代碼片段。
<code class="language-php"><form action="post.php" method="post"> <input type="text" name="comment" value=""> <input type="submit" name="submit" value="Submit"> </form></code>
這裡我們有一個簡單的表單,其中有一個文本框用於數據輸入和一個提交按鈕。提交表單後,它將提交數據到 post.php 進行處理。假設 post.php 只輸出數據,如下所示:
<code class="language-php"><?php echo $_POST["comment"]; ?></code>
沒有任何過濾,黑客可以通過表單提交以下內容,這將在瀏覽器中生成一個帶有消息“hacked”的彈出窗口。
<code class="language-javascript">alert("hacked")</code>
這個例子,儘管本質上是惡意的,但似乎並沒有造成太大危害。但是,想想如果 JavaScript 代碼被編寫為竊取用戶的 cookie 並從中提取敏感信息會發生什麼?有比簡單的 alert() 調用更糟糕的 XSS 攻擊。
跨站腳本攻擊可以分為兩大類,基於它們傳遞惡意有效負載的方式:非持久性 XSS 和持久性 XSS。請允許我詳細討論每種類型。
也稱為反射型 XSS 攻擊,這意味著惡意代碼實際上並未存儲在服務器上,而是通過服務器傳遞並呈現給受害者,這是兩種傳遞方法中更流行的 XSS 策略。攻擊是從外部來源發起的,例如電子郵件或第三方網站。這是一個簡單的搜索結果腳本的一部分示例:
<code class="language-php"><form action="post.php" method="post"> <input type="text" name="comment" value=""> <input type="submit" name="submit" value="Submit"> </form></code>
此示例可能是一個非常不安全的成果頁面,其中搜索查詢會顯示回用戶。這裡的問題是,$_GET["query"]
變量未經驗證或轉義,因此攻擊者可以向受害者發送以下鏈接:
<code class="language-php"><?php echo $_POST["comment"]; ?></code>
無需驗證,頁面將包含:
<code class="language-javascript">alert("hacked")</code>
當惡意代碼已經通過驗證過程並存儲在數據存儲中時,就會發生這種類型的攻擊。這可能是評論、日誌文件、通知消息或網站上任何其他需要用戶輸入的部分。稍後,當此特定信息顯示在網站上時,惡意代碼就會執行。讓我們使用以下示例來創建一個基本的基於文件的評論系統。假設我前面介紹的相同表單,假設接收腳本只是將評論附加到數據文件。
<code class="language-php"><?php // 根据查询获取搜索结果 echo "You searched for: " . $_GET["query"]; // 列出搜索结果 ...</code>
在其他地方,comments.txt 的內容顯示給訪問者:
<code>http://example.com/search.php?query=alert("hacked")</code>
當用戶提交評論時,它會被保存到數據文件中。然後,整個文件(因此是整個評論系列)將顯示給讀者。如果提交了惡意代碼,則它將被保存並按原樣顯示,沒有任何驗證或轉義。
防止跨站腳本攻擊
幸運的是,與對不受保護的網站進行 XSS 攻擊一樣容易,防止它們也同樣容易。但是,即使在編寫一行代碼之前,預防也必須始終銘記在心。任何 Web 環境(無論是開發、暫存還是生產)都需要“強制執行”的第一條規則是永遠不要信任來自用戶或任何其他第三方來源的數據。這怎麼強調都不為過。必須驗證每一位數據輸入,並在輸出時進行轉義。這是防止 XSS 的黃金法則。為了實施防止 XSS 攻擊的可靠安全措施,我們應該注意數據驗證、數據清理和輸出轉義。
數據驗證是確保應用程序使用正確數據運行的過程。如果您的 PHP 腳本期望用戶輸入整數,則任何其他類型的數據都將被丟棄。接收到的每條用戶數據都必須經過驗證,以確保其類型正確,如果未通過驗證過程,則將其丟棄。例如,如果您想驗證電話號碼,您將丟棄包含字母的任何字符串,因為電話號碼應僅包含數字。您還應考慮字符串的長度。如果您想更寬鬆一些,您可以允許有限的一組特殊字符,例如加號、括號和破折號,這些字符通常用於格式化特定於您目標區域設置的電話號碼。
<code class="language-php"><form action="post.php" method="post"> <input type="text" name="comment" value=""> <input type="submit" name="submit" value="Submit"> </form></code>
數據清理側重於操作數據以確保其安全,方法是從數據中刪除任何不需要的位並將其規範化為正確的形式。例如,如果您期望純文本字符串作為用戶輸入,您可能希望從中刪除任何 HTML 標記。
<code class="language-php"><?php echo $_POST["comment"]; ?></code>
有時,數據驗證和清理/規範化可以同時進行。
<code class="language-javascript">alert("hacked")</code>
為了保護顯示/輸出數據的完整性,您應該在將數據呈現給用戶時對其進行轉義。這可以防止瀏覽器對可能找到的任何特殊字符序列應用任何意外的含義。
<code class="language-php"><?php // 根据查询获取搜索结果 echo "You searched for: " . $_GET["query"]; // 列出搜索结果 ...</code>
現在一起!
為了更好地理解數據處理的三個方面,讓我們再次查看前面基於文件的評論系統,並對其進行修改以確保其安全。代碼中的潛在漏洞源於這樣一個事實,即 $_POST["comment"]
被盲目地附加到 comments.txt 文件中,然後直接顯示給用戶。為了確保其安全,應在將 $_POST["comment"]
值添加到文件之前對其進行驗證和清理,並且在將文件內容顯示給用戶時應對其進行轉義。
<code>http://example.com/search.php?query=alert("hacked")</code>
該腳本首先驗證傳入的評論,以確保用戶已提供非零長度字符串。畢竟,空白評論不是很有趣。數據驗證需要在一個定義良好的上下文中進行,這意味著如果我期望從用戶那裡獲得一個整數,那麼我會通過將數據轉換為整數並將其作為整數處理來相應地對其進行驗證。如果這導致無效數據,則只需將其丟棄並讓用戶知道。然後,腳本通過刪除可能包含的任何 HTML 標記來清理評論。最後,檢索、過濾和顯示評論。通常,htmlspecialchars()
函數足以過濾打算在瀏覽器中查看的輸出。但是,如果您在網頁中使用的字符編碼不是 ISO-8859-1 或 UTF-8,那麼您可能需要使用 htmlentities()
。有關這兩個函數的更多信息,請閱讀官方 PHP 文檔中的各自說明。請記住,在像 Web 這樣不斷發展的媒介上,不存在 100% 安全的單一解決方案。使用最新的 XSS 測試向量徹底測試您的驗證代碼。使用以下來源的測試數據應該可以揭示您的代碼是否仍然容易受到 XSS 攻擊。
總結
希望本文對您很好地解釋了跨站腳本攻擊是什麼以及如何防止它們發生在您的代碼中。永遠不要信任來自用戶或任何其他第三方來源的數據。您可以通過在一個定義良好的上下文中驗證傳入的值、清理數據以保護您的代碼以及轉義輸出以保護您的用戶來保護自己。編寫代碼後,請確保您的工作正常,方法是盡可能徹底地測試代碼。
(圖片來自 Inge Schepers / Shutterstock)
如果喜歡這篇文章,您會喜歡 Learnable;從大師那裡學習新技能和技巧的地方。會員可以立即訪問所有 SitePoint 的電子書和交互式在線課程,例如 Jump Start PHP。
本文的評論已關閉。對 PHP 有疑問?為什麼不在我們的論壇上提問呢?
關於 PHP 安全性和跨站腳本攻擊 (XSS) 的常見問題 (FAQ)
跨站腳本 (XSS) 攻擊會對 PHP 應用程序產生重大影響。它們可能導致數據盜竊、會話劫持、網站損毀,甚至將惡意代碼分發給用戶。 XSS 攻擊利用 Web 應用程序中的漏洞來注入惡意腳本,然後由用戶的瀏覽器執行。這可能會危及用戶與應用程序的交互,並可能洩露敏感信息。
識別 PHP 應用程序中潛在的 XSS 漏洞需要結合手動代碼審查和自動化測試。查找代碼中用戶輸入直接包含在輸出中而沒有適當清理或驗證的區域。像 XSS 掃描器這樣的自動化工具還可以通過測試各種 XSS 攻擊向量來幫助識別潛在的漏洞。
XSS 攻擊通常涉及將惡意腳本注入其他用戶查看的網頁。這可以通過多種方法完成,例如將腳本嵌入 URL 參數、表單輸入甚至 cookie 中。然後,惡意腳本可以代表用戶執行操作,例如竊取其會話 cookie 或操作網頁內容。
防止 PHP 應用程序中的 XSS 攻擊涉及驗證和清理用戶輸入、編碼輸出以及使用適當的 HTTP 標頭。始終將用戶輸入視為不受信任,並根據可接受值的允許列表對其進行驗證。清理輸入以刪除任何可能存在危害的字符或代碼。編碼輸出以確保任何可能存在危害的字符都變得無害。使用 HTTP 標頭(如內容安全策略)來限制腳本和其他資源的來源。
內容安全策略 (CSP) HTTP 標頭在防止 XSS 攻擊中起著至關重要的作用。它允許您指定瀏覽器應認為是可執行腳本有效來源的域。這意味著,即使攻擊者可以將腳本注入您的網頁,瀏覽器也不會運行它,除非腳本的來源在您的 CSP 中列入白名單。
存儲型 XSS 攻擊涉及注入永久存儲在目標服務器上的惡意腳本。然後,當用戶查看某些頁面時,腳本就會提供給用戶。另一方面,反射型 XSS 攻擊涉及通過 URL 或表單輸入註入腳本,然後服務器立即在響應中返回該腳本並由用戶的瀏覽器執行。
PHP 提供了一些內置函數,可以幫助防止 XSS 攻擊。例如,htmlspecialchars()
函數可用於編碼用戶輸入中的特殊字符,從而使潛在的腳本無害。 filter_input()
函數可用於清理用戶輸入,刪除或編碼有害字符。
HTTPOnly Cookie 是一種無法通過客戶端腳本訪問的 Cookie。這意味著,即使攻擊者可以將腳本注入您的網頁,他們也無法使用該腳本讀取或修改 HTTPOnly Cookie。這可以幫助保護敏感信息(例如會話標識符)不被 XSS 攻擊竊取。
是的,XSS 攻擊可能會用來繞過跨站點請求偽造 (CSRF) 保護。如果攻擊者可以將腳本注入您的網頁,他們可以使用該腳本代表用戶執行操作,從而可能繞過您已實施的任何 CSRF 保護。這就是為什麼保護免受 XSS 和 CSRF 攻擊都很重要的原因。
是的,許多 PHP 框架都提供針對 XSS 攻擊的內置保護。例如,Laravel 會自動編碼輸出以防止 XSS 攻擊。其他框架(如 Symfony 和 CodeIgniter)也提供用於清理用戶輸入和編碼輸出的功能。但是,必須記住,沒有哪個框架可以提供完全的保護,您仍然應該遵循防止 XSS 攻擊的最佳實踐。
以上是跨站點腳本攻擊(XSS)的詳細內容。更多資訊請關注PHP中文網其他相關文章!