Q> Websocket 개발시 보안고려사항에 대한 문의

웹으로 간단한 채팅기능을 넣으려고 합니다. 보안적으로 고려해야 햐는 사항은 무엇이 있나요?

A>

<> Websocket 구현시 고려해야 하는 보안사항

1. Authentication mechanism
비인가자의 Websocket접근을 방지하기 위하여 적절한 인증메커니즘을 적용한다.

2. Access Control
인가된 사용자 또는 디바이스만 접근할 수 있도록 적절한 방법으로 접근통제를 적용한다.

3. Session Management
Session은 비인가된 접근을 방지하기 위하여 적절하게 관리되어야 한다. 특히, Websocket의 disconnections, timeouts, session검증 등에 대한 적절한 처리가 적용한다.

4. Transaction Encryption
Client와 Server간 송수신되는 데이터의 변조와 도청을 방지하기 위하여 HTTPS/TLS를 이용한 송수신구간 암호화를 적용한다.

5. CSWSH(Cross-site Websocket Hijacking)
공격자가 사용자로 하여금 Websocket request를 악의적인 서버로 보내도록하여 데이터 유출공격을 할 수 있으므로 이를 방지하기 위하여 SOP(Same-Origin Policy) 및 Origin header 유효성 검사를 하도록 한다.

6. Input validation
입력값 검증은 어느 어플리케이션에서든 중요한다. 특히 Websocket은 stateful protocol이기 때문에 악의적인 입력값이 수신되지 않도록 적절한 방법으로 검증하는 것이 중요하다.

7. Data Protection
중요 데이터를 사용하는 경우, Websocket의 송신측과 수신측 모두 데이터 암호화를 적용한다.

8. DDoS
Websocket은 DDoS공격 대상이 되어 서버 사용에 장애를 줄수 있으므로 이를 방지하기 위하여 웹서버에서 rate-limiting을 설정하거나 적절한 메시지 큐 메커니즘을 적용한다.

9. Logging and monitoring
보안사고 탐지와 대응을 위해 로깅과 모니터링을 적용한다.

10. Updates
운영체제 뿐만아니라 Websocket 라이브러리, 연동된 S/W 들이 보안취약점에 노출되지 않도록 최신 버전으로 에 사용되는 S/W를 정기적 업데이트를 한다.

<> 취약점 진단 Python script

위의 보안고려사항 중에서 SSL certification, SOP의 Origin Header, Sec-Websocket-Accept header의 유효성을 검증하여 결과를 출력하는 간단한 진단용 Python script는 아래와 같다.

import socket
import ssl
import traceback
import sys

def check_websocket_vulnerability(host, port, use_ssl=True):
    try:
        s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        if use_ssl:
            context = ssl.create_default_context()
            context.check_hostname = False
            context.verify_mode = ssl.CERT_NONE
            s = context.wrap_socket(s, server_hostname=host)
        s.connect((host, port))

        # Send WebSocket upgrade request
        s.send(b"GET / HTTP/1.1\r\n"
               b"Host: " + host.encode() + b"\r\n"
               b"Origin: https://example.com\r\n"
               b"Upgrade: websocket\r\n"
               b"Connection: Upgrade\r\n"
               b"Sec-WebSocket-Key: x3JJHMbDL1EzLkh9GBhXDw==\r\n"
               b"Sec-WebSocket-Version: 13\r\n"
               b"\r\n")

        # Check response
        response = s.recv(4096).decode()
        if "101 Switching Protocols" not in response:
            raise Exception("Invalid response")
        if "Sec-WebSocket-Accept" not in response:
            raise Exception("Missing Sec-WebSocket-Accept header")

        print("WebSocket is not vulnerable")
    except Exception as e:
        print(f"Error: {e}")
        print("WebSocket may be vulnerable")
        traceback.print_exc()

if __name__ == '__main__':
    if len(sys.argv) != 3:
        print("Usage: python websocket_test.py <host> <port>")
        sys.exit(1)
    host = sys.argv[1]
    port = int(sys.argv[2])
    check_websocket_vulnerability(host, port)