소스코드 보러가자
#!/usr/bin/env python3
import subprocess
from flask import Flask, request, render_template, redirect, url_for
import string
import os
import hashlib
app = Flask(__name__)
try:
FLAG = open("./flag.txt", "r").read()
except:
FLAG = "[**FLAG**]"
KEY = hashlib.md5(FLAG.encode()).hexdigest()
guest_key = hashlib.md5(b"guest").hexdigest()
# filtering
def filter_cmd(cmd):
alphabet = list(string.ascii_lowercase)
alphabet.extend([' '])
num = '0123456789'
alphabet.extend(num)
command_list = ['flag','cat','chmod','head','tail','less','awk','more','grep']
for c in command_list:
if c in cmd:
return True
for c in cmd:
if c not in alphabet:
return True
@app.route('/', methods=['GET', 'POST'])
def index():
# GET request
return render_template('index.html')
@app.route('/flag', methods=['POST'])
def flag():
# POST request
if request.method == 'POST':
key = request.form.get('key', '')
cmd = request.form.get('cmd_input', '')
if cmd == '' and key == KEY:
return render_template('flag.html', txt=FLAG)
elif cmd == '' and key == guest_key:
return render_template('guest.html', txt=f"guest key: {guest_key}")
if cmd != '' or key == KEY:
if not filter_cmd(cmd):
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('flag.html', txt=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('flag.html', txt=f'Timeout! Your key: {KEY}')
except subprocess.CalledProcessError:
return render_template('flag.html', txt="Error!")
return render_template('flag.html')
else:
return redirect('/')
else:
return render_template('flag.html')
if __name__ == '__main__':
app.run(host='0.0.0.0', port=8000, debug=True)
이 Python 코드는 플래스크(Flask) 웹 애플리케이션으로, 사용자가 제공한 키와 명령어를 통해 플래그를 얻거나 명령어를 실행할 수 있는 인터페이스를 제공합니다. 보안 필터링과 명령어 실행 로직이 포함되어 있으며, 아래는 코드의 주요 부분에 대한 상세 설명입니다.
1. 주요 동작 구조
(1) 파일 및 상수 로드
- FLAG:
- flag.txt 파일의 내용을 읽어서 변수 FLAG에 저장.
- 파일을 읽을 수 없을 경우 기본값으로 [**FLAG**]를 설정.
- KEY와 guest_key:
- KEY: FLAG를 MD5 해시하여 생성된 키.
- guest_key: 문자열 guest를 MD5 해시하여 생성된 키.
(2) 명령어 필터링
def filter_cmd(cmd):
alphabet = list(string.ascii_lowercase)
alphabet.extend([' '])
num = '0123456789'
alphabet.extend(num)
command_list = ['flag','cat','chmod','head','tail','less','awk','more','grep']
for c in command_list:
if c in cmd:
return True
for c in cmd:
if c not in alphabet:
return True
- 입력된 명령어(cmd)를 필터링하여 보안성을 확보:
- 허용된 문자:
- 소문자 알파벳, 숫자, 공백.
- 금지된 명령어:
- flag, cat, chmod, head, tail, less, awk, more, grep 등.
- 필터링 논리:
- 금지된 명령어가 포함되거나 허용되지 않은 문자가 포함된 경우 True를 반환(필터링 적용).
- 허용된 문자:
(3) 라우팅
/ - 메인 페이지
@app.route('/', methods=['GET', 'POST'])
def index():
return render_template('index.html')
- 메인 페이지(index.html)를 렌더링.
- 주로 입력 폼을 사용자에게 제공.
/flag - 플래그 페이지
@app.route('/flag', methods=['POST'])
def flag():
- 동작 방식:
- 사용자로부터 key와 cmd_input을 POST 방식으로 입력받음.
- 조건에 따라 플래그를 보여주거나 명령어를 실행.
- 플래그 출력:
- 키가 KEY와 일치:
- 플래그 파일의 내용을 출력.
- 키가 guest_key와 일치:
- 게스트 키와 관련된 메시지 출력.
- 키가 KEY와 일치:
- 명령어 실행:
- cmd_input이 비어 있지 않은 경우:
- 필터링(filter_cmd)에 통과한 명령어만 실행.
- /bin/sh를 사용해 명령어 실행:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
- 명령어 실행 성공: 실행 결과를 출력.
- 실행 시간 초과: 타임아웃 메시지 반환.
- 오류 발생: 오류 메시지 반환.
- cmd_input이 비어 있지 않은 경우:
- 필터링 실패:
- 명령어에 금지된 문자가 포함되거나 조건에 맞지 않는 경우, 명령어 실행 없이 페이지 리로드.
- 기타:
- 키와 명령어가 모두 없는 경우 메인 페이지(/)로 리다이렉트.
2. 보안 취약점 분석
(1) 명령어 필터링 우회 가능성
- 필터링된 명령어 목록이 비교적 제한적이며, 허용된 문자 조합으로 우회 가능.
- 예: cat 대신 c a t처럼 공백으로 분리하여 우회 가능성 존재.
(2) 명령어 실행 제한 부족
- 명령어가 /bin/sh에서 실행되므로, 명령어 체인(;, &&)을 통해 악의적 명령어 실행 가능.
(3) 민감한 정보 유출 위험
- FLAG와 관련된 키(KEY)가 코드에서 직접 사용되므로, 만약 코드가 노출되면 MD5 해시를 복호화하여 플래그 유출 가능.
3. 해결 방안
(1) 필터링 강화
- 허용된 문자만 남기고 모든 특수 문자와 숫자열 제한.
- 예: 정규식을 사용하여 특정 패턴만 허용:
import re def filter_cmd(cmd): return not re.match(r'^[a-z0-9 ]+$', cmd)
(2) 명령어 실행 환경 제한
- 서브 프로세스 대신 파이썬 내부 로직으로 처리.
- 명령어 실행이 반드시 필요한 경우, 컨테이너 또는 가상 환경에서 실행.
(3) 플래그 관리 보안 강화
- FLAG와 관련된 데이터는 별도 암호화된 파일로 저장하고 동적으로 로드.
- MD5 대신 SHA256 또는 Argon2와 같은 더 강력한 해시 알고리즘 사용.
4. 요약
- 이 코드의 주요 기능은:
- 특정 키 입력 시 플래그 노출.
- 제한된 명령어 실행.
- 그러나 필터링 및 실행 환경의 보안이 취약하여 명령어 우회와 정보 유출 가능성이 존재.
- 이를 강화하려면 필터링 개선, 명령어 실행 제한, 플래그 관리 보안성을 높이는 것이 중요합니다.
우회 방법일 것 같네. 문제 제목처럼 if문을 바이패스 해야할 것 같다
KEY = hashlib.md5(FLAG.encode()).hexdigest()
guest_key = hashlib.md5(b"guest").hexdigest()
"guest"라는 문자열을 바이트로 변환 후, hexdigest로 16진수로 문자열 변환 이 후 hashlib.md5를 사용해서
해싱한 값을 guest_key에 저장한다
guest_key를 찾아보자
비쥬얼코드 저장경로 오류떠서 리눅이 켰다
윈도우말고 리눅이가 최고다...ㄹㅇ
import hashlib
hashtext = hashlib.md5(b"guest").hexdigest()
print(hashtext)
084e0343a0486ff05530df6c705c8bb4
하씨 burpsuit 아직도 사용방법 모르겠다 ㅋㅋㅋ아 ㅋㅋ내일 선생님한테 당장 달려가고싶으면 개추..
https://minnggyuu.tistory.com/10
https://velog.io/@cherry613/Dreamhack-CTF-BypassIF
https://tjrrb4551.tistory.com/entry/Dreamhack-BypassIF-write-up
https://yun-2.tistory.com/entry/CTFSeason5Round4-BypassIF
다른 사람들 풀이글 보면, burpsuit이용해서 패킷 가로채쇼 cmd_input에 ls를 전달하면
flag.txt
requirements.txt
static
templates
가 뜨는걸 확인할 수 있는데 문제는 명령어 필터링 때문에 읽을 수가 없다
방법은?
if cmd != '' or key == KEY:
if not filter_cmd(cmd):
try:
output = subprocess.check_output(['/bin/sh', '-c', cmd], timeout=5)
return render_template('flag.html', txt=output.decode('utf-8'))
except subprocess.TimeoutExpired:
return render_template('flag.html', txt=f'Timeout! Your key: {KEY}')
except subprocess.CalledProcessError:
return render_template('flag.html', txt="Error!")
return render_template('flag.html')
else:
return redirect('/')
Timout! Your key: {key}
아
타임아웃되면 flag키값이 나온다 엌ㅋ
이런 부분이 있다.
filter_cmd 에서 바이패스에 성공하면, 밑의 구문을 실행한다.
try 첫 번째는 cmd 커맨드를 실행한다. timeout=5을 써서 명령이 실행되는 시간을 5초로 제한했다. 5초를 넘어가면, Timeout 시킨다.
그럼 Timeout되면 어떻게 되냐?
밑에 달린 except 구문을 보면, timeout이 발생하면, 'Timeout! Your key: {KEY}' 를 반환한다.
ㅇ... 그냥 KEY.. FLAG를 던져준다.
출처 ㅣhttps://minnggyuu.tistory.com/10
이분도 당황하신듯 ㅋㅋ
: cmd가 필터링 함수에 해당하는 것이 있는지 확인하게 된다. 통과된다면 try문으로 이동한다.
: try문에서 cmd에서 작성했던 쉘 명령어가 실행되고 출력 결과를 가져오게 된다. 이때, 명령어 실행에 5초 이상 지연이 발생하면 에러문을 발생하는 것을 확인할 수 있다.
: except subprocess.TimeoutExpired는 timeout 에러가 발생하면 flag.html 페이지를 렌더링하고 KEY(Admin의 KEY)를 전달함을 알 수 있다.
: 따라서 지연시키면 Admin의 KEY를 얻을 수 있을 것이다.
출처 ㅣ https://yun-2.tistory.com/entry/CTFSeason5Round4-BypassIF
큰일났다 burpsuit 이용해야하네;; 도움 도움;;;
dkdkdㅏㄴㅁ암나안ㅁ아
내일 선생님한테 도움 요청해야겠다..버프 너무 어렵네
2024-12-02
캬 ㅋㅋㅋ3달만에 버프수트 사용법 깨달음ㅋㅋㅋ
앜ㅋㅋㅋㅋ
캬
ㅋㅋㅋㅋㅋㅋㅋㅋ
'Dreamhack > Dreamhack Wargame (Challenge)' 카테고리의 다른 글
[85] IT 비전공자 [dreamhack]random-test문제 풀기 (0) | 2024.12.03 |
---|---|
[84] IT 비전공자 [dreamhack]what-is-my-ip문제 풀기 (0) | 2024.12.02 |
[82] IT 비전공자 [dreamhack]memory_leakage문제 풀기 (0) | 2024.11.30 |
[81] IT 비전공자 [dreamhack]NoSQL-CouchDB문제 풀기 (0) | 2024.11.29 |
[80] IT 비전공자 [dreamhack]Type c-j문제 풀기 (0) | 2024.11.28 |