
https://dreamhack.io/wargame/challenges/269
여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다.
CSRF 취약점을 이용해 플래그를 획득하는 문제입니다.
CSRF 취약점 : 사용자가 로그인된 상태를 악용하여, 공격자가 의도한 요청을 사용자 모르게 실행하게 하는 공격입니다.
주어진 서비스에 접속을 해 보았습니다. flag에 들어가면 http://127.0.0.1:8000/vuln?param=( ) 에 무언갈 입력할 수 있습니다. 이 입력을 통해 CSRF 공격을 하는 문제임을 알 수 있습니다.
app.py의 / 경로 코드를 확인했습니다.
@app.route("/")
def index():
session_id = request.cookies.get('sessionid', None)
try:
username = session_storage[session_id]
except KeyError:
return render_template('index.html', text='please login')
return render_template('index.html', text=f'Hello {username}, {"flag is " + FLAG if username == "admin" else "you are not an admin"}')
여기서 admin으로 로그인을 성공 해야만 FLAG값이 얻어짐을 확인할 수 있었습니다.
/flag 함수에서는 POST 요청 시 새로운 세션 ID를 생성하고, 그 세션 ID를 admin 사용자와 연결하는 것을 확인했습니다.
session_id = os.urandom(16).hex()
session_storage[session_id] = 'admin'
이는 flag 에 어떤 공격을 하여도, 그 요청은 항상 admin 권한을 가진 세션으로 처리됩니다.
비밀번호를 바꾸는 change_password 함수를 확인 해 보았습니다.
@app.route("/change_password")
def change_password():
pw = request.args.get("pw", "")
session_id = request.cookies.get('sessionid', None)
try:
username = session_storage[session_id]
except KeyError:
return render_template('index.html', text='please login')
users[username] = pw
return 'Done'
이 함수는 쿠키의 세션 ID를 통해 사용자 이름을 확인하고, 해당 사용자의 비밀번호를 변경합니다. admin에 로그인 을 성공해야 하지만, 비밀번호를 모르기 때문에 이 함수를 통해 admin의 비밀번호를 변경 후, 로그인을 해야함을 유추할 수 있습니다.
/vuln 함수에서 script를 통한 공격은 막혔다는걸 확인할 수 있습니다.
따라서 스크립트 삽입은 물가능 하지만, 태그 삽입은 가능하기에 /flag 에서, admin의 비밀번호를 바꾸는 <img src="/change_password?pw=1234"> 를 입력해줍니다.

/login 에서 id는 admin, password 는 위에서 설정한 1234 를 입력해 로그인에 성공하였습니다.
정상적으로 admin에 로그인 해 성공적으로 플래그를 획득할 수 있었습니다.

script 로 접속이 불가능한 상황에 우회할 수 있는 방법인 <img> 태그에 대해 알 수 있었습니다./flag, the server creates a new session linked to the admin./change_password route uses the sessionid cookie to determine the user.<script> tags are blocked, but HTML tags like <img> are allowed.<img src="/change_password?pw=1234"> triggers a password change.1234 reveals the flag.