본문 바로가기

SWLUG/CTF

[CTF/Dreamhack] pathtraversal

 

pathtraversal

사용자의 정보를 조회하는 API 서버입니다. Path Traversal 취약점을 이용해 /api/flag에 있는 플래그를 획득하세요! Reference Server-side Basic

dreamhack.io

 

 

pathtraversal

 

문제 설명

 

 

* API 서버란?

 

API(Application Programming Interface)

서로 다른 프로그램끼리 통신할 경우 API를 통함. (즉, 통신의 매개체)

API 서버는 규격화 되어 있는 서버.. 대표적으로 데이터베이스를 대신해서 규칙(로그인하기, 상품정보 보기, 결제하기 등)들을 정의함.

 

 

-> 이 문제에서는 사용자의 정보를 조회하는 API 서버인 것

 

 

Path Traversal 취약점이란?

 

디렉터리 조작으로도 알려져 있으며 파일 다운로드 취약점과 유사한 부분이 많다.


(*파일 다운로드 취약점 : 웹 서비스의 파일 시스템에 존재하는 파일을 다운로드하는 과정에서 발생
공격자가 웹 서비스의 파일 시스템에 존재하는 임의 파일을 다운로드 할 수 있음)

사용자로부터 경로(path) 형태의 입력값을 받아 서버의 파일에 접근할 수 있는 공격 기법이다.
즉, 경로 조작을 통해 서버 내의 파일에 접근 가능함

 

출처: https://velog.io/@zzsla/webDirectory-traversal

 

-> /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와 관련해 이렇게 쓰일 수도 있다는 점을 알게 되어 어려웠지만 몹시 흥미로웠다. 

 

 

참고

 

API와 API 서버 개념 정리하기

큐레이션 : '웹 서비스를 제공하는 IT 회사가 사용하는 기술 A to Z 훑고 가기'

maily.so

 

 

Path(Directory) Traversal

What Is❔ Path Traversal 취약점은 "디렉터리 조작" 으로도 알려져 있으며 파일 다운로드 취약점과 유사한 부분이 많다. 사용자로부터 경로(path) 형태의 입력값을 받아 서버의 파일에 접근할 수 있는

jini23-lamp.tistory.com

 

 

파일 다운로드 취약점에서 자주 쓰이는 Path Traversal 취약점 정리 - filedownload, path traveral

파일 다운로드 취약점이란. 웹 서비스의 파일 시스템에 존재하는 파일을 다운로드하는 과정에서 발생하는 보안 취약점 공격자가 웹 서비스의 파일 시스템에 존재하는 임의 파일을 다운로드할

hobbylists.tistory.com

 

 

[백엔드] Flask : @app.route() 의미

@app.route() 의미 @app.route('/', methods = ['GET']) def hello_world(): return 'Hello World hihi' - route란: URI를 정리하는 것, 연결시켜주는 아이. - Request가 왔을 때, router가 항상 먼저 받는다. 그리고 어떤 모델을 실

yeo0616.tistory.com

 

'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