WebSocket은 네트워크 처리량을 개선하고, 대기 시간 감소, 서버 부담을 줄일 수 있는 장점이 있지만 공격자가 사용자 데이터를 삭제, 수정하고 악의적으로 데이터를 가로채고 훔치는 등의 많은 보안 위협을 초래할 수 있다.
최근 몇 년 동안, 웹소켓 관련 보안 취약점이 다수 발견되었으며, 가장 일반적인 취약점으로는 CSWSH 이 있다.
CSWSH 취약점
:Cross-Site WebSocket Hijacking, 웹 소켓을 통해 웹 애플리케이션의 취약점을 악용하여 공격자가 사용자의 웹 소켓 연결을 탈취하는 공격 기술
CSWSH 취약점은 다음과 같은 상황에서 발생할 수 있다.
- 인증 및 권한 부여 부재 : 웹소켓 연결이 인증 및 권한 부여 매커니즘이 없는 경우, 악의적인 사용자가 사용자의 인증 정보를 획득하지 않고도 웹소켓에 연결할 수 있다.
- CSRF 취약점 : CSRF 취약점이 존재하는 경우, 악의적인 웹 사이트가 사용자의 브라우저를 통해 웹소켓에 대한 요청을 위조할 수 있다. CSRF 취약점에는 잘못된 Origin 헤더 설정 등이 포함된다. Orgin 헤더를 잘못 설정하는 경우, 서버가 요청의 출처를 올바르게 확인할 수 없어 악의적인 요청과 정상적인 요청을 구분하지 못하고 모든 요청을 수락하게 되어 CSRF 공격이 발생할 수 있다.
- 보안 토큰 누락 : 웹소켓 연결 시에 보안 토큰이 누락되거나 제대로 구현되지 않은 경우, 악의적인 사용자가 특정 행동을 수행할 수 있다.
- 세션 관리의 부재 : 웹 소켓 연결에 대한 적절한 세션 관리가 이루어지지 않은 경우, 공격자가 세션을 탈취하거나 다른 사용자의 세션을 이용할 수 있다.
WebSocket Connection Process
먼저 클라이언트는 WebSocket API를 호출하여 연결 요청을 시작한다. 요청 주소는 'ws'로 시작하지만, 본질적으로 HTTP 요청이며, 일반적인 HTTP 요청과는 다르다.
WebSocket 연결 설정은 Connection: Upgrade, Upgrade: WebSocket, Sec-WebSocket- Key 등과 같은 몇 가지 헤더가 있는 HTTP 요청 업그레이드로 시작된다.
1. Request
Connection:Upgrade header는 Websocket 핸드셰이크를 나타내고 Sec-WebSocket-Key 필드는 핸드셰이크 확인을 위해 클라이언트가 생성한 24-bit random based64 문자 시퀀스이다.
2. Response
서버가 요청을 받으면, response 와 같이 요청 헤더를 구문 분석하고 응답한다.
응답 코드 101은 연결이 성공했고 서버가 웹소켓 프로토콜로 대체되었음을 나타낸다.
Sec-WebSocket-Accept은 Request의 Sec-WebSocket-Key 필드에 의해 생성된 새로운 문자 배열이다.
브라우저 클라이언트가 응답을 받은 후에, 서버가 프로토콜을 업그레이드한 것을 확인하고 동일한 알고리즘에 따라 Sec-WebSocket-Key 값을 계산한 다음, 반환된 Sec-WebSocket-Accept와 비교한다. 비교값이 맞다면 handshake는 성공되고, 클라이언트가 웹 소켓 프로토콜로 연결되고 연결이 설정된다. 그리고 각 클라이언트들은 서로에게 데이터를 보낼 수 있게 된다. 연결이 설정된 후에, 네트워크 오류가 발생하거나 종료 요청을 보낼 때까지 연결은 지속된다.
CSWSH 공격 과정
웹소켓 프로토콜은 handshake 단계에서 HTTP를 기반으로 하고, handshake 중 서버가 클라이언트의 신원을 인증하는 방법을 정해놓지 않는다. 따라서 서버는 일반적으로 쿠키 또는 http 기본 인증 등과 같은 HTTP 클라이언트 인증 매커니즘을 사용하는데, 이로 인해서 공격자가 악의적으로 웹 페이지 등을 이용해서 사용자의 신원으로 위장하고 서버와 웹 소켓 연결을 맺을 수 있는 문제점이 발생한다.
먼저, 사용자는 로그인하고 신뢰할 수 있는 사이트를 탐색한다. 로그인이 성공하면, 브라우저는 사용자 인증 정보를 쿠키에 저장한다. 그 후, 사용자의 각 HTTP 요청은 클라이언트 사용자의 신원을 확인하기 위해 쿠키를 자동으로 가져온다.
사용자가 웹사이트 A에서 로그아웃하지 않고 악의적인 웹 사이트를 방문할 때, 악의적인 웹사이트인 B가 페이지에서 웹사이트 A와의 웹소켓 연결을 위해서 핸드셰이크 요청을 실행하는 경우, 웹사이트 A의 쿠키는 서버가 알지 못하게 자동으로 요청 헤더에 추가된다.
따라서 악의적인 웹사이트는 사용자의 신원으로 가장하여, 서버와의 연결을 성공적으로 설정하여 서버 메시지를 훔치거나 데이터를 조작하기 위해 위조된 요청을 보낼 수 있게 된다.
이러한 CSWSH 취약점은 CSRF 취약점과 비슷하지만, CSRF 취약점이 위조된 요청만 보낼 수 있는 것과는 달리 CSWSH 취약점은 완전한 읽기/쓰기 양방향 채널을 설정하고, SOP (동일 출처 정책) 에 제한되지 않기 때문에 더 위험한 취약점으로 볼 수 있다.
하지만, CSWSH 과 CSRF의 기본적인 원칙은 비슷하기 때문에, 해결책의 핵심은 클라이언트의 신원을 확인하는 것이다.
일반적인 해결책은 다음과 같다.
- 그래픽 인증 코드 : 각 연결 요청 전에 서버에서 이미지 인증 코드가 요청된다. 이 코드는 수동으로 입력되고 클라이언트의 신원을 확인하기 위한 요청에 포함된다. 그래픽 인증 코드 방식은 높은 보안성을 가지지만, 매번 인증코드를 수동으로 입력해야하며 사용자가 진행하는 검사가 힘들다는 단점이 있다. 그래픽 인증 코드를 사용하여, 사용자의 동작을 요구하고 이를 통해 악의적인 요청이 자동으로 전송되는 것을 방지할 수 있다. 예를 들어, 사용자가 특정 동작을 수행해야만 애플리케이션에서 요청을 처리하도록 하는 식으로 동작한다. 이렇게 하면 CSRF / CSWSH 공격을 시도하는 공격자가 사용자의 동작을 모방하는 것이 어려워진다.
- Origin 확인 : Request의 Origin 필드는 요청의 소스 주소를 나타낸다. 서버는 악의적인 요청을 피하기 위해 요청 헤더의 Origin 필드를 확인할 수 있다. Orgin 헤더를 확인하여 요청이 예상되는 출처에서 온 것인지를 검증하여 공격을 방지할 수 있다. 하지만 Origin 필드는 브라우저에서만 제공되고, 만약 클라이언트일 경우에는 Origin 필드는 비어있어서 공격자가 Origin 헤더 정보를 조작할 수 있기 때문에 Origin 확인만으로 모든 공격을 방어할 수는 없다.
- Random Token : Random Token은 서버에서 생성된 무작위 배열이며, 로그인이 완료된 후에 클라이언트에게 발행된다. 클라이언트는 각 요청과 함께 토큰을 가져오고, 서버는 요청자의 신원을 결정하기 위해 값을 확인하기 위해서 interceptor를 설정한다. Random Token 방식을 잘 작동하지만, 토큰의 보안을 보장하기 어렵기 때문에 토큰 유출과 재전송 공격의 위험성도 있다.
CSRF 공격을 방어하기 위한 방법으로 Randomized parameter names 방식이 사용될 수 있다.
- Randomized parameter names : 애플리케이션에서 사용되는 요청 매개변수 이름을 무작위로 생성하여 매 요청마다 다른 매개변수 이름을 사용하는 방법이다.
일반적으로 CSRF 공격은 공격자가 악의적인 웹 페이지를 통해 사용자의 브라우저에서 특정 요청을 실행시키는 것을 말하는데 ,이 때 공격자는 악성 요청을 위해 알려진 매개변수 이름을 사용할 수 있다.
예를 들어, 공격자가 이전에 관찰한 것과 동일한 매개변수 이름을 사용하여 POST 요청을 실행시킬 수 있는데 Randomized parameter names 방법은 각 요청마다 매개 변수 이름을 무작위로 생성하기 때문에, 공격자가 유효한 요청을 실행시키기 위한 정확한 매개변수 이름을 알아내는 것을 어렵게 한다.
하지만 Randomized parameter names 방법은 request parameter를 위조하는 것을 방지하지만, request parameter를 사용자가 동적으로 생성하는 경우에는 일관성의 부재 / 사용자 경험 저하 등의 문제가 발생한다.
그리고 웹소켓의 경우에는 단일 연결을 통해 지속적인 양방향 통신이 이루어지기 때문에 Randomized parameter names 와 무작위 토큰 (CSRF 토큰) 사이에 상대적으로 큰 차이가 없고, CSWSH 공격은 웹소켓 연결을 통해 이루어져 HTTP요청과는 다른 형태의 공격이기 때문에 Randomized parameter names 방법은 CSWSH 취약점을 방어하는데 적합하지 않다.
CSWSH 취약점을 보완하기 위해서, 하이브리드 암호화를 기반으로한 일회성 무작위 토큰 체계를 사용할 수 있다.
이 방법은 일회성 토큰을 사용해서 클라이언트의 신원을 확인할 수 있으며, 토큰 유출과 재전송 공격을 성공적으로 방지할 수 있다.
하이브리드 암호화
: 비밀 키(개인 키) 암호화와 공개 키 암호화를 혼합한 응용 암호화
암호화 기술은 일반적으로 대칭 암호화 / 비대칭 암호화로 나뉜다.
- 대칭 암호화 : 키를 사용하여 일반 텍스트를 암호 텍스트로 암호화하는 것 , 암호 텍스트는 일반 텍스트를 얻기 위해 동일한 키로만 해독할 수 있다.
- 비대칭 암호화: 암호화와 복호화에 서로 다른 키를 사용하는 암호화 기술, 공개키와 개인키라는 두가지 키가 사용된다
1. 공개키 : 누구나 알 수 있는 키, 메세지를 암호화하는데 사용된다. 암호화된 메세지는 해당 공개키로만 복호화할 수 있다.
2. 개인키 : 오직 해당 키를 소유하고 있는 사람만이 알 수 있는 키로 , 암호화된 메세지를 복호화하는데 사용된다.
대칭 암호화와 비대칭 암호화는 각각 단점이 있기 때문에, 둘을 함께 사용하는 하이브리드 암호화가 사용된다.
하이브리드 암호화는 비대칭 암호화를 이용하여 대칭 암호화 키를 전송한 다음, 대칭 암호화를 사용하여 무작위 토큰을 전송하는 방법이다.
이 방법은 클라이언트와 서버가 동일한 키를 가지고 있다는 것을 보장하고, 토큰이 손상되더라도 공격자는 암호화 키를 알지 못하므로 사용자 요청을 위조할 수 없게 된다.
웹소켓 연결은 HTTP Handshake를 기반으로 완료된다.
제시한 하이브리드 암호화를 기반으로한 일회성 무작위 토큰 체계 방법은 handshake 단계를 여섯 개의 handshake 단계로 변경하여 진행한다.
1~4 까지의 handshake는 로그인하고 키를 주고받는데 사용되고, 5,6 번의 handshake는 웹소켓 연결을 설정하고 새로운 토큰을 반환하는데 사용된다.
- 클라이언트가 서버에게 공개 키를 요청한다.
- 서버는 공개 키 정보를 클라이언트에게 전달한다.
- 클라이언트는 무작위로 대칭을 생성하고, 서버의 공개키를 이용하여 키와 사용자 로그인 정보를 암호화하여 서버로 보낸다.
- 서버는 개인 키를 이용하여 암호를 해독한다. 클라이언트 키와 로그인 정보를 얻은 후에, 로그인 정보가 일치하면 토큰 문자열이 무작위로 생성되고 서버는 토큰과 클라이언트 키를 저장한다. 마지막으로 무작위 토큰과 확인 정보가 클라이언트에게 반환된다.
- 클라이언트가 연결을 설정하면, 협상키로 토큰을 암호화하고 웹소켓 연결 요청과 함께 서버로 보낸다.
- 서버는 협상 키를 이용하여 토큰 값을 해독하고, 신원 정보를 확인하여 연결을 수락할지를 결정한다. 신원 정보가 확인되면, 이전 토큰은 동시에 파괴되고 새로운 토큰이 생성되어 클라이언트에게 반환된다.
이 방법은 로그인 정보와 클라이언트 키의 보안을 보장하기 위해서 공개키 암호화를 사용한다.
다음에 사용된 협상키는 토큰을 암호화하는데 사용되었기 때문에, 토큰이 유출되더라도 서버는 키 암호화 없이 토큰 정보를 확인할 수 없어 토큰 유출 위험을 방지할 수 있다.
그리고 검증이 끝난 후, 이전 토큰을 파괴하고 새로운 토큰을 발행하기 때문에 재전송 공격에 대비할 수 있다.
CSWSH 공격은 악의적인 공격자가 웹소켓 연결을 통해 사용자의 세션을 탈취하거나 조작하는 공격이다. 웹 소켓을 통해 클라이언트와 서버 간의 통신이 이루어지는 환경에서 발생한다.
제시한 하이브리드 암호화와 일회성 무작위 토큰 방법을 통해 토큰의 고유성 , 토큰 암호화, 토큰 검증을 이용하여 CSWSH 공격에 대응할 수 있다.
[논문]
'INCOGNITO 2023' 카테고리의 다른 글
[WebSocket] HTTPS / SSL / TLS (0) | 2024.02.26 |
---|---|
[WebSocket] CSWSH 취약점 방어 기법- Oauth 인증 프레임워크를 통한 AccessToken 인증 (0) | 2024.02.18 |
[WebSocket] WebSocket 취약점 확인 스크립트 (0) | 2024.02.11 |
[WebSocket] CORS 취약점 분석 (0) | 2024.02.11 |
[WebSocket] XSS 취약점과 WebSocket 핸드셰이크 조작 (0) | 2024.02.04 |