pathtraversal
문제 설명
* API 서버란?
API(Application Programming Interface)
서로 다른 프로그램끼리 통신할 경우 API를 통함. (즉, 통신의 매개체)
API 서버는 규격화 되어 있는 서버.. 대표적으로 데이터베이스를 대신해서 규칙(로그인하기, 상품정보 보기, 결제하기 등)들을 정의함.
-> 이 문제에서는 사용자의 정보를 조회하는 API 서버인 것
Path Traversal 취약점이란?
디렉터리 조작으로도 알려져 있으며 파일 다운로드 취약점과 유사한 부분이 많다.
(*파일 다운로드 취약점 : 웹 서비스의 파일 시스템에 존재하는 파일을 다운로드하는 과정에서 발생
공격자가 웹 서비스의 파일 시스템에 존재하는 임의 파일을 다운로드 할 수 있음)
사용자로부터 경로(path) 형태의 입력값을 받아 서버의 파일에 접근할 수 있는 공격 기법이다.
즉, 경로 조작을 통해 서버 내의 파일에 접근 가능함
-> /api/flag 디렉토리에 접근하는 걸까? 문제를 풀며 확인하도록...
문제 분석
(1) 서버 생성 후 탐색
Ger User Info에 들어가보니 아래와 같은 화면을 확인할 수 있다.
View 버튼을 누른 모습
내 마음대로 useid를 입력하니 이런 화면이 뜸
(2) 다운로드 파일 열어 코드 확인
#!/usr/bin/python3
from flask import Flask, request, render_template, abort
from functools import wraps
import requests
import os, json
users = {
'0': {
'userid': 'guest',
'level': 1,
'password': 'guest'
},
'1': {
'userid': 'admin',
'level': 9999,
'password': 'admin'
}
}
def internal_api(func):
@wraps(func)
def decorated_view(*args, **kwargs):
if request.remote_addr == '127.0.0.1':
return func(*args, **kwargs)
else:
abort(401)
return decorated_view
app = Flask(__name__)
app.secret_key = os.urandom(32)
API_HOST = 'http://127.0.0.1:8000'
try:
FLAG = open('./flag.txt', 'r').read() # Flag is here!!
except:
FLAG = '[**FLAG**]'
@app.route('/')
def index():
return render_template('index.html')
@app.route('/get_info', methods=['GET', 'POST'])
def get_info():
if request.method == 'GET':
return render_template('get_info.html')
elif request.method == 'POST':
userid = request.form.get('userid', '')
info = requests.get(f'{API_HOST}/api/user/{userid}').text
return render_template('get_info.html', info=info)
@app.route('/api')
@internal_api
def api():
return '/user/<uid>, /flag'
@app.route('/api/user/<uid>')
@internal_api
def get_flag(uid):
try:
info = users[uid]
except:
info = {}
return json.dumps(info)
@app.route('/api/flag')
@internal_api
def flag():
return FLAG
application = app # app.run(host='0.0.0.0', port=8000)
# Dockerfile
# ENTRYPOINT ["uwsgi", "--socket", "0.0.0.0:8000", "--protocol=http", "--threads", "4", "--wsgi-file", "app.py"]
@app.route()를 이해하기 위해서는 파이썬 플라스크를 알아야 한다... (따로 이건 정리하겠음...)
route는 request 요청을 전달받으면 어떤 모델을 실행시킬지 판단함
@app.route: 해당 앱의 URL을 함수/기능에 쉽게 할당하기 위해 Flask가 제공하는 Python 데코레이터
HTTP Methods
- 주요 메소드 5가지
GET | For reading data | 리소스 조회, 오직 데이터 수신 |
POST | For creating data | 요청 데이터 처리, 주로 데이터 등록에 사용 |
PUT | For updating data by completely replacing data with new content |
리소스를 대체, 해당 리소스 없으면 생성 |
PATCH | For updating data, but by partially modifying a few attributes |
리소스 일부만 변경 |
DELETE | For deleting data | 리소스 삭제 |
GET
보통 리소스를 조회할 때 사용하며, 서버에 전달하고 싶은 데이터는 query를 통해서 전달한다. 메시지 body를 사용하여 데이터를 전달하지만, 지원하지 않는 곳이 많음
POST 데이터 요청을 처리하고, 메시지 body를 통해 서버로 데이터 전달.
주로 신규 리소스를 등록하거나 프로세스 처리에 사용된다.
PUT
리소스 있으면 대체하고, 없으면 생성한다. 쉽게 말해 덮어쓰기
PATCH
PUT과 마찬가지로, 리소스를 수정할 때 사용하지만, 일부분만 변경 가능하다는 점이 다르다.
DELETE
리소스를 제거할 때 사용한다.
(3) 코드를 간단하게 해석해보자
이 코드에서는 입력한 userid를 /api/user/ {userid}에 저장한다.
elif request.method == 'POST':
userid = request.form.get('userid', '')
info = requests.get(f'{API_HOST}/api/user/{userid}').text
return render_template('get_info.html', info=info)
그리고 /api/flag에서 FLAG를 찾을 수 있다.
@app.route('/api/flag')
@internal_api
def flag():
return FLAG
그래서 FLAG를 찾기 위해 ../flag를 입력했더니 아래와 같은 화면이 출력되었다.
(4) 뭐가 잘못된건지 확인하기 위해 Burp Suite를 실행하여 문제 파악 및 해결
버프스위트 - 웹 프록시
브라우저와 웹 서버 간의 요청 및 응답 패킷을 Intercept하여 내용을 보거나 변조하여 취약점 점검에 사용하거나
해킹에 사용한다.
Intercept ON으로 설정한다.
Open browser를 통해 ../flag 입력했더니 undefined임을 확인할 수 있음
그래서 버프스위트를 통해 intercept 해본 결과 userid=undefined로 정의되어 있었음
Flag를 얻기 위해 userid의 값을 ../flag로 수정해준다.
그리고 다시 브라우저를 확인하면 Flag를 획득!!
파이썬 문법을 잘 모르기도 해서 더 어려웠던 것 같다... 버프스위프에서 브라우저 열 때 계속 버퍼링 걸리고 화면이 뜨지 않아 프록시 설정이랑 이것저것 해봤는데 (결국 되긴 했으나) 프록시 때문에 안 됐던 건지... 프록시와 어떠한 관련점이 있는지... 그리고 http와 관련해 이렇게 쓰일 수도 있다는 점을 알게 되어 어려웠지만 몹시 흥미로웠다.
참고
'SWLUG > CTF' 카테고리의 다른 글
[CTF/Dreamhack] web-misconf-1 (0) | 2024.05.17 |
---|---|
[CTF/Dreamhack] simple-web-request (0) | 2024.05.11 |
[CTF/Dreamhack] baby-union (0) | 2024.05.06 |
[CTF/Dreamhack] phpreg (0) | 2024.05.06 |
[CTF/Dreamhack] php7cm4re & Flying Chars (0) | 2024.04.27 |