본문 바로가기
INCOGNITO 2023

[WebSocket] CSWSH 취약점 방어 기법- Oauth 인증 프레임워크를 통한 AccessToken 인증

by hezin* 2024. 2. 18.

 

 

CSWSH 공격으로부터 웹 애플리케이션을 보호하기 위해서는 

1. HandShake 과정에서 Origin 헤더를 확인

2. 서버의 Handshake 요청시 CSRF 토큰처럼 세션별 임의의 토큰을 사용하여 서버를 확인

 등의 방법이 있지만, 이러한 방법들은 사용 효율성이 떨어지거나 불필요한 토큰 생성 프로세스를 증가시키는 문제점이 존재한다.

 

이러한 문제점을 보완하는 방법으로는 Oauth 2.0의 개념을 도입하여 다른 도메인과의 접근을 허용하며 임의의 토큰을 사용하는 방법을 구체화하여 Oauth 인증 프레임워크를 통한 AccessToken 인증을 하는 방법이 있다.

이 인증 방법은 최초에 한번 생성된 토큰으로 사용자를 인증하기 때문에 로그아웃을 하지 않는 이상 토큰 생성 프로세스는 실행되지 않아서 CSRF 토큰의 단점인 토큰 생성 프로세스를 증가시키는 문제점이 발생하지 않는다.

 


 

OAuth (Open Authorization)

: 사용자들이 비밀번호를 제공하지 않고 다른 웹 사이트 상의 자신들의 정보에 대해 웹사이트나 애플리케이션의 접근 권한을 부여할 수 있는 공통적인 수단으로서 사용되는, 접근 위임을 위한 개방형 표준이다.

웹소켓 연결에 OAuth 2.0를 이용하여 인증 및 권한 부여를 수행하게 되면 이 인증을 공유하는 애플리케이션끼리의 별도의 인증이 필요없게 되어, 여러 애플리케이션을 통합하여 사용하는 것이 가능하게 된다.

 

 

 

이 때, OAuth 를 이용하여 로그인 전용 서버를 따로 두고, 여러 어플리케이션에서 로그인을 처리하지 않고 로그인 전용 서버에 역할을 위임하여 처리하고자 한다. 

 

웹소켓 연결에서 OAuth 2.0 프로토콜을 사용하여 인증 및 권한 부여를 수행하는 방식은 다음과 같다.

1. request authorized page

: 사용자가 App에 연결 요청을 하고 App은 사용자에게 인증 및 권한 부여가 필요하다는 응답을 보낸다.

2. [302] location=/login_server/oauth/authorize

: App은 사용자를 OAuth 2.0 인증 서버로 리다이렉트한다. 리다이렉트 코드는 302이다.

3. request code(/oauth/authorize)

: 사용자는 인증 서버에 로그인 페이지를 요청한다.

4. login page

:사용자는 로그인 페이지에서 로그인 정보를 입력한다.

5. login

: 사용자는 로그인 정보를 인증 서버에 보낸다.

6. user consent page

: 인증 서버는 사용자에게 App에 대한 권한 허가 여부를 묻는 동의 페이지를 표시한다.

7.approve authoriztion

: 사용자가 권한 허가를 승인한다.

8. [302] location=/app/handle_code?code=L93Jus

: 인증 서버는 사용자에게 인증 코드(code=L93Jus)를 포함하여 App으로 리다이렉트한다.

9./handle_code?code=L93Jus

:App은 인증 코드를 받아 인증 서버에 액세스 토큰을 요청하기 위해 준비한다.

10.request access_token(/oauth/token?code=L93Jus)

: App은 인증 코드를 포함하여 인증 서버에 액세스 토큰을 요청한다.

11. grant access_token

: 인증 서버는 인증 코드를 검증하고 유효하면 액세스 토큰을 App에 제공한다.

12. request information of user (/userinfo)

: App은 사용자 정보를 얻기 위해 인증 서버에 사용자 정보 요청을 보낸다.

13. response userinfo(username,email,etc..)

:인증 서버는 액세스 토큰을 검증하고 유효하면 사용자 정보(이름, 이메일 등)를 App에 제공한다.

14.save userinfo in session

: App은 사용자 정보를 세션에 저장한다.

15. resonse page

: App은 사용자에게 연결 허가 응답 페이지를 보내고 사용자는 App 연결을 통해 서버와 실시간 통신을 수행할 수 있다.

 


 

Access Token의 암호화

Access Token은 OAuth 2.0에서 사용자 인증 후 리소스에 접근하기 위해서 사용된다. Access Token은 중요한 정보이므로 안전하게 보관해야하기 때문에, 암호화하여 저장하고 HTTPS 같은 보안 프로토콜을 사용하여 전송해야한다.

 

Access Token의 세션 ID 하이재킹을 방지하기 위해서 토큰을 발급받고, 이를 SHA 해시 함수를 이용해 다시 한번 유효성 검사를 하는 방식을 사용할 수 있다. Access Token을 세션에 저장하고 SHA256 해시 함수로 암호화해서 클라이언트에게  넘겨주면 현재 접근한 URL에 포함되 있는 Access Token을 SHA256 해시 함수로 암호화한 값과 비교하여 CSRF 여부를 판단하게 된다.

 

from hashlib import sha256
session_access_token = "your_access_token"
request_access_token = request.args.get("access_token")
if sha256(session_access_token.encode()).hexdigest() != sha256(request_access_token.encode()).hexdigest():
    # CSRF 공격 의심
    return """
        <script>
            alert("Session Hijacking Detected!! ");
        </script>
    """
# ... 요청 처리 ...

 

Access Token의 해시함수 비교 로직을 살펴보면 세션에 저장된 Access Token을 session_access_token 변수에 저장하고, 현재 접근한 URL에서 access_token 쿼리 파라미터 값을 추출하여 request_access_token 변수에 저장한다.

두 Access Token을 SHA256 해시 함수로 암호화하고 값을 비교한다. 만약 값이 일치하지 않으면 CSRF 공격을 의심하여alert 메세지를 띄운다.

 

Access Token은 다양한 형식으로 발급될 수 있으며,  JWT 토큰도 사용자 인증 및 권한 부여에 OAuth 2.0과 함께 사용될 수 있다.

 

 

JWT Token

: JSON 형식으로 구성된 토큰으로 사용자 정보, 권한 정보, 서명 정보 등을 포함한다.

Base64 인코딩되어 발급되며, 디지털 서명으로 검증되어서 위조 또는 변조가 어렵다.

JWT Token은 만료기간을 포함하기 때문에 만료가 되면 새로운 토큰을 발급해야 한다.

 

JWT Token을 OAuth 2.0 Access Token 으로 사용할 때 아래의 방식으로 처리된다,

 

  • Authorization 서버:
  1. 사용자 인증 및 권한 부여 후 JWT 토큰을 생성한다.
  2. JWT 토큰에 사용자 정보, 권한 정보, 서명 정보 등을 포함한다.
  3. Access Token으로 JWT 토큰을 발급한다.
  • Resource 서버:
  1. 요청 헤더에서 JWT 토큰을 받고 JWT 토큰의 서명을 검증한다.
  2. JWT 토큰의 정보를 사용하여 사용자 정보 및 권한을 확인한다.
  3. 토큰이 유효하고 사용자에게 권한이 있는 경우 요청을 처리한다.