這裏由於實驗的時候只記錄了一部分因此就展現一部分前端
(1)看到界面發現是查詢id功能,沒有在url裏看到有傳參因此應該是post方法提交數據。mysql
(2)進行sql注入以前咱們最好是先想像一下這個功能提交的參數到了後臺以後後臺是怎樣的操做的,對於當前的頁面我猜想後臺是這樣操做sql
現接受個人id請求而後帶入到查詢語句數據庫
$id=$_POST['id']數組
select 字段1,字段2 from 表名 where id = $id網絡
能夠用下面的語句添加在等號後面來測試是否真確(post請求經過抓包的方式來進行測試)函數
1 or 1=1;工具
能夠看到返回的是200post
而後查看返回的結果能夠看到把全部的結果都查詢出來了。因此有漏洞而且是數字型的測試
查看頁面發現是get請求
(1)首先也是猜測後臺進行的操做,由於是查詢名字,先將咱們查詢的數值賦給一個變量
$uname=$_GET['username']
select 字段1,字段2 from 表名 where username='$uname ' or 1=1#';
or = 1=1#驗證漏洞是否存在,#號註釋閉合‘’
測試結果
(1)搜索型
看到界面是用戶名查找我首先仍是進行猜想後臺的操做,猜想後臺可能使用的是mysql的搜索功能,mysql查詢語句
Select * from member where username like ’$$’;
對於咱們滲透者來時要進行一個閉合構造
Payload:xxxx%' or 1=1 #
測試結果
(2)xx型
查看頁面發現與搜索型相似,可是測試發現拼接閉合的語句不一樣,查看源碼發現是括號閉合,因此能夠獲得payload的類型是多種多樣的。
原理方法與搜索型相似,因此構造payload
xx') or 1=1 #
但實際滲透測試過程當中不可能獲得目標網站的源碼,這時候就須要根據經驗和多測試。好比發現一個輸入框,就首先進行單雙引號測試
aaa」 or 1=1# 或者 aaa’or 1=1#等等等。
主要是經過輸入來看返回,來看咱們的輸入有沒有參與到數據庫後臺的運算裏面.
(1)insert
看到界面發現是註冊猜想後臺數據庫操做應該是insert命令,咱們點擊註冊,咱們先進行單引號測試
提交發現出現錯誤意味着提交的語法在後臺參與了操做。
而後咱們得知道mysqlinsert語句的用法
Insert into member(username,pw,sex,phonenum,email,address)values(‘xxxxxxxx’11111,1,2,3,4);
要構造閉合首先在咱們能夠輸入的部分就是‘xxxx’裏插入報錯函數
Updatexml()
kobe' and updatexml(1,version(),0)#
updataxml(是mysql對xml文檔函數進行出巡和修改的Xpath函數)
函數有三個參數第一個數指定xml文檔表的字段名稱,第二個是指定要替換的位置,第三個是新的值,但這三個值都是錯誤的。
第一個是不存在的,最後一個0由於前面的是不存在的因此替換也是沒有意義的。關鍵是中間的數值,中間的數值也能夠用表達式的形式,函數會把這個表達式執行了而後以報錯的形式返回出來。
測試
發現沒有返回完整的版本號信息,這裏由於咱們沒有進行處理。
這裏咱們對函數進行處理加入concat函數意思是將傳進去的參數組合成一個字符串打印出來,concat也能夠執行表達式也就是將 0x7e和version()結果組合成一個字符串打印出來
kobe' and updatexml(1,concat(0x7e,version()),0)#
kobe' and updatexml(1,concat(0x7e,database()),0)#
0x7e是~號的十六進制
測試:
xiaohong' or updatexml(1,concat(0x7e,database()),0) or '
發現成功返回報錯打印數據庫名稱
(2)update
首先登錄以後發現能夠修改我的信息
Update語法與insert差很少咱們將以前的palyload輸入
xiaohong' or updatexml(1,concat(0x7e,database()),0) or '
提交測試:
發現同樣能夠返回報錯
首先看到界面有請求和刪除功能咱們點擊刪除,以後再burp上查看
猜想由於對於後臺來講其實就是獲取了id,而後進行刪除操做,因此咱們就對id進行操做,仍是使用以前的updatexml函數構造payload
1 or updatexml(1,concat(0x7e,database()),0)
將payload帶入burp裏面,由於參數是url類型進行提交的因此要進行URL編碼
能夠看到空格都變成了+號
最後看返回
成功報錯。
Base time注入輸入單引號不會返回報錯,通常方法也不會返回報錯,
這時候咱們猜想是否爲base time 的注入
先打開控制檯f12選擇網絡
而後輸入payload:kobe' and sleep(5)#
發現執行了咱們的語句延遲五秒,證實存在base time的注入
而後就能夠構造咱們的payload
kobe' and if((substr(database(),1,1))='a',sleep(5),null)#
經過一個if語句讓數據庫名稱的第一個字符與a進行比較,若是同樣就會暫停五秒,若是不等於就爲假不暫停。
而後就慢慢進行嘗試
1.基於boolean的與基於time的同樣,用以前的方法都不會返回報錯。
2.不論是輸入正確,仍是輸入錯誤,都只顯示兩種狀況(能夠認爲是0或者1)
3.在輸入正確的狀況下,輸入and1=1/and1=2發現能夠判斷
測試,經過輸入正確的名字加上咱們的語句and 1=1#發現,也成功返回信息。
而後輸入kobe' and 1=2#,發現有報錯,斷定是存在sql注入的,可是前端返回信息特別少。用我以前的報錯函數payload輸入也不能得到報錯。怎麼辦呢。
辦法總比困難多
這裏咱們使用一個這裏substr函數,先了解什麼是substr函數
Select substr(database(),1,1);
意思是使用取出數據庫名稱的第一個字符一次取出一個。
那咱們如何知道要猜的名稱長度,這裏再用一個函數,length得到長度,可是基於boolean函數的只能返回真假因此
Length(database())>8,經過這種方式來猜,
(1)測試payload
kobe' and ascii(substr(database(),1,1))>113#
前面爲真若是and後面也爲真就會返回kobe的信息,根據真假來判斷咱們的猜想
先去猜想數據庫第一個字符的ascii碼大於113
返回爲假
再次猜想
kobe' and ascii(substr(database(),1,1))=112#
返回爲真。
如今進行進一步構造payload
將database()替換爲查找數據庫裏第一個表的表名,以後再去一個個判斷字符
kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))<112#
返回爲真,說明數據庫第一個表的表名的第一個字符的ASCII碼小於112,而後以此類推就能夠猜到完整的。
手工盲注效率仍是很慢,因此咱們只須要搞懂原理,在實際測試的過程當中仍是須要自動化的工具,例如sqlmap之類的,因爲以前測試的時候沒有記錄,這裏就不演示了。