fix(realtime): 문서 SSE 채널이 소유권 검증 없이 열려 있던 문제 - #186
Merged
Conversation
`/realtime/stream/documents/{id}` 만 토큰 리소스 범위를 확인하지 않고 있었다
(`// TODO: DOCUMENT 스코프 검증 (deferred)`). 세션 채널 3개는 모두
`ResourceType`/`ResourceID` 를 확인한다.
이 채널로 흐르는 건 `AnalysisCallbackPayload` 다 — 분석 **요약·기술스택·문서 S3 경로**.
즉 남의 이력서·자소서 내용이다. 유효한 스트림 토큰(로그인한 사용자면 자기 것으로 언제든
발급 가능)만 있으면 document id 를 바꿔가며 타인의 분석 결과를 구독할 수 있었다.
id 는 BIGSERIAL 이라 열거도 쉽다. 이벤트 replay 는 없으므로 "구독 중일 때 완료되는 분석"
으로 범위가 제한되지만, 연결을 열어두면 계속 수확할 수 있다.
세션 채널과 같은 방식으로 막는다. RealTime 은 DB 를 보지 않으므로, Core 가 소유권을 확인해
발급한 토큰의 리소스 범위를 강제하는 것이 유일한 소유권 검사다. `channelByPath` 를
`scopedChannel(sse, kind, resourceType)` 로 바꿨다.
현재 Core 는 DOCUMENT 스코프 토큰을 발급하지 않고, 프론트도 이 채널을 쓰지 않는다
(분석 상태는 `/realtime/stream/me` 유저 채널로 받는다 — AnalysisCallbackService 가 양쪽에
publish 한다). 따라서 이 변경으로 깨지는 사용처는 없고, 나중에 DOCUMENT 토큰을 도입하면
그대로 동작한다.
테스트 4종: 다른 리소스 타입(SESSION) 토큰 거부, 다른 문서 id 거부, claims 없음 거부,
그리고 **일치하는 토큰은 거부되지 않음**(거부만 검증하면 비교를 뒤집어도 통과한다).
§15 가 '리소스 소유권 검증 미구현' 이라고 적고 있었는데 세션 채널 3개는 이미 검증하고 있었다. 이번에 document 채널까지 붙였으므로 채널별 규칙을 표로 정리한다.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
변경 사항
마지막 점검에서 RealTime(Go) 서버를 처음 읽다가 나왔다. 오늘 CI 에 들어오긴 했지만 코드를 본 적은 없던 축이다.
라우터의 채널 4개 중 document 만 토큰 리소스 범위를 확인하지 않고 있었다:
세션 채널 3개(
/realtime/stream/sessions/{id},/realtime/sessions/{id},.../audio)는 모두 이렇게 막고 있다:무엇이 새는가
이 채널로 흐르는 건
AnalysisCallbackPayload다:즉 남의 이력서·자소서 분석 결과다. 유효한 스트림 토큰만 있으면(로그인한 사용자는 자기 것으로 언제든 발급 가능)
document id를 바꿔가며 타인의 분석 결과를 구독할 수 있었다. id 는 BIGSERIAL 이라 열거도 쉽다.범위 제한 요소: 이벤트 replay 가 없어 구독 중에 완료되는 분석만 받는다. 다만 연결을 열어두면 계속 수확할 수 있다.
수정
세션 채널과 같은 방식으로 막는다. RealTime 은 DB 를 보지 않으므로, Core 가 소유권을 확인해 발급한 토큰의 리소스 범위를 강제하는 것이 유일한 소유권 검사다.
channelByPath를scopedChannel(sse, kind, resourceType)로 일반화했다.깨지는 사용처가 없는 이유
/realtime/stream/me(유저 채널)로 받는다.AnalysisCallbackService가 document·user 양쪽에 publish 하고, 코드 주석도 "프론트가 documentId 를 모르고도 /realtime/stream/me 로 받을 수 있게"라고 적고 있다즉 제품에서 안 쓰이면서 열려 있던 경로다. 나중에 DOCUMENT 토큰을 도입하면 이 검증이 그대로 동작한다.
테스트 (4)
로컬에 Go 툴체인이 없어 CI 로 검증한다.
영향 범위
리뷰어 체크포인트
/realtime/stream/me(유저 채널)는 토큰의UserID로 채널을 만들므로 id 조작 여지가 없다 — 확인했다