- Web Hacking_command-injection-1🚩2024년 09월 28일 21시 29분 01초에 업로드 된 글입니다.작성자: sonootri
1. 문제 설명
2. 문제 풀이
시작 페이지, ping 페이지가 있는 간단한 웹 사이트다.
전 강의와 마찬가지로, Host IP를 입력하면 정상적으로 동작한다.
그럼 이제 코드를 살펴보자.
#!/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')
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')
-> cmd = f'ping -c 3 "{host}"': 사용자가 입력한 Host 값을 기반으로 Ping 명령어를 생성한다. ping -c 3은, 해당 Host에 대해 Ping을 3번 보내겠다는 의미이다.
-> output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5): 해당 함수는 시스템 명령어를 실해하고, 그 결과를 캡쳐해서 반환한다.
-> return render_template('ping_result.html', data=output.decode('utf-8')): 해당 함수를 통해 캡쳐한 Ping 명령어 결관 output은 byte 데이터로 반환되기 때문에, 이를 디코딩해 문자열로 반환한다.
-> 아래의 except는 Timeout = 5, 즉 Ping 명령어 실행이 5초를 초과하면 예외처리 하는 부분이다. CalledProcessError은 Ping 명령어가 실패하거 나 잘못된 명령어를 실행하면 발생한다.
이 부분을 살펴보자.
사용자의 입력을 받는 부분이 이전 강의와 다르게 ""로 감싸져있다.
cmd = f'ping -c 3 "{host}"'
//이전 강의에서의 cmd 형식 cmd = f'ping -c 3 {query}'
3. 라이트업 참고
cmd 변수는 사용자로부터 입력받은 Host 값을 포함하고 있다. 하지만 사용자의 입력을 그대로 명령어로 실행하기 때문에, 사용자가 악의적인 공격 코드를 주입할 수 있다.
예를 들어 host의 의도대로 "8.8.8.8"이 들어간다면 ping이 올바르게 실행되겠지만, " 문자를 하나 더 붙여 문자열에서 빠져나오게 된다면...? 그리고 뒤의 "는 #를 통해 주석처리 한다면...? Command Injection 공격을 수행할 수 있게 된다.
아까 위에서 형식이 일치하지 않아, 사용자가 입력한 값이 제출되지 않는 문제가 있었다. 이 문제는 개발자도구를 통해 코드를 살펴봤을 떄 왜 그랬는지 알 수 있다. pattern 속성 설정이 되어있다.
pattern 속성은, 폼 제출시 <input> 요소의 값을 검사할 때 사용될 정규 표현식을 명시하며, 여기서 표현된 정규 표현식은 A-Za-z 즉 영어 알파벳 전체 + 0-9 숫자 + "." + 글자수는 5에서 20글자까지 이다.
<input type="text" class="form-control" id="Host" placeholder="8.8.8.8" name="host" pattern="[A-Za-z0-9.]{5,20}" required="">
이 필터링은, Server단에서 일어나는 검증이 아닌, 클라이언트 단에서 일어나는 검증이기 때문에 우회가 가능하다.
개발자 도구를 사용해 pattern 속성을 제거하면 된다.
이제 아래 명령어를 사용해보자 (flag.py가 있는지 확인하기 위해 그냥)
8.8.8.8"; ls #
위의 명령어가 잘 작동 되는것을 확인했으니, 이제 flag를 얻자
8.8.8.8"; cat flag.py #
zizizi
'Dreamhack > 워게임' 카테고리의 다른 글
webhacking.kr: old-27 (0) 2024.10.01 Dreamhack: simple_sqli_chatgpt (1) 2024.10.01 Lord of Injection: germiln (0) 2024.10.01 Web Hacking_simple_spqi🚩 (0) 2024.09.27 root_me: CSRF-0 (0) 2024.09.25 다음글이 없습니다.이전글이 없습니다.댓글