關於使用佔位符來解決SQL注入

2021-07-04 22:39:23 字數 1646 閱讀 7195

總結:

sql已經預編譯好了,然後替換中間的佔位符,這個佔位符在編譯後就已經確定了它只是乙個引數屬性。因此,用注入的**去替換佔位符,這個sql也不會再進行編譯了,所以也達不到注入的目的。

sql注入並不是乙個在sql內不可解決的問題,這種攻擊方式的存在也不能完全歸咎於sql這種語言,因為注入的問題而放棄sql這種方式也是因噎廢食。首先先說乙個我在其他回答中也曾提到過的觀點:

沒有(執行時)編譯,就沒有注入

sql注入產生的原因,和棧溢位、xss等很多其他的攻擊方法類似,就是

未經檢查或者未經充分檢查

的使用者輸入資料

,意外變成了**被執行

。針對於sql注入,則是使用者提交的資料,被資料庫系統編譯而產生了開發者預期之外的動作。也就是,sql注入是使用者輸入的

資料,在拼接sql語句的過程中,超越了資料本身,成為了sql語句查詢邏輯的一部分,然後這樣被拼接出來的sql語句被資料庫執行,產生了開發者預期之外的動作。

所以從根本上防止上述型別攻擊的手段,還是避免資料變成**被執行,時刻分清**和資料的界限。而具體到sql注入來說,被執行的惡意**是通過資料庫的sql解釋引擎編譯得到的,所以只要避免使用者輸入的資料被資料庫系統編譯就可以了。

現在的資料庫系統都提供sql語句的預編譯(prepare)和查詢引數繫結功能,在sql語句中放置佔位符'?',然後將帶有佔位符的sql語句傳給資料庫編譯,執行的時候才將使用者輸入的資料作為執行的引數傳給使用者。這樣的操作不僅使得sql語句在書寫的時候不再需要拼接,看起來也更直接,而且使用者輸入的資料也沒有機會被送到資料庫的sql直譯器被編譯執行,也不會越權變成**。

至於為什麼這種引數化的查詢方式沒有作為預設的使用方式,我想除了相容老系統以外,直接使用sql確實方便並且也有確定的使用場合。

多說一點,從**的角度來看,拼接sql語句的做法也是不恰當的。

delete

from

planet

where

name

='mercury'

;delete

from

planet

where

name

='venus'

;delete

from

planet

where

name

='earth'

;delete

from

planet

where

name

='mars'

;

我修改一下那個很經典的笑話:程式設計師不應該執行

刪除地球

這樣的sql語句,而是寫

刪除乙個行星

,然後將地球當作引數傳入。

$stmt = $mysqli->prepare("delete from planet where name = ?");

$stmt->bind_param('s', "earth");

$stmt->execute();

mysql :: mysql 5.1 reference manual :: 13.5 sql syntax for prepared statements

prepared statement

mysql 如何使用佔位符 sql佔位符怎麼用

繫結變數是oracle解決硬解析的首要利器,能解決oltp系統中library cache的過度耗用以提高效能 繫結變數是oracle解決硬解析的首要利器,能解決oltp系統中library cache的過度耗用以提高效能。然刀子磨的太快,使起來鋒利,卻容易折斷。凡事皆有利弊二性,因地制宜,因時制宜...

佔位符是如何防止sql注入的

因為prepare是把sql模板發給mysql編譯,然後execute是把使用者輸入的引數交給mysql套模板執行.php模擬預處理的意思就是資料庫並不會有編譯模板這一步,而是php自動轉義使用者輸入的引數,相當於手動呼叫mysqli real escape string get id 或 pdo ...

sql 為什麼佔位符可以防止sql注入

為什麼佔位可以防止sql注入,不從什麼預編譯的角度來將,直接上原始碼,下面是mysql jar包中的setstring方法。以select from user where id 語句為例,傳入1 or 1 1 如果是最後sql為select from user where id 1 or 1 1,那...