특정 Host에 ping 패킷을 보내는 서비스입니다.
Command Injection을 통해 플래그를 획득하세요. 플래그는 flag.py에 있습니다.
chatGPT와 함께 풀어보세요!
출처: dreamhack
문제 페이지는 ping
을 보낼 수 있는 사이트로 구성되어 있습니다.
#!/usr/bin/env python3
import subprocess
from flask import Flask, request, render_template, redirect
from flag import FLAG
APP = Flask(__name__)
@APP.route('/')
def index():
return render_template('index.html')
@APP.route('/ping', methods=['GET', 'POST'])
def ping():
if request.method == 'POST':
host = request.form.get('host')
cmd = f'ping -c 3 {host}'
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('ping_result.html', data=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('ping_result.html', data='Timeout !')
except subprocess.CalledProcessError:
return render_template('ping_result.html', data=f'an error occurred while executing the command. -> {cmd}')
return render_template('ping.html')
if __name__ == '__main__':
APP.run(host='0.0.0.0', port=8000)
본 문제에서는 소스코드를 제공하고 있습니다.
압축파일에는 app.py 외에 requirements.txt 에서 Flask가 기재되어 있고, 그 외에는 static, template 폴더도 존재하지만 문제 해결에 영향을 주는 요소는 아니므로 분석하지 않았습니다.
Code | Description |
---|---|
/ping 페이지에 GET Method로 접속 시에는 핑을 보낼 수 있는 템플릿을 리턴합니다.POST Method로 접속한 경우에는 host 파라미터를 받아와 host 라는 변수에 지정하고, ping -c 3 {host} 명령어를 통해 입력한 값을 {host} 에 대입함으로써 핑을 보냅니다. |
flag는 flag.py
파일에 있다고 문제에서 말했고, Command Injection으로 풀이하면 된다고도 친절하게 적혀있습니다.
따라서 입력란을 잘 활용해 커멘드 인젝션을 시도하면, cat 명령어를 통해 flag.py 파일의 내용을 읽어와 플래그를 가져올 수 있을 것이라 생각하고 문제를 풀어보았습니다.
보통 command injection을 하기 위해서는 &&
기호를 사용하거나 ||
, ;
등 여러 기호를 사용합니다. 모두 명령어를 한 줄에 연속 실행하기 위한 기호입니다.
다만 약간의 차이점이 있는데, &&
기호는 앞의 명령어가 성공하면 뒤에 있는 명령어도 실행되게 됩니다. 반면에, ||
기호는 앞의 명령어가 오류가 발생하면 뒤의 명령어가 실행되고, ;
기호는 성공실패여부를 가리지 않고 무조건 실행합니다.
리눅스에서 파일의 내용을 확인하는 방법은 view, nano 등 여러 가지 방법이 있지만 간단하게 내용을 확인하려면 cat
명령어를 주로 사용합니다.
따라서 command injection을 하기 위한 기호에 여러가지가 있으므로, 페이로드는 여러가지로 나올 수 있습니다.
단순 cat flag.py
를 입력란에 입력할 경우, 프로그램은 입력받은 값을 앞의 ping
문과 합쳐 ping -c 3 cat flag.py
라는 명령어를 만든 후 실행할 것이고, 이는 잘못된 명령어이므로 오류가 발생합니다.
위 사항을 주의해서 페이로드를 만들어보면 아래와 같은 페이로드들을 통해 플래그 값을 얻을 수 있습니다.
& cat flag.py
| cat flag.py
; cat flag.py
DH{chatGPT_knows_what_the_ping_is}