2010-01-07 127 views
13

用戶是否可以僞造在PHP中從$_SERVER['REMOTE_ADDR']返回的結果,以便他們理論上可以在數據庫上使用SQL注入?IP地址SQL注入

這有點愚蠢,但我對PHP仍然是新的,我想知道它是否可以完成,當SELECT語句從$_SERVER['REMOTE_ADDR']返回的IP地址中選擇時是否需要清理數據庫輸入。所以,如果我想使用像$query = "SELECT * FROM users WHERE IP='" . $_SERVER['REMOTE_ADDR'] . "'";這樣的東西,我會這樣做嗎?

再次,可能是一個「nooby」的問題,但我覺得它必須被問到。

感謝

回答

16

這是一個延伸,並且不太可能的,但我不會走得太遠,因爲說這是不可能的。所以......

反正使用參數化查詢。

即使您永遠不會通過IP地址字段受到攻擊,您仍然可以通過緩存獲得更快查詢的額外好處。

+0

什麼是參數化查詢?你能給個例子嗎? – Cyclone 2010-01-07 20:23:16

+3

我看了他們。謝謝! – Cyclone 2010-01-08 01:35:11

+2

你「不會遠去說」=你不知道答案。安德魯麥格雷戈(下圖)似乎知道他在說什麼。 – 2013-11-10 18:02:53

5

務必消毒所有外部輸入 - 使用mysql_real_escape_string,或者更好的是,prepared statements

2

您可以使用PHP的數據過濾函數。

filter_var()與FILTER_VALIDATE_IP將驗證遠程IP。如果遠程IP有效,請在SQL中使用它。

編輯:filter_input()與INPUT_SERVER是另一種選擇;)

http://www.php.net/manual/en/book.filter.php

http://www.php.net/manual/en/filter.filters.validate.php

http://www.php.net/manual/en/function.filter-var.php

http://www.php.net/manual/en/function.filter-input.php

希望這有助於

Simeon

+0

我們在談論什麼樣的表現衝擊?這個過濾器是否真的會去互聯網檢查IP? – 2013-11-10 17:59:52

1

我總是把這個代碼放在我的所有項目中(一些初始輸入消毒),以防止僞造的IP發生一些令人討厭的事情。 我不確定他們是否可以僞造REMOTE_ADDR。

function validate_ip($ip) { 
    // Try IPv4 First, as its the most used method right now 
    if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4)) { 
     // Oops... try v6 
     if(!filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_IPV6)) { 
      return false; // Sorry... 
     } 
     else { 
      return true; 
     } 
    } 
    else { 
     return true; 
    } 
} 
if(!isset($_SERVER['REMOTE_ADDR'])) # wtf? 
    die("Could not find your IP Address..."); 
else { 
    if(validate_ip($_SERVER["REMOTE_ADDR"])) 
     die("Could not validate your IP Address..."); 
} 
+3

'#wtf?'讓我大笑 – Cyclone 2010-01-07 04:21:01

+0

哈哈沒錯,我忘記了我添加的評論。深夜「編碼」(編寫小而簡單的代碼只是爲了保持清醒)迫使我寫出糟糕的評論。 – 2010-01-07 04:23:35

6

我覺得有人僞造$_SERVER['REMOTE_ADDR']將構建一個IP數據包用假IP地址,在這種情況下的反應將被路由(因爲它是由服務器,而不是客戶端設置)的唯一途徑回到僞造的地址。如果您擔心注入攻擊,我認爲您沒有問題,因爲IP數據包中的地址字段只有地址空間。

+0

我同意(實際上我正在寫這篇文章)。然而,從理論上來說,嘗試注入攻擊可以使其他一些入口方式(像你所說的那樣一味地進行)是理所當然的,但這種可能性不大。 – Eduardo 2010-01-07 04:18:49

1

REMOTE_ADDR不是由客戶端發送的,它是由服務器設置的。雖然在技術上可能在網絡級別欺騙IP地址,但攻擊者必須盲目工作。最棘手的部分是猜測sequence number。 (在Coldfusion下,順便提一下,它是another story。)

正如其他人所說的那樣,使用預準備語句,您不必擔心SQL注入(儘管可能會發生其他類型的注入攻擊)。

+1

有趣的是,我並不認爲它甚至是真的可能 – Cyclone 2010-01-07 04:21:55

+0

請注意,IP地址欺騙不能用作SQL注入的向量,它只是意味着您無法知道某些REMOTE_ADDR是計算機的地址發送了請求。另外,猜測序號並不容易。在OpenBSD上,它以隨機數開頭,這基本上是不可能的。 – outis 2010-01-07 06:58:20

1

爲了提高效率和安全性,您可能希望在數據庫中存儲和使用IP作爲整數。

直接存儲IP地址的方法是在數據庫中使用varchar字段。但是,另一種表示IP的方式是整數。以這種方式轉換提供的IP將消毒它,並且使您的存儲和查詢更高效。存儲一個INT在DB中佔用更少的空間,並且對索引更好,我相信查詢緩存。

檢出ip2longlong2ip爲PHP函數進行轉換,而inet_aton和inet_ntoa在MySQL中執行。

因此,過程可能會去像

$user_ip=ip2long($_SERVER['REMOTE_ADDR']); 
if(!$user_ip){ //returned false due to odd input 
    echo 'wtf, yo'; 
    } 
else{ 
    //do your query 
    } 

您還可以消毒的IP,並通過結合兩個

$user_ip=long2ip(ip2long($_SERVER['REMOTE_ADDR'])); 
+0

您可能希望使編碼風格更好。 $ _SERVER [REMOTE_ADDR]很糟糕。 – 2010-01-07 04:53:14

+0

謝謝,由於某種原因,我認爲這些是沒有引號常量或什麼的。是的,我應該包括引號,所以我已經更新了我的答案。但我並不認爲這是編碼風格的問題。 – JAL 2010-01-07 05:07:52

9

你不能依靠保持在原來的點分四組形式REMOTE_ADDR是真的......由於匿名代理或一些這樣的技巧,它可能是錯誤的地址。你可以通過依賴它始終是一個IP地址,所以這條路徑的SQL注入是不可能的。

從堆棧底部開始,它已經從創建TCP連接的數據包的源地址轉換到服務器。這意味着a)它必須是一個IP地址,並且b)它必須路由回客戶端以便根本發生連接。

+1

IMO這是真正的答案。如果我爲每個參數化查詢佈道,LOL都有一分錢。 – 2013-11-10 17:54:45