Dreamhack - csrf-2

·2025년 7월 14일

Dreamhack-Writeups

목록 보기
21/52
post-thumbnail

csrf-2

문제 링크

https://dreamhack.io/wargame/challenges/269

문제 설명

여러 기능과 입력받은 URL을 확인하는 봇이 구현된 서비스입니다.
CSRF 취약점을 이용해 플래그를 획득하는 문제입니다.

CSRF 취약점 : 사용자가 로그인된 상태를 악용하여, 공격자가 의도한 요청을 사용자 모르게 실행하게 하는 공격입니다.

풀이과정

  1. 주어진 서비스에 접속을 해 보았습니다. flag에 들어가면 http://127.0.0.1:8000/vuln?param=( ) 에 무언갈 입력할 수 있습니다. 이 입력을 통해 CSRF 공격을 하는 문제임을 알 수 있습니다.

  2. 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값이 얻어짐을 확인할 수 있었습니다.

  3. /flag 함수에서는 POST 요청 시 새로운 세션 ID를 생성하고, 그 세션 ID를 admin 사용자와 연결하는 것을 확인했습니다.

    session_id = os.urandom(16).hex()
    session_storage[session_id] = 'admin'

    이는 flag 에 어떤 공격을 하여도, 그 요청은 항상 admin 권한을 가진 세션으로 처리됩니다.

  4. 비밀번호를 바꾸는 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의 비밀번호를 변경 후, 로그인을 해야함을 유추할 수 있습니다.

  5. /vuln 함수에서 script를 통한 공격은 막혔다는걸 확인할 수 있습니다.
    따라서 스크립트 삽입은 물가능 하지만, 태그 삽입은 가능하기에 /flag 에서, admin의 비밀번호를 바꾸는 <img src="/change_password?pw=1234"> 를 입력해줍니다.

  6. /login 에서 id는 admin, password 는 위에서 설정한 1234 를 입력해 로그인에 성공하였습니다.

  7. 정상적으로 admin에 로그인 해 성공적으로 플래그를 획득할 수 있었습니다.


배운점

  • CSRF 공격을 실습을 통해 배워볼 수 있었습니다.
  • script 로 접속이 불가능한 상황에 우회할 수 있는 방법인 <img> 태그에 대해 알 수 있었습니다.
  • 필터링된 키워드(script, on, frame)가 있다고 하더라도, HTML의 다양한 태그와 속성을 이용해 우회가 가능하다는 점을 배웠습니다. 실제 공격에서는 단순한 필터링보다 더 정교한 방어가 필요하다는 걸 느꼈습니다.
  • 세션을 고정해놨기에 공격이 가능했던 문제입니다. 따라서 세션을 어떻게 관리하고 생성함에 따라 공격에 취약해질 수 있음을 배웠습니다.

Summary (English)

  • The challenge uses CSRF to change the admin's password and access the flag.
  • When visiting /flag, the server creates a new session linked to the admin.
  • Any request made via this session has admin privileges.
  • The /change_password route uses the sessionid cookie to determine the user.
  • Direct <script> tags are blocked, but HTML tags like <img> are allowed.
  • A crafted <img src="/change_password?pw=1234"> triggers a password change.
  • After that, logging in as admin with 1234 reveals the flag.
  • Key Learnings
    • CSRF can work through harmless-looking HTML elements.
    • Keyword filtering is not enough to stop real attacks.
    • Session fixation enabled privilege abuse.
    • Strong session handling and CSRF protection are essential.
profile
CTF 풀이 및 실습 중심 학습을 기록합니다.

0개의 댓글