문제
https://dreamhack.io/wargame/challenges/1186
소스코드
#!/usr/bin/python3
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)
코드 분석
/로 들어가게 되면,
일단
["/bin/bash", "-c", f"echo {user_ip}"],
익숙한.. 저기에 대충 1;cat /flag 이런 거 입력하면 될 거 같은...command injection이 가능할 거 같은 코드가 보인다.
저기에 무엇이 들어 갈 거 같은지 보면
user_ip = request.access_route[0] if request.access_route else request.remote_addr
user_ip에는...
request.access_route[0]가 들어간다.
만약 access_route가 있다면... access_route[0]이 들어가고, 아니라면 request.remote_addr이 들어간다.
대챗지피티한테 물어봐볼까?
request.access_route 에는 사용자 -> 서버 까지 갈 때 동안 방문한 모든 ip 주소를 반환한다고 한다.
예를 들어 사용자 -> 프록시1 -> 프록시2 -> 서버 이 순서대로 방문을 하게 된다면, access_route에는
request.access_route = ['사용자 IP', '프록시 1 IP', '프록시 2 IP']
이렇게 저장이 된다고 한다.
즉 사용자의 ip를 가져오는 것, 그 뒤의 remote_addr로 사용자의 ip를 가져오는 것이다. 그래서 처음에 접속했을 때 나의 아이피가 나왔었다.
Burp Suite
일단, 이 문제를 어떻게 풀면 좋을지 잘 모르겠어서 이것저것 찾아본 결과
내가 지금까지, 이것을 꼭 배워야하나? 라고 생각해서 안 배운 두 가지중에 하나는 써봐야겠다라는 생각이 들었다.
1. Burp Suite
2. 익스플로잇 코드
1번같은 경우는 쓰는 법을 몰라서
2번 같은 경우에는 시스템 해킹같은 경우에는 직접 ssh나 이런 접근으로만 접근을 하여야했었는데, 웹쪽은 아예 웹 사이트 및 코드가 주어졌었기에 굳이 필요하나? 싶었기 때문이었다.
그런데, 이번 거는 둘 중에 하나를 배워야했고..이참에 Burp Suite를 설치해서 작동시켜보았다.
맥북 프록시 설정에 들어가서
설정을 해주고
이것저것 설정을 해주었다.
그리고 실행을 시켜보면?
이렇게 잘 된다.
이거 사용하면 burp suite가 중간에 내용 오는 거 다 뻇어가서 그런가 실제 웹 브라우저는 렉 걸린 것처럼 실행이 제대로 안 된다.
아직 사용법은 제대로 잘 모르겠고, 이러이렇하게 사용한다는 것만 알았다. 그냥 intercept on/intercept off 이것만 알고있다.
풀이 전략
X-Forwarded-For 헤더를 알아야 한다.
X-Forwarded-For(XFF) 헤더란, 클라이언트의 원래 IP주소를 추적하기 위해 사용된다
서버는 사용자의 요청을 받았을 때, 서버는 보통 최종 프록시 또는 로드 밸런서의 IP 주소만 확인할 수 있는데, 이를 해결하기 위해서 XFF에다가 원래 사용자의IP 주소를 넣어서 확인할 수 있는 것이다.
만약 사용자 -> 프록시1 -> 프록시2->서버를 통해서 거쳐간다면
X-Forwarded-For: 사용자 Ip, 프로시1 ip, 프록시2ip 이렇게 설정이 된다
풀이 과정
burp suite를 찾고
X-Forwarded-For: 1;cat /flag를 치고 forward를 치면
플래그 값이 나온다
왜 헤더값만 넣어줬다고 저렇게 되는가?
- request.access_route는 서버에 들어오는 요청이 프록시를 거쳤을 때 X-Forwarded-For 헤더에 기록된 IP 주소들을 반환함.
- 만약 X-Forwarded-For 헤더가 존재하지 않으면, Flask는 request.remote_addr를 사용해 클라이언트의 IP를 반환함. request.remote_addr는 가장 마지막에 거친 IP 주소(주로 프록시나 로드 밸런서의 IP)가 됨.
그러니까, 저 헤더값을 가지고 access_route가 결정되는 거고, 그 첫번째에 1;cat /flag를 넣었기에 comand injection이 실행이 된것이다.
에필로그
그냥 포스트맨으로 해도 됐을 거 같은걸?
'보안 스터디 > 웹 해킹' 카테고리의 다른 글
[드림핵/워게임] random-test (웹 해킹) (2) | 2024.09.26 |
---|---|
[드림핵/워게임] baby-union (웹 해킹) (9) | 2024.09.25 |
[드림핵/워게임][wargame.kr] login filtering (웹해킹) (2) | 2024.09.20 |
[드림핵/워게임] CSRF Advanced (웹 해킹) (2) | 2024.09.19 |
[드림핵/워게임] sql injection bypass WAF (웹 해킹) (2) | 2024.09.16 |