Web Hacking

[WebHacking] - Dreamhack command-injection-1 문제 풀이 (command injection)

Papya_j 2024. 8. 17. 20:23

Command Injection에 해당하는 기본 문제를 풀어보겠다.

 

[문제 분석]

서버에 접속하면 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의 코드를 보면 POST에서 보낼 핑을 받고 이것을 host로 놓은 다음 cmd에서 "ping -c 3 "host"를 하는 것을 알 수 있다.

 

실제로 8.8.8.8로 ping을 보내보면 다음과 같다.


[Write Up]

요청한 형식과 일치시키라는 경고문이 뜬다. 뭔가 제약이 있는 것 같아서 추가적으로 확인해보겠다.

 

개발자 모드로 확인해서 들어가보니 pattern에 제약이 걸린 것을 확인할 수 있다. 이것을 없애야 입력이 가능할 것 같아서 pattern 부분을 지워주고 다시 해보겠다.

 

이젠 입력이 잘 되는 것을 확인할 수 있다.

 

ping -c 3 "| cat flag;" 처럼 원래 안되던 입력이 되는데 이러한 입력을 적절히 수정해보겠다.

* 일단 ping을 보내고 flag를 나을 것 같다. ping을 보낸 후에 그 뒤에 flag를 얻어내는 방식으로 시도해보았다.

 

-> 입력 : 8.8.8.8" ; ls"

 

다음과 같은 결과가 나왔다. ping이 잘 되고 난 후에 flag.py가 보이는 것을 확인할 수 있다. 여기서 flag.py를 cat 명령어를 통해 정보를 빼내면 될 것 같다.

 

정답

8.8.8.8" ; cat flag.py"

정상적으로 FLAG가 출력되는 것을 확인할 수 있다.

 

 


* 더 간단하게

" ; cat flag.py"

를 입력하면 바로 정답을 얻을 수 있다.

 

ping -c 3 "{host}" 형태로 전달이 되는데 여기서 위 답을 입력하면

pint -c 3 "" ; cat flag.py"" 가 된다.

-> ping을 아무것도 안 보낸 후에 다음 작업을 ;를 통해 진행하고 cat flag.py를 실행한 후에 ""는 상쇄시키면 끝난다.