오늘 풀 문제는 Dreamhack.io에 있는 wargame의 file-download1 문제이다. Web hacking의 강의와 system hacking 강의의 logical bug를 참고하면 좋다고 한다. 풀면서 느낀거지만.. 아무래도 webhacking을 많이 까먹은듯하여.. 공부하면서 포스팅을 좀 해야겠다는 생각이 들었다.. 암튼 사담은 이쯤하고 문제풀이를 들어가고자 한다
https://dreamhack.io/lecture/curriculums/1
Web Hacking
-
dreamhack.io
https://dreamhack.io/lecture/courses/1
Logical Bugs
로지컬 버그를 이해하고 공격할 수 있다.
dreamhack.io

이번 문제도 다른 문제와 마찬가지로 Host, port를 이용하여 문제에 접근할 수 있도록 되어있다. 또한 문제 파일을 다운로드를 해 보면 본 web의 코드가 나와있는 모습을 볼 수 있다. 저번과 마찬가지로 본 Host와 Port를 이용하여 웹 사이트에 접근하고자 한다.
접속 하는 형식 : http://host:port

문제에서 제시한 링크를 타고 접속을 하면 다음과 같은 화면이 뜬다. 우선 메모를 업로드를 하라고 하니 upload my memo에 들어가서 어떻게 이 web이 구성되어있는지 파악해보고자 한다.

이 창에서 대충 몇가지의 숫자나 글자를 입력하고 upload를 눌러보고 home으로 가니 다음과 같은 화면을 볼 수 있었다.



본 주소를 보아하니 메모를 읽기위해 read가 뜨고 그 이후 name으로 memo의 제목을 판단해서 내가 저장한 메모가 있는 곳으로 저장하는 구조인듯 하다.

비슷하게 없는 메모를 입력했을때에는 이런 창이 뜬다. 여기서 이제 flag.py를 얻어내야하는데, 어떤 방법이 있을지 고민하다가 우선 주소창에 입력하면 되지 않을까 하고 다음과 같은 값을 name=뒤에 입력해 보았다
flag.txt
flag.py
하지만 되지 않아서 왜인지.. 해보니 앞에서 주어진 소스코드랑 system hack 강의를 참고하다보니 상위 디렉토리로 움직여서 상위 디렉토리에서 flag.py를 도출할 수 있지 않을까 하며 상위 디렉토리로 가는 문자 (../)와 함께 입력하고자 했다
read?name=../flag.py
이러한 결과를 입력해보니 flag값이 도출된 것을 아래와 같이 볼 수 있다.

그렇다면 이게 어떻게 가능한 것인지.. 어디서 이걸 이렇게 유추를 해야하는지 문제에서 제시를 해 준 소스코드를 보면서 한번 생각을 해보도록 하자
import os
import shutil
from flask import Flask, request, render_template, redirect
from flag import FLAG
APP = Flask(__name__)
UPLOAD_DIR = 'uploads'
@APP.route('/')
def index():
files = os.listdir(UPLOAD_DIR)
return render_template('index.html', files=files)
@APP.route('/upload', methods=['GET', 'POST'])
def upload_memo():
if request.method == 'POST':
filename = request.form.get('filename')
content = request.form.get('content').encode('utf-8')
if filename.find('..') != -1:
return render_template('upload_result.html', data='bad characters,,')
with open(f'{UPLOAD_DIR}/{filename}', 'wb') as f:
f.write(content)
return redirect('/')
return render_template('upload.html')
@APP.route('/read')
def read_memo():
error = False
data = b''
filename = request.args.get('name', '')
try:
with open(f'{UPLOAD_DIR}/{filename}', 'rb') as f:
data = f.read()
except (IsADirectoryError, FileNotFoundError):
error = True
return render_template('read.html',
filename=filename,
content=data.decode('utf-8'),
error=error)
if __name__ == '__main__':
if os.path.exists(UPLOAD_DIR):
shutil.rmtree(UPLOAD_DIR)
os.mkdir(UPLOAD_DIR)
APP.run(host='0.0.0.0', port=8000)
본 소스코드를 크게 보면 index 부분과 memo를 등록하는 함수부분, memo를 읽어들이는 총 세가지의 함수 부분으로 나뉜 것을 볼 수 있다. 여기서 read_memo()의 부분을 보면 특별히 입력된 값을 검사하는 부분이 존재하지 않아 path traversal 버그가 발생하게 된다. 주로 상위 디렉토리로 가는것인지 아닌것인지에 대한 검증을 하지 않았기 때문에 발생하는 버그로 이를 검증해주는 절차가 필요하다. path traversal에 대한 버그는 system hack 강의를 수강하면서 차차 정리를 해보기로..!
'Security > Web hacking' 카테고리의 다른 글
| [Dreamhack] wargame cookie 문제풀이 (0) | 2021.11.08 |
|---|
보안 전공 개발자지만 대학로에서 살고 싶어요
포스팅이 좋았다면 "좋아요❤️" 또는 "구독👍🏻" 해주세요!