以下查詢返回表tbl_user中的所有密碼,但我無法理解爲什麼會發生這種情況。'admin'的含義是什麼OR 1 = 1 - '
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
請幫助我理解查詢的這個部分: '管理員' OR 1 = 1 - '
你能介紹其他威脅這樣的(網站,書籍等)?
以下查詢返回表tbl_user中的所有密碼,但我無法理解爲什麼會發生這種情況。'admin'的含義是什麼OR 1 = 1 - '
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
請幫助我理解查詢的這個部分: '管理員' OR 1 = 1 - '
你能介紹其他威脅這樣的(網站,書籍等)?
這是一個經典的SQL注入。 SQLfiddle
在這個例子中,有5個用戶被添加到表:
聽我的解釋是看到這個小提琴。然後您的查詢運行。預期結果將僅返回admin
用戶的密碼值。
但是,通過添加1=1
(這是一個真實的語句),將返回所有密碼。
幫助可視化的另一種方法是添加括號,以便您可以看到如何評估所有內容。
SELECT pass FROM users WHERE (user_name = 'admin') OR (1=1) -- '
^Pulls only the admin user ^Pulls everything because 1=1
所以,我們選擇在這裏用戶名是admin
表中的密碼。我們也從1 = 1的表格中提取密碼 - 這總是正確的。每行評估爲true,因此所有密碼都會返回。
最後的-- '
用於註釋掉其餘的查詢。
SELECT pass from users WHERE user_name = 'admin' or (1=1) -- 'and permission='superadmin'
通常情況下,(如果1=1
沒有被注入),你會拉密碼與管理員和超級管理員權限USER_NAME用戶。你現在已經發表了評論,並沒有被執行。這就是整個密碼錶可以被返回的方式。
非常好,不僅邏輯部分 - 我認爲我做得很好 - 但是這種利用如何改變查詢的意圖以及如何擴展。 – VMai
我認爲你正在尋找「和」而不是「或」
「OR」表示的條件之一(其中name =「管理員」 OR 1 = 1)必須是真實的,並在此情況下,它返回具有名稱等於「管理員」的一切,或具有1等於1
嘗試使用此來代替:
SELECT password FROM tbl_users WHERE name = 'admin' AND 1=1
的邏輯OR
的結果如下:
a | b | a OR b
-----------------------
false | false | false
false | true | true
true | false | true
true | true | true
如果其中一個操作數爲真,則OR b的結果爲真。
1 = 1 evaluates to true
=>
(any expression) OR 1 = 1 evaluates to true
=>
name = 'admin' OR 1 = 1
計算結果爲真爲你的表的每一行
結果:
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1 -- '
將返回密碼,所有用戶,不僅是管理,因爲PeeHaa
作爲陳述--
是開始SQL註釋的。
有兩種可能的混淆,我可以想象你在這裏遇到。第一個是,正如其他人所提到的,只要或者expr1
或expr2
爲真,則返回true。由於1=1
始終爲真,因此您的WHERE
語句對於表中的每個記錄均爲真。
您可能會困惑的第二件事是查詢中的最後一個-- '
。 --
是PHP中的//
的SQL等效項;它表示該行的其餘部分是註釋,應該忽略。所以SQL解釋器只讀SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1
而忽略了其餘部分,這就是爲什麼尾部單引號不會導致語法錯誤的原因。
這裏唯一的安全風險是如果您將未轉義的用戶輸入傳遞給SQL。在SQL查詢中使用它之前,請始終使用mysqli_real_escape_string或等效函數轉義任何用戶輸入。
編輯:正如在註釋中指出的,參數化查詢通常比手動轉義每個輸入元素更好。 PHP的PDO擴展是以這種方式開始的好地方。
IMO,最好使用參數化而不是轉義和串聯 - 後者應該只用於不能被參數化的東西,比如列名。 – halfer
@halfer我同意,參數化優於轉義+串聯作爲編碼實踐,因爲錯誤更難。我將編輯它的參考到答案中。 –
最後部分-- '
是註釋,所以MySQL不關心。所以我們沒有留下
SELECT password FROM tbl_users WHERE name = 'admin' OR 1=1
在此查詢1=1
是真實的,因爲1是同樣是1這可能是這裏當然另一個真實的表達,例如2=2
或'a'='a'
- 結果將是始終不變的。
所以您的查詢看起來是這樣的:
SELECT password FROM tbl_users WHERE name = 'admin' OR true
操作OR
以這種方式工作,如果有任何的條件是事實,就意味着整個表達式爲true。在表達name = 'admin' OR true
一個表達式爲true(真實不虛),所以這整個表達式是true
所以查詢現在可能是
SELECT password FROM tbl_users WHERE true
現在,如果我們看看那裏的一部分,我們有WHERE true
。這意味着事實上沒有條件,所以我們可以改變查詢到:正如你在表格中看到您的查詢簡單的獲得列password
每個記錄
SELECT password FROM tbl_users
所以(可能爲所有用戶)
也就是說一個經典的SQL注入。它返回名稱爲'admin' * OR *的用戶,其中1 = 1(因爲1確實每個記錄匹配1)。'--'只是在將它看作是註釋之後才確認eveyrthing – PeeHaa
您可以刪除1 = 1,因爲它什麼也不做。 – Gadgetster
@Gadgetster你是什麼意思? – PeeHaa