Oh! JUN

[개인 공부] JSESSIONID와 CSRF 토큰 본문

웹 해킹/Request Forgeries(CSRF)

[개인 공부] JSESSIONID와 CSRF 토큰

Kwon Oh! JUN 2024. 1. 17. 16:26

1. JSESSIONID와 CSRF 토큰을 활용해서 로그인 시도해보기

로그인하면 Cookie를 전송하는 것 처럼 보이지만, 사실 이전에 로그아웃 하고 서버에서 무효화 시킨 세션이고 웹 브라우저에서는 바로 삭제되지 않을 수 있습니다. 그래서 위에 burp suite 처럼 쿠키가 요청되는것 처럼 보이는거고 서버에서 세션을 생성하고 세션에 대한 고유 식별자를 JSESSIONID 쿠키에 저장하여 브라우저로 전송하게 됩니다. 


로그인을 성공하게 되면 서버한테 새로 응답받은 JSESSIONID를 확인할 수 있습니다. 


그래서 기존에 사용하는 크롬 웹 브라우저 말고 다른 웹 브라우저로 JSESSIONID를 사용해서 로그인을 시도해보자 했지만, CSRF 토큰도 사용중이어서 토큰을 알아보자 시도해봤습니다.


XSS 취약점을 활용해서 사용자가 사용중인 CSRF 토큰을 알고 싶었는데 사실 CSRF는 서버에 요청할때마다 난수화된 상태로 계속 바뀝니다. 


정리하면,  JSESSIONID와 CSRF 토큰을 사용해서 로그인하려면 JSESSIONID는 XSS 공격으로 사용자의 값을 알아낸다고 해도 CSRF 토큰은 요청할때마다 변경되기 때문에 사실상 어려울거 같습니다. 일반적으로 사용자가 웹 페이지를 로드할 때, 서버는 새로운 또는 기존의 CSRF 토큰을 페이지에 포함시키는데, 이때 토큰을 알려면 요청하는 방법말고 웹 브라우저를 조작하지 않는 이상 알아내기는 거의 불가능하다고 합니다.


2. 공부하면서 찾아본 정보

1. 로그아웃 한 상태에서도 JSESSIONID이 존재하던데 왜 그런거야?
JSESSIONID는 사용자의 세션을 식별하는 쿠키입니다. 사용자가 로그인하면 서버는 세션을 생성하고, 이 세션에 대한 고유한 식별자를 JSESSIONID 쿠키에 저장하여 브라우저로 전송합니다.


사용자가 로그아웃하면, 서버는 해당 세션을 무효화(, 로그아웃 상태로 만듭니다)하지만, JSESSIONID 쿠키 자체는 브라우저에서 바로 삭제되지 않을 수 있습니다. 쿠키의 수명은 서버에서 설정되며, 일부 웹 애플리케이션에서는 로그아웃 후에도 JSESSIONID 쿠키를 삭제하지 않고, 다음 로그인 시에 새로운 세션 식별자로 업데이트합니다.


따라서 로그아웃 한 상태에서도 JSESSIONID 쿠키가 존재하는 것은 정상적인 현상일 수 있습니다. 그러나 이 상태에서 JSESSIONID 쿠키를 이용하여 사용자를 식별하거나, 사용자의 로그인 상태를 유지하려는 시도는 효과가 없습니다. 왜냐하면 로그아웃 시점에서 서버는 해당 세션을 무효화했기 때문입니다.
2. "서버는 요청을 받을때 CSRF 토큰을 확인해 토큰이 없거나 일치하지 않으면 요청을 거부합니다." 서버에 요청을 보낼 때 CSRF 토큰을 매번 랜덤화 난수화해서 보내는데 그러면 서버는 어떻게 일치하는지 확인할 수 있는거야?
CSRF(Cross-Site Request Forgery) 토큰은 사용자의 요청이 신뢰할 수 있는 원본에서 발생했는지 확인하는 데 사용되는 보안 수단입니다. 이는 웹 애플리케이션에서 중요한 요청(: 비밀번호 변경, 이메일 주소 변경 등)을 처리할 때 사용됩니다.


CSRF 토큰은 서버가 생성하여 웹 페이지에 포함시킵니다. 사용자가 요청을 보낼 때, 이 토큰이 요청과 함께 서버로 전송됩니다. 서버는 요청을 받을 때 이 토큰을 확인하고, 토큰이 없거나 일치하지 않으면 요청을 거부합니다.


토큰이 랜덤화되어 생성되더라도, 서버는 세션 또는 사용자 별로 이 토큰 값을 관리하고 있습니다. 따라서 사용자로부터 요청이 들어올 때마다 서버는 전송받은 토큰 값을 자신이 보관하고 있는 토큰 값과 비교하여 일치하는지 확인할 수 있습니다.


, 서버는 사용자의 세션 또는 사용자 별로 CSRF 토큰 값을 생성하고 관리하며, 이 토큰은 사용자에게 제공되어 요청과 함께 전송됩니다. 이렇게 해서 서버는 CSRF 토큰을 통해 요청이 신뢰할 수 있는 원본에서 발생했는지 확인할 수 있습니다.
2-1. 서버가 세션 또는 사용자 별로 토큰 값을 가지고 있다고 했는데 그러면 서버가 이미 소유하고 있는 토큰이 정해져 있는거야?
서버가 CSRF 토큰을 관리하는 방식은 애플리케이션마다 다르지만, 일반적으로 서버는 각 세션 또는 사용자에 대해 유일한 CSRF 토큰을 생성하고 관리합니다. 이 토큰은 세션 또는 사용자가 활성 상태인 동안에만 유효합니다.


사용자가 웹 페이지를 로드할 때, 서버는 새로운 또는 기존의 CSRF 토큰을 페이지에 포함시킵니다. 사용자가 폼을 제출하거나 AJAX 요청을 보낼 때, 이 토큰 값이 요청과 함께 서버로 전송됩니다. 서버는 이 토큰 값을 자신이 보관하고 있는 토큰 값과 비교하여 일치하는지 확인합니다.


이렇게 하면, 공격자가 사용자의 세션을 가로채서 악의적인 요청을 보내더라도, 공격자는 CSRF 토큰 값을 알 수 없기 때문에 서버는 이런 요청을 거부할 수 있습니다.


따라서, 서버가 "소유하고 있는" 토큰이라는 표현보다는, 서버가 각 세션 또는 사용자에 대해 "관리하고 있는" 토큰이라고 이해하는 것이 더 정확합니다. 이 토큰은 일반적으로 랜덤하게 생성되므로, 서버나 사용자가 미리 알 수 있는 값이 아닙니다.
2-2. CSRF 토큰은 요청 할때마다 랜덤 값으로 보내니까 결국에 공격자는 토큰을 알 수 있는 방법은 없지 않을까?
, 맞습니다. CSRF 토큰은 보통 각 요청마다 또는 세션마다 랜덤하게 생성되므로, 외부의 공격자가 이 값을 예측하거나 알아내는 것은 매우 어렵습니다.


이 토큰은 사용자의 브라우저에 저장되고, 사용자가 폼을 제출하거나 서버에 요청을 보낼 때 함께 전송됩니다. 이런 방식 때문에, 공격자가 사용자의 브라우저를 직접 조작하지 않는 한 CSRF 토큰 값을 알아내기는 거의 불가능합니다.


그래서 CSRF 공격을 방어하는 가장 효과적인 방법 중 하나가 바로 이 CSRF 토큰을 사용하는 것입니다. 이를 통해 서버는 사용자의 요청이 신뢰할 수 있는지 확인하고, 악의적인 요청을 거부할 수 있습니다.