2010-05-07 123 views
-6

我一直被MySQL注入困擾了很長時間,並且正在想辦法一起消除這個問題。我想出了以下希望很多人會覺得這個有用。MySQL注入解決方案

唯一我可以想到的是這個部分搜索: Jo =>通過使用類似%%語句返回「John」。

這裏是一個PHP的解決方案:

<?php 
function safeQ(){ 
    $search= array('delete','select');//and every keyword... 
    $replace= array(base64_encode('delete'),base64_encode('select')); 
    foreach($_REQUEST as $k=>$v){ 
     str_replace($search, $replace, $v); 
    } 
} 
safeQ(); 

function html($str){ 
    $search= array(base64_encode('delete'),base64_encode('select')); 
    $replace= array('delete','select');//and every keyword... 
    str_replace($search, $replace, $str); 
} 

//example 1 
... 
... 
$result = mysql_fetch_array($query); 
echo html($result[0]['field_name']); 

//example 2 
$select = 'SELECT * FROM $_GET['query'] '; 

//example 3 
$insert = 'INSERT INTO .... value($_GET['query'])'; 


?> 

我知道,我知道,你仍然可以使用1=1或任何其他類型的注射...... 注入但這我覺得可以解決你的問題的一半,從而正確的mysql查詢被執行。

所以我的問題是,如果任何人都可以找到任何退後,請隨時在這裏評論。

請給一個答案只,如果你認爲這是一個非常有用的解決方案並沒有大的缺點被找到,或者你認爲這是一個壞主意都在一起......

+0

爲什麼這麼笨? – Val 2010-05-07 09:54:03

+0

你想達到什麼目的? – newtover 2010-05-07 09:55:35

+0

基本上對所有的mysql關鍵字進行編碼,所以當有人試圖注入像$ v =「1; DROP tbl;」這樣的語句時'$ s ='選擇*從tbl WHERE ID ='。$ v; '但是如果你編碼了所有的關鍵字,那麼將會觸發一個mysql錯誤,然後你的表是安全的。 – Val 2010-05-07 10:02:39

回答

6

重新發明車輪並將其改造成錯誤的方式(TM)。

  • 首先,有參數化查詢(可用於擴展MySQLi的PHP);如果這不是一個選項,那麼mysql_real_escape_string。這是主要問題 - 在決定自行實施之前,請檢查已有的選項。第二,你試圖在SQL中調用PHP函數,你想要的可能是類似於'SELECT * FROM ' . safeQ($_GET['query'])
  • 第三,你打破了所有索引和搜索包含你的「惡言」的數據,向性能問題問好和瘋狂的解決方法。

編輯:爲了解決你的意見作爲例子來說明:

$v="1; DROP tbl;\";DROP tbl" // oh look, an SQL injection attempt! 
$s = 'SELECT * FROM tbl WHERE ID='.$v; // SQL injection, no doubt 

// if ID is an integer field, make it an integer. Simple, secure, and fast. 
$s = 'SELECT * FROM tbl WHERE ID='.(int)$v; 
// $s == 'SELECT * FROM tbl WHERE ID=1' // see PHP manual for explanation of type casting 

// if ID is a string field, escape it. Simple, secure, and still plenty fast. 
$s = 'SELECT * FROM tbl WHERE ID="'.mysql_real_escape_string($v) . '"'; 
// $s == 'SELECT * FROM tbl WHERE ID="1; DROP tbl;\";DROP tbl"'; 
// See? No injection, as the quote is *escaped* 
+0

順便說一句,有一種情況,其中mysql_real_escape_string()已通過(不知道如何,但通過使用類似x0XXX的東西),它給你一個雙重轉義'「DROPtbl; \\」; DROP tbl「' – Val 2010-05-07 10:31:35

+0

@Val no,mysql_real_escape_string ()不能繞過:)你只是搞糊塗了,你最好開始學習,而不是抱怨和抱怨,沒有什麼個人的,只是友好的建議 – 2010-05-07 10:36:34

+0

@Val:我曾說過「這是一個錯誤的方式來解決這個問題」 至於旁路,你想到的函數是'addslashes()';'mysql_real_escape_string()'是爲了對付你提到的Unicode黑客攻擊,並且不容易受到它 – Piskvor 2010-05-07 10:39:39

11

這已經被正確PHP實現:

但是,您應該先閱讀PHP manual entry on SQL injection


爲了回答您的實際問題,你的方法的主要缺點是:

  1. 它不工作
  2. 只要是明確的,它不工作,並會離開你全面開放SQL注入。
  3. 它還可以防止您輸入任何與MySQL關鍵字衝突的數據。

如果你打算重新發明車輪,我會建議看看現有的車輪。

+0

mysql_real_escape_string只有廣告斜槓「\」來轉義關鍵字符。它不編碼關鍵字。 關於我上面的代碼的好處是,你仍然可以搜索關鍵詞。 – Val 2010-05-07 10:04:47

+0

您的代碼不會阻止SQL注入。它只是不起作用。我甚至不明白你想描述什麼優勢? – 2010-05-07 10:08:51

+3

它不會停止子彈,但我的防彈背心的好處是取色的範圍... – 2010-05-07 10:10:23

1

看,你從錯誤的角度思考它。
雖然很多人都這樣做。 根據SQL注入有2個強烈的疑慮:

  1. 有一些特殊攻擊,稱爲「SQL注入」。
  2. 爲了防止它,輸入數據必須以某種特殊的方式威脅。

兩者都是錯誤的。

當您遵循SQL語法時,沒有「SQL注入」這樣的事情。

去圖。

如果您遵循SQL語法規則(無論如何您都必須遵守它),您是安全的,就像一個副作用一樣。

放入SQL查詢的任何字符串數據都必須使用2條規則處理:
1.必須轉義字符串中的所有特殊字符。
2.字符串必須用引號引起來。

非文本數據也存在問題。沒有什麼大不了的。
但是,如果你覺得它太複雜了,你可以隨時準備好準備好的陳述 - 它總是安全的,不會有任何想法。

儘管查詢的非數據部分仍然存在問題。這確實是最危險的部分。唯一的問題有權被稱爲「SQL注入」。
爲了避免它,查詢中的所有動態非數據部分必須在您的腳本中進行硬編碼。這是唯一可能的方法。

2

這是一個壞主意。

在每種語言,平臺,運行時,引擎,庫,whateveryoumight都有SQL注入已經有一個適當的,正確的和工作的解決方案。

它被稱爲參數。

不是將值作爲文字常量放入SQL中,而是添加一個參數佔位符,然後在查詢旁邊提供參數值,而不是使用任何格式化技巧將其返回到SQL中。

每個其他解決方案試圖通過查看SQL或其中的某些部分來「解決」問題並試圖確定它是否正確的問題是次級問題,並且其中大多數解決方案還存在其他缺陷和問題看,不知道,並不真正想擁有。

因此,不要在荊棘叢中跳動,並以正確的方式開始。切換到使用參數。

在PHP中,交談到MySQL,有很多種方法,但是使用的mysqli庫:

$stmt = $db->prepare('SELECT * FROM products WHERE id = ?'); 
$stmt->bind_param('i', $id); 
$stmt->execute(); 
.. bind for results 
$stmt->fetch(); 

如果$ id變量這裏包含了不安全的代碼,就會使SQL執行崩潰,因爲如果ID是一個整數,它不能與除另一個整數以外的其他任何數據進行比較,如果它是一個字符串,它將與您提供的字符串進行比較,而不是嘗試將該字符串作爲SQL的一部分執行。

現在,評論帶出了一個觀點,有時您必須更改SQL,因爲您將提供動態排序(即用戶選擇的排序)或動態篩選(即要應用哪些篩選器由用戶)。

在這種情況下,解決方案很簡單:請勿採取任何用戶提供的文本並將其放入SQL。相反,您需要對常量進行硬編碼以將SQL添加到您的代碼中,並讓用戶選擇指導哪些常量要添加的代碼,順序以及位置。

+0

雖然這個解決方案並不完整,有時候我們必須看看這些作品。在動態排序的情況下,例如 – 2010-05-07 10:39:10

+0

,您仍然不應該將任何用戶提供的文本添加到SQL中。如果您需要進行動態排序,您可以根據用戶的輸入注入代碼中的硬編碼常量,以便在用戶向您提供不良數據以嘗試將其注入到SQL中時,將能夠做的是混淆或破壞爲訂購選擇正確的列名或表達式的代碼。 – 2010-05-07 10:57:20