2.7. HTTP請求欺騙
一個比欺騙表單更進階和複雜的攻擊方式是HTTP請求欺騙。這給了攻擊者完全的控制權與靈活性,它進一步證明了不能盲目信任使用者提交的任何資料。
為了示範這是如何進行的,請看下面位於http://example.org/form.php的表單:
CODE:
<form action="process.php" method="POST">
<p>Please select a color:
<select name="color">
<option value="red">Red</option>
<option value="green">Green</option>
<option value="blue">Blue</option>
</select><br />
<input type="submit" value="Select" /></p>
</form>
如果使用者選擇了Red並點擊了Select按鈕後,瀏覽器會發出下面的HTTP請求:
CODE:
POST /process.php HTTP/1.1
Host: example.org
User-Agent: Mozilla/5.0 (X11; U; Linux i686)
Referer: http://example.org/form.php
Content-Type: application/x-www-form-urlencoded
Content-Length: 9
color=red
.
看到大多數瀏覽器會包含一個來源的URL值,你可能會試圖使用$_SERVER['HTTP_REFERER']變數去防止欺騙。確實,這可以用於對付利用標準瀏覽器發起的攻擊,但攻擊者是不會被這個小麻煩給擋住的。通過編輯HTTP請求的原始資訊,攻擊者可以完全控制HTTP頭部的值,GET和POST的資料,以及所有在HTTP請求的內容。
攻擊者如何更改原始的HTTP請求?過程非常簡單。通過在大多數系統平台上都提供的Telnet公用程式,你就可以通過串連網站伺服器的偵聽連接埠(典型的連接埠為80)來與Web伺服器直接通訊。下面就是使用這個技巧請求http://example.org/頁面的例子:
CODE:
$ telnet example.org 80
Trying 192.0.34.166...
Connected to example.org (192.0.34.166).
Escape character is '^]'.
GET / HTTP/1.1
Host: example.org
HTTP/1.1 200 OK
Date: Sat, 21 May 2005 12:34:56 GMT
Server: Apache/1.3.31 (Unix)
Accept-Ranges: bytes
Content-Length: 410
Connection: close
Content-Type: text/html
<html>
<head>
<title>Example Web Page</title>
</head>
<body>
<p>You have reached this web page by typing "example.com",
"example.net", or "example.org" into your web browser.</p>
<p>These domain names are reserved for use in documentation and are not
available for registration. See
<a href="http://www.rfc-editor.org/rfc/rfc2606.txt">RFC 2606</a>, Section
3.</p>
</body>
</html>
Connection closed by foreign host.
$
上例中所顯示的請求是符合HTTP/1.1規範的最簡單的請求,這是因為Host資訊是頭部資訊中所必須有的。一旦你輸入了表示請求結束的連續兩個分行符號,整個HTML的回應即顯示在螢幕上。
Telnet公用程式不是與Web伺服器直接通訊的唯一方法,但它常常是最方便的。可是如果你用PHP編碼同樣的請求,你可以就可以實現自動操作了。前面的請求可以用下面的PHP代碼實現:
CODE:
<?php
$http_response = '';
$fp = fsockopen('example.org', 80);
fputs($fp, "GET / HTTP/1.1\r\n");
fputs($fp, "Host: example.org\r\n\r\n");
while (!feof($fp))
{
$http_response .= fgets($fp, 128);
}
fclose($fp);
echo nl2br(htmlentities($http_response, ENT_QUOTES, 'UTF-8'));
?>
當然,還有很多方法去達到上面的目的,但其要點是HTTP是一個廣為人知的標準協議,稍有經驗的攻擊者都會對它非常熟悉,並且對常見的安全性漏洞的攻擊方法也很熟悉。
相對於欺騙表單,欺騙HTTP請求的做法並不多,對它不應該關注。我講述這些技巧的原因是為了更好的示範一個攻擊者在向你的應用輸入惡意資訊時是如何地方便。這再次強調了過濾輸入的重要性和HTTP請求提供的任何資訊都是不可信的這個事實。