2011-10-22 115 views
1

我意識到這裏面有很多問題。但我的方法與他們的方法不一樣,所以我想知道。我認爲我理解SQL,但我不想冒未來的風險,所以謝謝你的幫助。 (這只是我正在做的一個項目,而不是作業或任何重要的東西)。這是否容易受到SQL注入的影響

function checkLogin($username, $password) { 
    $username = strtolower($username); 
    connectToDatabase(); 
    $result = mysql_query("SELECT * FROM `users` WHERE username='$username'"); 
    $dbpassword = ""; 
while($row = mysql_fetch_array($result)) 
    { 
    $rowuser = $row['username']; 
    if($username != $row['username']) continue; 
    $dbpassword = $row['password']; 
    } 
    if($dbpassword == "") { 
     return false; 
    } 
    $genpass = generatePassword($password); 
    return $genpass == $dbpassword; 
} 

所以打我與你最好的拍攝:) 而且我不認爲我的方法同樣有效,因爲它可以。我不明白php足夠了解$row = mysql_fetch_array($result)不幸的是在做什麼。

+0

SQL注入是在爲你的函數提供$ username或$ password的奇怪值時發生的。如果這些值來自外部提供的來源,則會遇到麻煩。 –

+0

@Ira Baxter,它來自POST,所以我猜這意味着我有麻煩了? – Austin

+1

考慮到有人可能會輸入用於用戶名的文本「'或'A = A」。那麼你的循環會嘗試所有用戶的密碼,我想。這將使猜測密碼變得更容易。如果您的SQL允許在查詢調用中使用多個語句,那麼用戶名文本可能是「'; DELETE * FROM'users'會刪除您的用戶表,或者是UPDATE語句將某些用戶的密碼設置爲特定的密碼用這個密碼登錄很簡單,你需要檢查的是檢查用戶名字符串是否不包含引號 –

回答

6

因爲你正在服用的任意字符串,並直接將其放入一個SQL語句,你很容易受到SQL注入。

EDITED基於下面的註釋。)

SQL注入的典型例子是使一個用戶名如以下:

Robert'); DROP TABLE users;-- 

Obligatory XKCD link

說明:

鑑於上面的「用戶名」,插入到您的字符串中導致:

SELECT * FROM `users` WHERE username='Robert'); DROP TABLE users;--' 

末註釋符號--需要結束引號的「擺脫」,因爲我只是取代我的一個來結束你的SELECT語句,這樣我可以注入DROP TABLE語句。

正如@sarnold指出,PHP的mysql_query僅執行串中的第一個查詢,因此,上述實施例(被稱爲query stacking)不適用。功能解釋如下:http://php.net/manual/en/function.mysql-query.php

一個更好的例子可以發現here。在這裏,他們使用的

' OR 1 OR username = ' 

用戶名了插值成爲

SELECT * FROM `users` WHERE username='' OR 1 OR username = '' 

和這將導致你的應用程序來獲取所有用戶。

+0

我剛試過這個,它沒有丟掉我的表格,爲什麼會這樣? – Austin

+0

+1 for xkcd link! – michael667

+1

這個字符串不是一個很好的例子;默認情況下,'mysql_query' [只執行在字符串中的第一個查詢](http://www.ph p.net/manual/en/function.mysql-query.php#91669)。將它留給PHP來嘗試使用hacky機制來解決安全問題。 *咳嗽*魔術引號*咳嗽* – sarnold

2

我會說是的,它是開放的SQL注入。

這是因爲你正在服用的$用戶名的形式,用戶輸入,並把它變成你的SQL語句沒有確保它是乾淨的。

這是我喜歡在我的應用程序中使用的清潔字符串爲目的的功能:

function escape($data) { 
    $magicQuotes = get_magic_quotes_gpc(); 

    if(function_exists('mysql_real_escape_string')) { 
     if($magicQuotes) { 
      $data = stripslashes($data); 
     } 

     $data = mysql_real_escape_string($data); 
    } 
    else { 
     if(!$magicQuotes) { 
      $data = addslashes($data); 
     } 
    } 

    return $data; 
} 

然後你可以使用它像這樣:

$username = escape(strtolower($username)); 
connectToDatabase(); 
$result = mysql_query("SELECT * FROM `users` WHERE username='$username'"); 
4

簡短的回答是肯定的。

一個也許更有幫助的答案是,你永遠不應該信任用戶的輸入;準備好的陳述是防止這種情況的最簡單方法,如果您有PDO可用的話。見PDO Prepared Statements

<?php 
$stmt = $dbh->prepare("SELECT * FROM `users` WHERE username=?"); 
if ($stmt->execute($username)) { 
    while ($row = $stmt->fetch()) { 
    print_r($row); 
    } 
} 
?> 
4

其他的答案是你的問題的一個很好的說明,但是,我覺得他們都忽略了最好的解決辦法:使用PHP的PDO Prepared Statements爲您查詢。

$stmt = $dbh->prepare("SELECT * FROM users where username = ?"); 
if ($stmt->execute(array($username))) { 
    while ($row = $stmt->fetch()) { 
    print_r($row); 
    } 
} 

這是一個小而簡單的例子。有更復雜的使用PDO的方法可能更適合您的應用程序。

當您使用PDO準備你永遠需要手動逃避什麼,只要您使用此稍有不同的風格,你將永遠不會寫一個SQL注入漏洞語句你不必保持每底層兩個變量「數據」 - 一個用戶提供的數據 - 因爲只有一個是必需的。

相關問題