본문 바로가기
Study/Dreamhack

[Dreamhack] Beginner 워게임 baby-linux 풀이

by 이브(Eve) 2024. 8. 25.

 

리눅스 명령어를 실행하는 웹 서비스가 작동하고 있다고 한다.

그리고 웹 서비스의 코드가 첨부파일로 주어졌다. (코드의 해석은 이 글의 맨 아래에 있다.)

이 안에서 flag.txt 파일을 찾는 것이 목적이다.

일단 웹 페이지로 들어가보자.

웹 페이지의 화면

 

리눅스 명령어를 실행한다는 점과 echo $를 보니 저 검은색 부분은 리눅스의 터미널과 같은 동작을 할 것으로 추측되었다. 또 그 결과는 Result에 출력될 것이다.

flag.txt 파일을 찾아보라고 하였으므로, ls 명령어를 입력해보았다.

hint.txt라는 파일이 눈에 띈다. cat hint.txt 를 입력해 해당 파일을 열어보자.

flag가 있는 경로를 알려주었다! 그렇다면 flag의 전체 경로는 ./dream/hack/hello/flag.txt가 될 것이다.

cat 명령어를 통해 flag.txt 파일을 읽어주자.

어라? No!가 떴다.

내가 입력을 잘못했다면 No! 말고 아예 아무런 창도 뜨지 않았어야 한다. 문제 파일로 주어진 소스코드를 분석해보자.

#!/usr/bin/env python3
import subprocess
from flask import Flask, request, render_template

APP = Flask(__name__)

@APP.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST':
        user_input = request.form.get('user_input')
        cmd = f'echo $({user_input})'
        if 'flag' in cmd:
            return render_template('index.html', result='No!')

        try:
            output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
            return render_template('index.html', result=output.decode('utf-8'))
        except subprocess.TimeoutExpired:
            return render_template('index.html', result='Timeout')
        except subprocess.CalledProcessError:
            return render_template('index.html', result='Error')

    return render_template('index.html')

if __name__ == '__main__':
    APP.run(host='0.0.0.0', port=8000)

 

소스 코드 중간에 cmd에 'flag'가 있다면 'No!'를 반환하는 코드가 있었다.

이는 와일드카드 사용하여 우회할 수 있다.

 

  • 와일드카드란?
더보기

와일드카드(Wildcards)

리눅스에서 임의의 다른 문자를 나타낼 수 있는 특수 문자들을 의미한다. 주로 명령어를 다른 문자열로 대체하기 위해 사용된다.

 

?나 *와 같은 문자가 a-z, 0-9 범위 내 임의의 0개 이상의 문자로 대체될 수 있다.

 

ex) fl*g.txt는 fl과 g 사이에 어떤 문자가 몇 글자나 있든 상관없이 모두 일치시킨다. flg.txt도 fl*g.txt에 일치한다.

ex) fl?g.txt는 fl과 g 사이에 정확히 한 문자가 있는 파일과 일치한다. 

 

[] : [문자1-문자2] 혹은 [문자1, 문자2, ...] 형태로 범위를 지정한다. 범위 내 모든 문자로 대체될 수 있다.

ls test[0-9] : 파일명이 test로 시작하고 마지막이 숫자인 파일을 모두 출력한다.

와일드카드를 사용해 flag.txt 말고 fl?g.txt를 이용해주자.

이렇게 하면 최종적으로 flag값을 얻을 수 있다.

 

  • Python 소스 코드 분석
#!/usr/bin/env python3
import subprocess
from flask import Flask, request, render_template

APP = Flask(__name__) # Flask를 이용하여 초기화

@APP.route('/', methods=['GET', 'POST'])
def index():
    if request.method == 'POST': # 'POST'방식일 때만 작동
        user_input = request.form.get('user_input') # 사용자의 입력을 받음
        cmd = f'echo $({user_input})' # cmd는 echo $({user_input}) 형식으로 실행
        if 'flag' in cmd: # 만약 사용자가 입력한 내용에 flag가 있으면 'No!' 출력
            return render_template('index.html', result='No!')

        try: # 명령어를 실행하고 그 결과를 웹 페이지에 출력
            output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
            return render_template('index.html', result=output.decode('utf-8'))
        except subprocess.TimeoutExpired: # 명령어 실행이 5초 이상 걸릴 경우 Timeout 출력
            return render_template('index.html', result='Timeout')
        except subprocess.CalledProcessError: # 명령어 실행에 실패하면 'Error' 출력
            return render_template('index.html', result='Error')

    return render_template('index.html')

if __name__ == '__main__':
    APP.run(host='0.0.0.0', port=8000) #0.0.0.0:8000에서 실행하여 모든 IP주소에서 서버에 접근할 수 있도록 설정

 

공부하는 중에 분석한 코드라 부족하거나 틀린 부분이 있을 수 있습니다! 코드 지적은 언제든지 환영입니다.

'Study > Dreamhack' 카테고리의 다른 글

[Dreamhack] Begineer 워게임 64se64 풀이  (0) 2024.08.16