[Playbook] WebSocket 진단 Cheat Sheet

목차


이 문서는 WebSocket 진단 중 어느 지점을 조작할지 정하고 다음 테스트를 고르기 위한 빠른 참고서다. WebSocket을 통해 드러나는 개별 취약점의 페이로드 문법은 각 주제의 Playbook으로, 상세 풀이는 Write-up으로 연결한다.

승인된 테스트 환경과 실습에서만 사용한다. WebSocket 메시지는 다른 사용자에게 즉시 중계되는 경우가 많으므로, 처음부터 실행 페이로드를 보내지 않고 무해한 marker로 도달 지점만 확인한다. CSWSH는 연결 수립 여부까지만 확인하고, 실제 사용자 데이터를 외부로 전송하지 않는다.

30초 진단 흐름

  1. WebSockets history에서 엔드포인트, 핸드셰이크, 메시지 형식을 기록한다.
  2. 클라이언트가 값을 인코딩·검증하는지, 프록시에서 원문을 보내면 통과하는지 비교한다.
  3. 메시지가 나에게만 돌아오는지, 다른 사용자에게 중계되는지 확인한다.
  4. 핸드셰이크에 CSRF 토큰과 Origin 검증이 있는지 확인한다.
  5. 메시지, 핸드셰이크, 연결(CSWSH) 중 조작할 지점을 선택한다.
관찰 결과판단다음 단계
입력이 인코딩된 상태로 전송됨클라이언트 측 처리프록시에서 원문 전송으로 우회 확인
원문 태그가 그대로 중계·출력됨메시지 기반 XSS 가능수신 측 sink와 Trigger 확인
메시지가 조회·검색 결과에 반영됨서버 측 입력 취약점 가능SQL Injection 등 Probe 적용
특정 메시지만 오류 응답메시지 단위 필터문자·대소문자·인코딩 변형
오류 후 재연결까지 차단됨연결·IP 단위 차단핸드셰이크 헤더 조작
핸드셰이크에 쿠키만 존재CSWSH 가능Origin 검증 여부 확인

1. 연결 파악

페이로드보다 먼저 연결 자체를 기록한다. WebSocket은 핸드셰이크 한 번으로 이후 모든 메시지의 권한과 컨텍스트가 결정되므로, 연결 정보가 곧 공격면의 범위다.

기록 항목확인 이유
엔드포인트 URL과 schemews면 평문 노출, 경로에 사용자 입력이 포함되는지
핸드셰이크 요청 헤더 전체인증 값, 커스텀 헤더, 프록시 관련 헤더 유무
인증에 사용되는 값쿠키만인지, 토큰·헤더가 함께 있는지
메시지 형식단순 문자열인지 JSON인지, 필드별로 처리가 다른지
메시지 방향클라이언트 주도인지, 서버가 먼저 보내는지
연결 직후 규약 메시지READY 같은 값이 이전 상태·대화를 반환하는지

Sec-WebSocket-KeySec-WebSocket-Accept는 규격상 핸드셰이크 확인용 값이며 인증이나 CSRF 방어 역할을 하지 않는다. 예측 불가능한 값처럼 보이지만 방어로 계산하지 않는다.

2. 클라이언트 측 처리 우회

브라우저 입력창을 거치는 검증과 인코딩은 방어가 아니다. 메시지는 프록시에서 직접 만들어 보낼 수 있으므로, 같은 값을 두 경로로 보내 비교하는 것이 첫 단계다.

입력창으로 전송한 값프록시에서 직접 전송한 값

확인 결과의미다음 단계
입력창에서는 인코딩되지만 원문 전송은 통과검증이 클라이언트에만 존재서버·수신 측 처리로 진행
원문 전송도 인코딩되어 저장서버 측 인코딩 존재인코딩 시점과 출력 컨텍스트 재확인
원문 전송 시 오류 응답서버 측 필터 존재차단 기준 역추적
값이 JSON 필드 중 일부만 처리필드별 처리 차이필드마다 별도 marker 삽입

JSON 메시지는 message, user, room처럼 필드가 여러 개인 경우가 많다. 한 필드가 안전하게 처리된다고 나머지도 같다고 보지 않고, 필드별로 서로 다른 marker를 넣어 도달 지점을 분리한다.

3. 메시지 기반 취약점

원문 전송이 통과했다면, 그 값이 최종적으로 어디에서 해석되는지에 따라 취약점 종류가 갈린다.

처리 지점확인할 것사용할 Probe관련 문서
다른 사용자 화면에 출력수신 측이 어떤 sink로 삽입하는가태그 파싱 여부 → 이벤트 요소XSS Playbook
DB 조회·검색 조건구문 파괴와 복구 응답 차이', 참·거짓 조건 쌍SQL Injection Playbook
XML·파일 파서외부 엔티티 처리 여부무해한 엔티티 선언서버 측 파서 동작 확인
서버의 외부 요청응답에 반영되지 않는 처리고유 OAST 도메인인밴드 신호가 없을 때만
응답이 전혀 관측되지 않음Blind 여부OAST 또는 다른 사용자 화면신호를 먼저 확보

메시지가 다른 사용자에게 중계되는 구조는 Stored XSS와 성격이 같다. 저장 후 조회를 기다리는 대신 즉시 전파되므로, 실제 서비스에서는 무해한 marker 단계에서 멈추고 영향 범위를 먼저 판단한다.

수신 측 sink 확인은 XSS 진단과 동일하다. innerHTML로 삽입하는 구조에서는 <script>가 DOM에 보여도 실행되지 않으므로, 파싱 직후 자동으로 발생하는 이벤트를 사용해야 한다.

4. 핸드셰이크 조작

Repeater에서 WebSocket URL 옆의 연필 아이콘으로 새 연결을 수립하거나 기존 연결을 복제·재연결하면서 핸드셰이크 요청을 직접 편집할 수 있다. 메시지 단위 방어가 촘촘해도 연결 단계에서 무력화되는 경우가 있으므로 항상 함께 확인한다.

조작 대상확인할 것성공 신호
X-Forwarded-For·X-Real-IP애플리케이션이 헤더로 클라이언트 IP를 판단하는가차단된 상태에서 재연결 성공
Origin서버가 출처를 검증하는가값을 바꿔도 101 응답
Cookie·Authorization다른 세션으로 연결 시 권한이 달라지는가권한이 다른 메시지 처리 결과
커스텀 헤더애플리케이션 고유 값을 신뢰하는가분기 동작 변화
Sec-WebSocket-Protocol서브프로토콜에 따라 처리가 갈리는가다른 응답·다른 메시지 규약
경로·쿼리 파라미터엔드포인트에 사용자 입력이 들어가는가다른 채널·방으로 연결

핸드셰이크를 다시 만들어야 하는 상황은 헤더 조작으로 공격면을 넓힐 때, 공격 시도로 끊긴 연결을 되살릴 때, 만료된 토큰을 갱신할 때다.

5. CSWSH 빠른 확인

세 조건이 모두 성립하면 Cross-Site WebSocket Hijacking이 가능하다.

  1. 핸드셰이크 인증이 쿠키에만 의존한다.
  2. CSRF 토큰이나 예측 불가능한 값이 없다.
  3. 서버가 Origin을 검증하지 않는다.

브라우저는 WebSocket 연결에 동일 출처 정책을 강제하지 않고 Origin 헤더만 전달하므로, 교차 출처 차단 여부는 전적으로 서버 검증에 달려 있다.

Origin 조작 결과판단다음 단계
임의 값·삭제에도 101 응답검증 없음교차 사이트 연결 PoC
101 이후 즉시 close부분 검증 또는 메시지 단계 인증종료 코드와 첫 메시지 확인
400·403 응답검증 존재null Origin, 서브도메인, 접미사 매칭 확인
쿠키 없이도 연결 성공인증 자체가 없음인증 없이 접근 가능한 데이터 범위 확인

PoC는 데이터 유출 전에 연결 수립 여부만 확인한다.

<script>
    const ws = new WebSocket('wss://<target-host>/chat');
    ws.onopen = () => console.log('opened');
    ws.onclose = (e) => console.log('closed', e.code);
</script>

연결이 열리면 세션 쿠키가 교차 사이트 요청에 실렸다는 뜻이다. 메시지 전송과 응답 수집으로 확장하는 단계는 실습 환경에서만 진행한다. 세션 쿠키의 SameSite 설정도 함께 확인한다. None이면 교차 사이트 요청에 쿠키가 자동으로 첨부된다.

6. 차단에 막혔을 때

WebSocket은 차단이 메시지 하나에 그치지 않고 연결 전체에 적용되는 경우가 많다. 어느 단위로 차단됐는지를 먼저 구분해야 다음 시도를 고를 수 있다.

증상차단 단위다음 선택
해당 메시지만 오류 응답, 연결 유지메시지대소문자·인코딩·대체 문법 변형
오류 후 연결 종료, 재연결은 가능연결새 핸드셰이크로 재연결 후 재시도
세션을 바꿔도 재연결 불가IPX-Forwarded-For 등으로 출처 IP 위장
차단 사유가 응답에 노출탐지 규칙 노출사유를 근거로 매칭 방식 역추적
일정 시간 후 자동 해제임시 차단요청 간격과 재시도 조건 확인

차단 사유가 {"error":"Attack detected: Event handler"}처럼 그대로 노출되면 필터가 무엇을 보고 판단했는지 알 수 있다. 이벤트 핸들러라면 HTML 속성 이름이 대소문자를 구분하지 않는다는 점을, 특정 문자라면 대체 문법을 먼저 확인한다.

7. 특수·예외 상황

아래 항목은 일반 흐름에 맞지 않을 때만 확인한다.

상황짧은 판단 기준관련 글
연결 직후 규약 메시지가 과거 데이터를 반환세션 컨텍스트만 있으면 이전 대화·상태를 열람 가능CSWSH Write-up
서버→클라이언트 메시지만 취약Proxy의 interception 방향 설정을 바꿔 수신 메시지 확인메시지 조작 Write-up
라이브러리 래퍼 사용(Socket.IO 등)자체 프레임 형식을 유지해야 메시지가 파싱됨라이브러리 프레임 규격 확인
핸드셰이크가 HTTP/2로 표시프록시 표기 차이이며 조작 방식은 동일핸드셰이크 Write-up
메시지에 자체 인증 값이 포함핸드셰이크가 아닌 메시지 단계 인증 여부 확인재사용·만료 조건 확인
ws:// 평문 연결네트워크 구간 노출과 메시지 조작 가능성개념: 대응 방안

Quick Checklist

  • 엔드포인트·핸드셰이크·메시지 형식을 먼저 기록했는가?
  • 입력창 전송과 프록시 원문 전송 결과를 비교했는가?
  • JSON 필드별로 도달 지점을 분리해 확인했는가?
  • 메시지가 다른 사용자에게 중계되는 구조인지 확인했는가?
  • 값이 최종적으로 해석되는 지점(수신 측 sink·DB·파서)을 특정했는가?
  • 핸드셰이크 헤더를 근거로 보안 결정을 내리는지 확인했는가?
  • CSWSH 성립 조건 세 가지를 각각 확인했는가?
  • 차단이 메시지·연결·IP 중 어느 단위인지 구분했는가?