해당 서버는 공격자가 C&C 서버로 사용중인 서버이다. 해당 서버의 취약점을 식별하여라 파일 다운로드 경로 예: /download?filename=main.css
문제 설명에서 파일 다운로드 경로에 예시를 들어주는것을 보아 LFI(Local File Injection) 취약점을 예상할 수 있습니다. 실제로 저 경로로 들어가보니 main.css 파일 다운이 가능했습니다.
/etc/passwd
로 접근하여 확인해보니 LFI가 가능합니다.
/proc/self/cmdline
로 접근하여 현재 실행중인 프로세스 파일 명을 확인합니다.
app.py
가 실행중임을 확인할 수 있습니다.
../app.py
로 접근해보겠습니다.
from flask import Flask, render_template, abort, request, abort, send_file
from pathlib import Path
import os
import datetime as dt
app = Flask(__name__)
app.secret_key = os.urandom(128).hex()
def getReadableByteSize(num) -> str:
for unit in ['', 'K', 'M', 'G', 'T', 'P', 'E', 'Z']:
if abs(num) < 1024.0:
if num == int(num):
return "%d%s" % (int(num), unit)
else:
return "%3.1f%s" % (num, unit)
num /= 1024.0
if num == int(num):
return "%d%s" % (int(num), unit)
else:
return "%.1f%s" % (num, 'Y')
def getTimeStampString(tSec: float) -> str:
tObj = dt.datetime.fromtimestamp(tSec)
tStr = dt.datetime.strftime(tObj, '%Y-%m-%d %M:%S')
return tStr
@app.route('/')
def index():
return render_template("index.html")
@app.route('/', defaults={'reqPath': ''})
@app.route('/<path:reqPath>')
def directory_listing(reqPath):
FolderPath = app.root_path
absPath = os.path.join(FolderPath, reqPath)
if not os.path.exists(absPath):
return abort(404)
def fObjFromScan(x):
fileStat = x.stat()
return {'name': x.name,
'relPath': os.path.relpath(x.path, FolderPath).replace("\\\\", "/"),
'mTime': getTimeStampString(fileStat.st_mtime),
'size': getReadableByteSize(fileStat.st_size),
'isdir': os.path.isdir(x.path),
}
if os.path.isdir(absPath):
fileObjs = [fObjFromScan(x) for x in os.scandir(absPath)]
else:
abort(404)
parentFolderPath = os.path.relpath(
Path(absPath).parents[0], FolderPath).replace("\\\\", "/")
return render_template('list.html', data={'files': fileObjs, 'parentFolder': parentFolderPath, 'req_path': request.path})
@app.route('/download', methods=['GET'])
def download():
filename = request.args.get('filename')
if not filename:
abort(400)
file_path = os.path.join('static', filename)
if not os.path.isfile(file_path):
return abort(404)
return send_file(file_path, as_attachment=True)
if __name__ == '__main__':
app.run(host="0.0.0.0", port=5000)
디렉토리 명으로 접속 시 Directory listing 하는것을 확인할 수 있습니다.
root 폴더에 들어가니 flag-c368132241ec56040bdd.zip
라는 파일이 있습니다.
해당 파일을 내려받고 zip 압축해제 하여 플래그를 확인할 수 있습니다.
whitehat2024{1330E4DE5DD8DF533D8D5C5388420249E71135B7}