본문 바로가기
INCOGNITO 2023

[WebSocket] XSS 취약점과 WebSocket 핸드셰이크 조작

by hezin* 2024. 2. 4.

 

XSS 취약점 공격

: 웹사이트에 악성 스크립트를 주입하는 행위, 사용자로부터 입력받은 데이터를 적절하게 검증 또는 이스케이프하지 않고 출력할 때 발생하는 취약점이다.

 

공격 유형

1. Stored XSS

: 악의적인 스크립트가 서버에 저장되어, 해당 스크립트가 서버에서 제공하는 페이지에 포함되어 있는 경우이다.

일반적으로 게시글, 댓글, 사용자 프로필 등에 악성 스크립트가 저장되고, 해당 페이지를 방문하는 다른 사용자들에게 스크립트가 실행되게 한다.

2. Reflected XSS (반사형 XSS):

악의적인 스크립트가 피해자로 하여금 특정한 링크를 클릭하거나 악의적인 URL을 요청하도록 유도하여, 해당 스크립트가 서버로 전달되어 실행되는 경우이다. 서버에서 사용자에게 받은 입력을 적절하게 처리하지 않고 그대로 동적으로 생성된 페이지에 반영할 때 발생할 수 있다.

3.DOM-based XSS (DOM 기반 XSS):

클라이언트 측 스크립트에서 DOM(Document Object Model) 조작을 통해 발생하는 XSS이다. 사용자의 입력이 동적으로 DOM을 조작하는 스크립트에 의해 실행될 때 발생한다.

 

XSS 공격을 통해 공격자는 사용자 정보 탈취, 사용자 동작 조작, 웹페이지 변조 등의 악의적인 행위가 가능하다.

 


WebSocket 핸드셰이크 조작

:WebSocket은 HTTP 기반의 프로토콜로 시작하고 핸드셰이크를 통해 연결을 설정한다. 핸드셰이크는 클라이언트가 서버에게 연결을 요청하고 서버가 이를 수락하여 양쪽 간의 통신을 시작하는 과정이다.

Burp proxy를 사용하여 WebSocket 핸드셰이크를 확인하고 조작한다. X-Forwared-For 헤더를 추가하여 IP주소를 스푸핑하여 핸드셰이크 요청을 변경하고, 이를 통해 웹 서버는 사용자가 원하는 IP주소로 요청을 받아들인다.

-> 그리고 XSS취약점을 이용하여 난독처리된 XSS 페이로드를 WebSocket 메시지에 삽입하여 웹 어플리케이션이 이를 실행하도록 한다.

 


 

X-Forwared-For 헤더 추가 후  IP주소 스푸핑

: 웹 서버에서 클라이언트의 실제 IP 주소를 확인하는 데 사용되는 헤더를 조작하여 공격자가 웹 서버에 대한 요청을 원하는 대로 변조하는 행위이다.

 

1. 'X-Forwared-For' 헤더

: 'X-Forwared-For' 헤더 는 일반적으로 프록시 서버를 통과하는 요청에서 사용되고 클라이언트의 원본 IP주소를 기록하는데 사용된다. 예를 들어, 클라이언트 A에서의 요청이 프록시 B를 통과하면 'X-Forwarded-For:A, B' 과 같은 형태로 헤더값에 추가될 수 있다.

 

2. IP주소 스푸핑

:IP주소 스푸핑이란 공격자가 자신이 원하는 IP주소를 특정 헤더에 삽입하여, 웹 서버가 해당 IP주소를 신뢰하고 클라이언트로 간주하게 만드는 행위이다. X-Forwared-For 헤더에 원하는 IP주소를 추가해서 서버로 전송하면 , 서버는 이 값을 신뢰하여 해당 주소를 클라이언트로 간주한다.

X-Forwared-For 헤더를 조작하여 특정 IP주소를 추가하는 경우, 그 IP주소가 이전에 차단되었던 주소여도 접근이 가능하게 된다. 왜냐하면 서버는 클라이언트의 IP주소로서 'X-Forwared-For' 헤더에 포함된 값을 사용하기 때문이다.

 

3.WebSocket 핸드셰이크 요청 조작 , 편집

:Burp Proxy와 같은 도구를 사용하여 요청을 가로채서 해당 요청을 편집한다.

 

-> 이렇게 함으로써 공격자는 서버에 대한 요청에서 자신의 IP주소를 감추고, 서버는 공격자가 설정한 IP 주소를 실제 클라이언트로 인식하게 된다. 이렇게 되면 보안 측면에서 매우 위험하고, 서버 측에서 신뢰할 수 있는 방법으로 클라이언트의 IP주소를 확인하는 것이 중요하다.

 


Lab: Manipulating the WebSocket handshake to exploit vulnerabilities

WebSocket 메세지를 이용해서 브라우저에서 팝업을 트리거해야한다.

 

Lab에서 WebSocket을 활용한 실시간 채팅을 접근해야 하기 때문에 live chat 기능에 들어간다.

채팅을 시작한다.

채팅을 보내고 WebSocket history를 확인해보녀 채팅 메세지가 WebSocket 메세지를 통해 전송되었음을 확인할 수 있다.

 

해당 메세지를 리피터로 보내고 XSS payload가 포함된 메세지로 편집한 후 다시 send한다.

 

<img src=1 onerror='alert(1)'>

:이미지가 로드될 때 이미지 소스가 잘못되거나, 사용할 수 없는 경우에 (onerror 이벤트가 트리거된 경우) , 내장된 alert(1)이 실행되는 코드이다. 

 

편집한 메세지를 보내고 난 뒤 , Websocket history를 확인해보면 공격이 감지되었다고 에러가 발생한 것을 확인할 수 있다.

그리고 다시 채팅 창에 들어가보면 접속했던 IP주소가 블랙리스트 처리가 되어 접속이 불가한 것을 확인할 수 있다.

공격이 차다되고 WebSocket 연결이 종료되었기 때문에 Reconnect를 눌러 다시 Websocket 연결을 설정한다.

 

이 때 X-Forwarded-For: 1.1.1.1 을 추가한다.

공격자가 X-Forwarded-For: 1.1.1.1을 추가하면, 서버는 해당 헤더를 신뢰하고 요청한 클라이언트의 IP 주소로서 1.1.1.1을 사용한다. 이로써 공격자는 자신의 실제 IP 주소를 감추고, 서버는 공격자가 조작한 IP 주소를 클라이언트로 간주한다.

다시 채팅 창에 접속하여 intercept한 메세지마다 X-Forwared-For: 1.1.1.1 을 추가하여 헤더에 포함된 1.1.1.1의 주소를 클라이언트 ip주소로 인식하게 한다.

그리고 다시 메세지를 리피터로 보내 메세지를 편집한다. 이 때 alert창을 트리거하면 문제가 해결된다. alert 창을 띄우려면 xss 페이로드가 포함된 WebSocket 메세지를 보내야한다.

하지만, 앞서 보냈던 XSS 페이로드가 block된 것을 보면, 기본적인 방어 장치가 되어있기 때문에 XSS 페이로드를 난독처리하여 보내야한다.

 

* 난독화 방법

1. 대소문자 혼합 / 역순 / 랜덤

:함수 이름, 변수 이름 등을 대소문자를 혼합하여 작성한다. 예를 들어, aLeRt 대신에 aLeRt와 같은 식으로 사용하거나 단어나 문자열을 대소문자를 역순, 랜덤으로 나열한다.

2. Base64 인코딩

: 코드를 Base64로 인코딩하여 읽기 어렵게 만든다. 실행 시에 디코딩하여 사용된다.

3.JavaScript 함수 사용

: eval(), String.fromCharCode(), String.fromCharCode.apply(), String.fromCharCode.call()과 같은 함수를 이용하여 문자열을 동적으로 생성하거나 실행한다.

4. 함수 분할:

코드를 작은 조각으로 나누어 여러 함수로 나누고, 실행 시에 조합하여 실행하도록 하는 방법도 사용될 수 있습니다. 이는 코드를 더 어렵게 읽게 만듭니다.

5. 잡다한 문자 및 공백 추가:

코드에 잡다한 문자나 공백을 추가하여 코드를 읽기 어렵게 만들 수 있습니다.

 

해당 메세지를 보내고 다시 채팅페이지에 접속하면 문제가 해결된 것을 확인할 수 있다.


 

WebSocket에서의 XSS 공격이 가능한 이유는 주로 사용자 입력이 적절하게 처리되지 않을 때 발생한다. 

WebSocket 기반의 애플리케이션에서는 메시지가 클라이언트와 서버 간에 실시간 양방향 통신으로 전송되기 때문에 안전한 처리가 중요하다.

 

방어 방법

1. 데이터 이스케이핑

: 클라이언트로부터 받은 메세지를 출력할 때, 특수문자를 이스케이핑하여 적절하게 처리하여 악의적인 스크립트가 실행되지 않도록 방지한다.

 

2. Input Valdation

: 서버에서 클라이언트로 전달되는 메세지의 입력을 검증해야한다. 유효하지 않은 메세지를 거부하고 특수한 경우 특수 문자를 이스케이핑한다.

 

3. Content Securtiy Policy

: 웹 페이지에 Content Security Policy를 적용하여 허용된 소스에서만 스크립트 실행이 허용되도록 한다.

 

4. Secure WebSocket Connection

: TLS/SSL을 통해 WebSocket 연결을 암호화하여 중간자 공격을 방지한다.