스태프가 생성한 초대 링크가 must_approve_users 요구 사항을 우회합니다

초대 시스템에서 심각한 보안 문제가 발생했습니다. 재현이 비교적 쉬운 것 같습니다. 저희 사이트는 초대 전용(invite-only)으로 운영되고 있으며, 설정에서 “사용자 승인 필수” 옵션도 체크되어 있습니다.

스태프 중 한 명이 최대 사용 횟수가 1보다 큰 초대 링크를 발급하여, 특정 이메일 주소로 제한하지 않았습니다(아래 예시 참조).

해당 초대 링크가 유포되었고, 사람들이 이를 이용해 가입할 수 있었습니다. 그러나 설정에서 "사용자 승인 필수"가 체크되어 있다면, 이러한 “이메일 제한이 없는” 초대를 사용하는 모든 사용자는 스태프의 승인을 받아야 한다고 생각했습니다. 하지만 실제로는 해당 링크를 가진 누구나 자동으로 승인되어 가입할 수 있었습니다. 즉, 누구든 이 링크를 사용할 수 있으며, 누가 이 링크로 가입했는지 확인할 수 없습니다. 우리는 이메일, 이름, 그리고 추가한 다른 필수 항목들을 통해 가입 신청자의 신원(배경 조사)을 확인한 후 승인을 해야 합니다.

이로 인해 심각한 문제가 발생했는데, 엄격히 금지된 외국 조직의 한 사람이 이 링크를 얻어 가입을 시도했습니다. 저는 즉시 해당 계정을 삭제해야 했습니다. 이는 우리에게 심각한 보안 허점입니다.

따라서 “사용자 승인 필수” 옵션은 매우 위험하게 오해의 소지가 있다고 생각합니다. 현재 이 옵션은 초대 전용 인스턴스에서는 사실상 무의미합니다.

이메일로 제한되지 않은 초대 링크를 사용한 사용자를 스태프가 승인할 수 있는 방법이 있을까요? 사이트가 초대 전용인 경우 “사용자 승인 필수” 기능을 활성화하는 논리적인 방법이라고 생각됩니다.

5개의 좋아요

제가 문제를 재현해 보았더니, 대량 초대 링크가 생성되면 해당 링크로 가입한 사용자는 ‘사용자 승인 필요’ 설정에 자동으로 면역이 되는 것으로 확인됩니다.

6개의 좋아요

이 문제를 수정하는 데 관심이 있는 사람이 있습니까? 해결되지 않으면 결국 이 문제로 인해 우리 조직의 Discourse 프로젝트가 중단될 것입니다.

2개의 좋아요

이것이 버그인지 확신이 서지 않습니다.

전역 초대 코드와 승인 우회용 초대에 대한 이전 주제들을 읽어보니, 이는 의도된 동작일 가능성이 높습니다. 다만 팀의 누군가가 코멘트를 남겨야 할 것 같습니다.

@Wall-E 님, 이메일에 연결되지 않은 초대 코드가 승인 단계를 추가한다는 것으로 오해하게 한 문서를 확인하셨나요?

4개의 좋아요

여기서 핵심은 직원이 초대장을 발급했다는 점입니다. Discourse는 초대장을 사용하는 사용자들에 대한 묵시적인 승인(implicit approval)으로 간주합니다.

만약 직원 외의 사용자가 초대장을 생성했다면, 해당 초대장을 사용한 사용자는 직원의 승인을 기다리는 대기열에 추가됩니다.

5개의 좋아요

즉, 비스태프 사용자 계정을 이용해 초대장을 생성하면 그 초대장을 통해 가입한 사용자들은 검토 대기열에 들어가는 건가요? 만약 그렇다면 그것은 완전히 허용되는 동작이며, @Wall-E 님은 임시 일반 계정을 사용해 초대장을 생성하는 방식으로 우회할 수 있습니다.

3개의 좋아요

최소 한 번은 스태프 사용자에게 경고가 표시되어야 하며, 새 멤버가 어떻게 처리될지 선택할 수 있다면 정말 좋겠습니다. 두 번째 “일반” 사용자를 사용하는 것은 보기 싫은 우회 방법입니다.

7개의 좋아요

이 주제와 이전 주제들을 읽어보면서, 현재 동작 방식이 의도된 설계(by design)라는 것을 알 수 있지만, 초대 시스템의 새로운 변경 사항을 반영하지 못하고 있음을 확인했습니다. 이제 모르는 사람들이 사용할 수 있는 초대 링크를 생성하는 것이 훨씬 쉬워졌습니다. 또한 이제 스태프가 초대 대상자를 사이트의 보안 카테고리 접근 권한이 있는 그룹에 추가할 수 있는 위험한 초대 링크를 생성할 수도 있습니다.

@Wall-E 초대 링크가 사이트 접근 권한이 없는 사람들의 손에 넘어가는 구체적인 상황이 어떻게 되는지 궁금합니다. 아마도 사이트 스태프는 누구나 사용할 수 있는 초대 링크를 생성하거나, 잘못된 사람들이 이를 사용할 수 있는 환경에서 공개적으로 공유하지 않도록 주의해야 한다는 점을 알고 있을 것입니다. 따라서 현재 직면하고 있는 문제는 어느 정도 스태프 교육의 문제라고 볼 수 있습니다. 민감한 세부 사항이 포함된 답변이라면 편하게 DM으로 보내주세요.

현재 존재하는 초대 링크 중 어떤 식으로든 유출된 것이 있다면, 이를 삭제하고 새 링크를 생성한 후 앞으로는 더 신중하게 공유할 수 있습니다. 관리자라면 사용자 초대 페이지에서 누가 초대를 사용(redemption)했는지 항상 확인할 수 있습니다. 신뢰할 수 없는 스태프가 있다면, 그 권한을 TL4(거의 모더레이터 권한)로 낮출 수 있습니다.

세 가지 가능한 대응 방안을 제시합니다:

  1. 아무것도 하지 않습니다. 초대 시스템은 의도된 대로 작동하고 있으며, 스태프가 초대 링크를 신중하게 다루면 됩니다. 이 방향으로 간다면, must approve users 관리자 설정의 설명을 변경하여 관리자가 생성한 초대 링크가 이 설정을 우회한다는 점을 명확히 하는 것이 좋습니다.

스태프는 사용자가 사이트에 접근할 수 있도록 하기 전에 모든 새로운 사용자 계정을 승인해야 합니다. 참고: 스태프가 생성한 초대는 이 설정을 우회하며 승인이 필요하지 않습니다.

이 변경 사항에 대한 Pull request는 여기에 있습니다: clarify that invites by staff bypass user approval - Pull Request #16966 - discourse/discourse - GitHub

  1. (1)과 함께, 승인(approval)이 필요한 사이트에서만 사이트 접근 권한을 즉시 얻을 수 있는 초대 링크를 생성할 때 관리자에게 "확실합니까?"라는 추가 경고 단계를 추가합니다.

  2. 관리자가 생성한 초대 링크도 비관리자의 초대와 마찬가지로 승인 필요(approval required) 설정을 따르도록 동작을 변경합니다.

OP와 마찬가지로, 현재 동작 방식이 오해의 소지가 있으며, 승인(approval)이 필요한 사이트에서 문제를 초래할 가능성이 있다고 생각합니다. 이 설정을 활성화한 사이트는 접근 권한이 있는 사람에 대해 더 신중하고, 이러한 추가적인 편집증적 수준의 통제가 필요합니다.

따라서 제 추천은 세 번째 문(Door number three)을 선택하여 모든 초대 링크가 동일하게 작동하도록 하고 must approve users 설정을 따르도록 하는 것입니다.

이것은 버그라고 생각하지 않습니다. 의도된 대로 작동하고 있습니다. 기능 요청(feature request)으로 재분류합니다.

5개의 좋아요

저도 3번 옵션을 강력히 지지합니다. 사람들이 감정에 대해 더 깊이 성찰할 수 있는 커뮤니티를 구축하고 있는데, 익명 초대 링크(이메일 주소나 신원과 연결되지 않기 때문)에 추가적인 승인 단계를 두면, 제가 원하는 사람들만 가입할 수 있을 것이라는 안도감을 줄 수 있다고 생각합니다.

초대 링크 대신 초대 이메일을 사용하도록 할 수도 있겠지만, 링크는 WhatsApp이나 다른 커뮤니케이션 플랫폼에서 공유하기 훨씬 간편합니다.

따라서 익명 초대 링크가 사용자 승인 필수 설정을 따르도록 하는 것도 지지합니다.


또한, 3번이 실현된다면 초대 시스템이 초대 전용 포럼의 지원 시스템처럼 기능할 수 있을 것이라고 생각합니다. 현재는 별도의 Google Form 등을 사용하지 않고 사람들이 회원으로 가입하도록 신청받기 위해 어떻게 해야 할지 확신이 서지 않습니다. 이는 사용자 정의 필드를 지원서로 사용할 수 있게 하여 프로세스를 단순화할 수 있는 방법이며, 이것이 @Wall-E 님이 하려는 것이라고 생각합니다.

1개의 좋아요

제 주제는 그런 게 아닙니다. 저는 초대 전용 인스턴스에서 must_approve_users가 효과가 없다는 이야기를 하고 있습니다. 이 옵션을 켜고 끄는 것은 서로 다른 효과가 있어야 합니다. 그렇지 않다면, 이 동작이 초대 전용 인스턴스에는 적용되지 않는다는 점을 문서에 명시해야 합니다. 만약 제가 문서에서 이를 놓쳤다면, 그것은 확실히 우리 스태프의 책임입니다. 하지만 문서에 그런 내용이 없다면, 해당 기능은 오해를 불러일으키므로 수정하거나, 최소한 문서화해야 합니다. 이 기능 때문에 우리 스태프 전체가 혼란을 겪었으니까요.

위에서 @david의 답변을 확인하세요:

전적으로 동의합니다. 문서에 언급되어 있었을 수도 있지만 제가 놓쳤을 수 있습니다. 만약 문서에 명시되어 있었다면, 제 직원을 잘못된 방향으로 이끈 것은 제 책임이 될 것입니다. 그리고 경고 메시지는 해가 되지 않습니다. 왜냐하면 사람, 즉 직원도 잊어버릴 수 있기 때문입니다.

네, 확인했습니다. 알아두겠습니다.

저희 조직에서 해당 측면을 보안 문제로 간주하여 우리를 차단할 수 있는 권한을 가진 사람들의 말을 인용하겠습니다. “이 시스템이 무단 조직의 누군가가 들어올 수 있게 할 수 있다면, 당신의 주의와 관계없이 결국 그렇게 될 것이라고 가정해야 합니다.” 실제로 정확히 그런 일이 발생했습니다. 해당 “기능”(초대 전용인 경우 "must_approve_user"가 아무런 효과가 없으므로, 기능이라기보다는 비기능이라고 할 수 있습니다)이 활성화되어 있었고, 우리는 초대하려는 대상에게 제한 없는 초대장을 발급했습니다. 당연히 그중 한 명이 해당 제한 없는 초대 링크를 다른 조직에 공유했습니다.
이로써 @tobiaseigen 님에게도 답변드립니다.

저희는 수백 명의 인원이 참석하는 회의와 컨퍼런스를 개최합니다. 이들은 포럼 가입이 허용된 승인된 조직의 구성원들입니다. 하지만 그중 일부는 (저희가 통제할 수 없는 상위 정책상의 이유로) 포럼 가입이 허용되지 않은 다른 조직에서 온 경우도 있습니다.
해당 초대 링크는 “자유롭게” 유포되었습니다. 스태프가 주의했음에도 불구하고, 그 링크를 가진 “묵시적으로 승인된” 사람들이 무엇을 할지 저희가 통제할 수 없기 때문입니다. 정의상 그 링크는 "제한 없음"이므로, 그들은 원하는 누구에게든 전달할 수 있습니다. 만약 그것이 “설계상” 그렇게 되어 있고 묵시적 승인을 의미한다면, 이 제한 없는 초대 링크는 어디든 갈 수 있으며, 결국 그렇게 될 것입니다. 이것이 저희 IT 부서 책임자가 정당한 이유를 들어 말했던 내용입니다. 저희는 그것을 알고 있었기 때문에, 그것이 본래 의도한 보안 계층으로 작용하도록 *must_approve_users"를 활성화했습니다.

이것이 기능인지 버그인지에 대한 질문이 있는 것 같습니다. 저는 전문 프로그래머가 아니므로(저는 천체물리학자입니다) 그것은 여러분이 결정할 문제입니다. 저는 그저 이 놀라운 플랫폼을 계속 사용할 수 있도록, 우리에게 심각한 "문제"를 야기한 것을 보고할 뿐입니다.

저는 옵션 3에 전적으로 찬성하며, 저희 연구소와 포럼 스태프도 마찬가지입니다. 별도 통지가 있을 때까지, 스태프에게는 제한 없는 초대를 사용하지 않도록 지시되었습니다. 이로 인해 스태프는 초대하려는 모든 사람의 개별 이메일 주소를 수동으로 추가해야 하는 추가 부담을 지게 되었습니다(컨퍼런스의 경우 수백 명의 참가자가 넘는 경우가 많습니다…). 모든 회의, 이벤트 등에서 이를 수행해야 하는 것은 우리 성장에 높은 마찰을 더할 것이며, 추가된 업무량 때문에 일부 스태프가 떠나게 될 것을 예견할 수 있습니다(대부분은 자원봉사자이며, 다른 업무로 이미 과부하 상태입니다)."

2개의 좋아요

옵션 3가 진행되면 기존 동작과 일치하는 옵션이 제공될 것이라고 가정해도 될까요?

우리가 급하게 만든 훈련 사이트는 대량으로 초대된 그룹에 대한 승인 우회 기능이 없었다면 훨씬 실행하기 어려웠을 것입니다.

1개의 좋아요

대량 초대도 하나의 옵션이라는 점을 잊지 마세요. 이벤트에서 참가자 CSV 파일을 생성하는 경우, 이를 사용하여 모든 참가자를 직접 초대할 수 있습니다.

그렇지 않은 경우, 웹 폼의 URL을 공유하여 CSV를 작성하고 대량 초대를 보내기 전에 사용자를 검증할 수도 있습니다.

불행히도 저희가 진행하는 일반적인 행사에서는 해당 데이터에 접근할 수 없습니다. 컨퍼런스/회의를 주최하는 기관은 이러한 연락처 목록을 PII(개인 식별 정보)로 취급합니다. 설령 접근 권한이 있다 해도, 해당 기능을 활용할 여유가 전혀 없습니다. POC(담당자)에게 문의해야 하는데, 그분은 항상 업무 과부하 상태(정보 접근이 허용된다 해도 마찬가지입니다)이므로, 결국 높은 마찰이 발생합니다. 초대 링크를 받는 시점에는 이미 행사가 끝나고, 저희 직원들과 잠재적 초대 대상자 모두의 동력은 사라져 버립니다.

1개의 좋아요

확인했습니다. 우회 방법이 될 수는 있겠지만, 저희 직원은 그 추가 단계를 처리할 여유가 거의 없습니다. 따라서 이상적인 방법은 아닙니다.

1개의 좋아요

이 문제가 여러분과 커뮤니티에 불편을 끼쳤다는 점, 그리고 죄송하다는 말씀을 드립니다.

앞으로 시스템이 어떻게 작동하는지 아시게 되었으니, 여러분과 다른 관리자 및 모더레이터분들이 초대 시스템을 신중하게 사용할 수 있을 거라 생각합니다.

기능인지 버그인지에 대한 질문은 우선순위 문제입니다. 특히 보안 관련 버그인 경우 빠른 수정을 최우선으로 하지만, 이번 경우 해당 기능은 수년 전부터 동일한 방식으로 동작하고 있으며, 이는 의도적으로 설계된 것입니다. 변경하는 것이 좋다고 생각하지만, 모든 일을 멈추고 당장 수정해야 할 정도의 긴급한 사안은 아닙니다.

다른 분들의 의견을 들어볼 시간을 두고, 어떤 방향으로 진행할지 결정하겠습니다.

2개의 좋아요

가디언이 이 프로세스의 다양한 요소에 어떻게 관여하는지에 따라 훨씬 복잡한 변경이 될 수 있지만, 3번 옵션에 의존하는 또 다른 옵션은 다음과 같습니다:

  1. 초대 자체에 사용자 승인을 우회하기 위한 불리언 속성을 추가합니다. 이 속성은 기본적으로 꺼져 있으며, must_approve_users가 활성화된 경우에만 초대 생성 UI에서 노출됩니다.

수정: 다시 살펴보니, 데이비드가 언급한 코드에서 가디언은 초대된 사용자가 승인을 받아야 하는지 여부를 결정하는 과정에 전혀 관여하지 않는 것 같습니다. 해당 부분은 invite.invited_by.staff?를 invite.bypass_approval? 같은 것으로 교체하는 간단한 작업이 될 것 같습니다.

1개의 좋아요

우선순위 설정에 따른 여러분의 제약 사항을 충분히 이해합니다. 우리 인스턴스는 다소 특수한 상황에 있는 것 같습니다. 제가 아는 모든 디스커스 인스턴스는 우리가 준수해야 하는 엄격한 보안 정책을 가지고 있지 않은 조직에서 운영되고 있기 때문입니다. 예를 들어, 초대 전용(invite-only)은 우리 조직이 부과한 제약 사항이었으며, 셀프 가입(self-signup)이 없다면 우리 인스턴스는 존재할 수 없었습니다. 셀프 가입이 가능하다면 더 쉬울 텐데, 그렇게 되면 ‘느슨해지’ 수 있는 무제한 초대 기능을 사용할 필요가 없었을 것입니다.

2개의 좋아요