SQL注入

2022-03-05 23:19:56 字數 3031 閱讀 2721

1、 sql注入攻擊的本質:讓客戶端傳遞過去的字串變成sql語句,而且能夠被執行。

2、 每個程式設計師都必須肩負起防止sql注入攻擊的責任。

說起防止sql注入攻擊,感覺很鬱悶,這麼多年了大家一直在討論,也一直在爭論,可是到了現在似乎還是沒有定論。當不知道注入原理的時候會覺得很神奇,怎麼就被注入了呢?會覺得很難預防。但是當知道了注入原理之後預防不就是很簡單的事情了嗎?

第一次聽說sql注入攻擊的時候還是在2023年(好像得知的比較晚),那是還是在寫asp呢。在一次寫**的時候,有同事問我,你的這段**防注入攻擊了嗎?什麼攻擊?這是什麼呀。

後來到網上各種找,終於弄明白了是怎麼攻擊進來的了。注入攻擊都是來自於客戶端,無論是表單提交、url傳值還是cookie等,其實原理都是一樣的。到了伺服器端可以分成三種情況:數字、日期時間、字串。

一、數字。

如何注入?

假設我們要實現乙個顯示新聞的頁面,我們可能會隨手寫下下面的**:

string

id =

request.querystring["id

"];string

sql ="

select * from news where colid="+

id;如果傳遞過來的 id是我們想像的 數字(比如168),那麼自然不會有什麼問題。但是如果傳遞過來的id是「168 delete from table 」的話,那麼sql的值就變成了「select * from table where colid=168 delete from news」。對於sql server來說是支援一次提交多條sql語句的,這個為我們提供了方便之餘也為sql注入敞開了大門。顯然如果這條sql語句被執行的話,那麼news表裡的記錄就都沒有了。

那麼如何預防呢?很簡單,因為colid欄位的型別是int的,那麼我們只需要驗證一下傳遞過來的id是不是整數就可以了。是整數就不存在注入;如果不是那麼就有可能存在注入。即使不存在注入,把乙個不是整數的id拼接進去也會造成執行錯誤。

所以說不管是不是為了預防sql注入,也都應該驗證id是不是整數。  

驗證方法嘛,可以用tryparse,可以用正則,也可以自己寫函式驗證。但是不建議用try異常的方式,因為這個有效率問題。

這裡還有乙個特殊情況,就是對於批量刪除這類的會傳遞過來多個數字,比如「1,2,3,10」,這個也需要驗證一下,萬一有人利用這個漏洞呢。至於驗證方法也很簡單,自己寫個函式就ok了。

二、日期時間

這個和數字的情況是一樣的,驗證是不是日期時間即可。

三、字串

最麻煩、爭議最大的就是這個了。

先看一下如何注入

比如我們先要按照新聞標題來進行查詢,可能寫的**:

string

key 

=txttitle.text;

string

sql ="

select * from news where title like '%"+

key +"

%'";那麼用了單引號又是如何注入的呢?假設key=" ' delete from news --" ,那麼sql的值就是「 select * from news where title like '%'

delete from news -- ' 」。

先用乙個單引號和前面的單引號組成一對封閉的單引號,這一對單引號內部('%')就作為字串處理,而外面的就被作為sql語句處理,而第二個單引號被 「--」給注釋掉了,這樣就保證了整個sql語句的正確性。

這是注入的一種方法。

那麼如何來防止呢?想想剛才的問題,如果沒有單引號是不是就天下太平了呢?對於這種情況(前面的「數字」的情況不算),到目前為止我是沒發現不用單引號,還能夠注入進來的方法。也許是我孤陋寡聞吧,不知道各位高手是否知道對於這種情況,不用單引號還能注入進來的方法。

既然找到了罪魁禍首,那麼就好辦了,把單引號乾掉就ok了。key = key.replace("'", "''");這時候sql的值就是」 select * from news where title like '%'' delete from news --'」。

對於sql 來說在一對單引號內部的兩個單引號表示乙個字串形式的單引號。這樣我們就把罪魁禍首改造成了字串了。在一對單引號內的「--」也是普通的字串而不代表注釋。

罪魁禍首是單引號,想不明白為什麼有許多人都去過濾 「delete、update」這一類的關鍵字,他們都是安善良民呀,他們是很冤枉的。當然了,如果前提是程式都已經寫好了,不能修改內部**,那就另當別論了。至於「--」頂多算是**,如果您不放心的話,把他處理了也行。

總結:數字、日期時間的,驗證型別字串的,處理好單引號。

另外為了安全起見,不要用sa連線資料庫xp_cmdshell這一類的有危險的擴充套件儲存過程也應該處理一下(比如刪除)。

ps:新增修改資料的時候可以用引數化的sql語句,但是目的不是防止注入,而是重用執行計畫。

還有就是js指令碼的問題,這個還沒有仔細考慮,可以用html編碼的方式,也可以用替換的方式,還有ubb的漏洞等。

小小總結:

1 檢查,型別檢查,如果是int一定要tryparse,如果是有限的幾個值,一定要列舉匹配。如果是日期一定要轉成日期轉入資料層。

2 長度,長度是個非常重要的因素,比如登入,如果使用者名稱是嚴格限死的10個字元以內就10個字元以內,使用者名稱中間沒有空格就檢查不能有空格,但是這個長度因素是需要嚴格控制的,不能把長度放開到10個字元以上,因為 "truncate table s"和這個"drop table s",長度需要跟具體需求具體確定,不能全部一刀切。如果有哪位可以在10個字元以內注入成功的,還請告之,我趕緊改我的程式了,呵呵。

3 過濾檢查,如果壓根不可能出現xp_的地方一定要過濾,至於其他的, delete,drop,很多地方都不能確保

如果前兩個檢查不能排除危險的話到第三步過濾建議還是都是用儲存過程引數化(或語句引數化),因為到第三步的時候已經不能確保100%防止注入了。

SQL注入(三) sql注入 bugku

原理 mysql 在使用 gbk 編碼的時候,會認為兩個字元為乙個漢字,例如 aa 5c 就是乙個 漢字 前乙個 ascii碼大於 128 才能到漢字的範圍 我們在過濾 的時候,往往利用的思 路是將 轉換為 換的函式或者思路會在每一關遇到的時候介紹 因此我們在此想辦法將 前面新增的 除掉,一般有兩種...

SQL注入 報錯注入

乙個帶get引數的 並且不從資料庫返回資料,但存在報錯資訊 檢視字段情況 報錯注入語句格式 and 1 2 union select1,2,3 from select count concat floor rand 0 2 sql語句 a from information schema.tables...

SQL注入 報錯注入

sql注入基礎 盲注 用於注入結果無回顯但錯誤資訊有輸出的情況 floor函式 返回小於等於某值的整數,例如floor 1 則返回1,floor 1.9 也返回1 rand函式 生成隨機數.可指定seed,指定後每次生成的數都一樣即偽隨機,不指定seed則每次生成的隨機數都不一樣.通過floor和r...