비밀번호 찾기 기능 악용

특정 사용자의 이메일 주소를 사용하여 forgot_password 엔드포인트를 하루에 여러 번 호출하는 스크립트나 누군가의 공격을 받고 있습니다. 이 현상은 며칠째 지속되고 있으며, 이메일이 발송되므로 시스템에 대한 악용으로도 볼 수 있습니다.

nginx access.log를 통해 해당 시간대의 IP 주소를 추적한 결과, 시스템의 다른 사용자로 확인되어 경고 메시지를 전송했지만, 이로써 해결될지는 의문입니다. 또한 해당 IP 주소를 Admin > Logs > Screened IPs에 추가했지만, 이것이 임시 로그인 차단 외에 어떤 효과를 가져올지 확실하지 않습니다. IP 주소는 변경될 수 있으며, 실제로도 변경되었고, 동적 주소일 가능성이 높지만, VPN을 켜서 다시 시작할 수도 있습니다.

이 문제를 어떻게 처리하는 것이 좋을까요? 조언을 주실 수 있으신가요?

2개의 좋아요

Dan님, 괜찮으시다면 먼저 몇 가지 질문을 드리고 싶습니다.

  1. 해당 사용자를 정지(suspend)하셨나요?
  2. 누구나 계정을 만들 수 있도록 허용하시나요, 아니면 모든 신규 계정을 승인하시나요?

admin/users/list/active 경로로 이동하여 문제를 일으킨 사용자의 이름을 클릭하면 해당 사용자를 정지할 수 있습니다. 정보 페이지에 도달하면 Permissions(권한) 섹션으로 스크롤하여 Suspend(정지)를 클릭하세요. 정지 조치가 적용되기까지 로그아웃이 필요할 수 있으므로 사용자가 로그아웃 상태인지 확인하세요. 만약 여전히 로그인되어 있다면, 같은 페이지 오른쪽 상단에 있는 파란색 상자를 클릭하여 직접 로그아웃 처리할 수 있습니다. 로그아웃된 후에는 이전 인증 정보로는 다시 로그인할 수 없습니다.

신규 계정을 승인하는 방식을 사용하신다면 — 그리고 '범인’이 계속 문제를 일으킨다면(그리고 누가 그런지 확실하다면) — 해당 사용자는 당신이 계정을 승인할 때까지 기다려야 합니다. 이미 그가 사용한 IP 주소(들)를 가지고 있으므로, 그 IP로 새로운 사용자가 나타나는 경우 어떻게 해야 하는지 아실 겁니다. :wink:
또한 사용자의 설정 페이지를 방문하여 Account(계정) 섹션에서 최근 사용된 장치를 확인할 수 있으며, 여기에는 로그인에 사용된 IP 주소도 표시됩니다. 이를 통해 추가적으로 모니터링할 IP 주소를 파악할 수 있습니다.

이때 계정 승인 제도가 유용하게 작용합니다.

:thinking: 이 사람이 어떻게 다른 사용자의 프로필에 접근하여 비밀번호 재설정을 요청하는 것일까요? 그것이 중요한 질문입니다.

2개의 좋아요

비밀번호를 잊으셨나요 페이지를 방문하고 이메일 주소를 입력하면 됩니다. 누구나 어떤 사용자를 위해든 이 작업을 수행할 수 있습니다.

2개의 좋아요

하루에 정확히 몇 번이나 호출하나요?

2개의 좋아요

좋아요, "많다"는 상대적인 개념이죠.

root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log
214
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.1
147
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.2.gz
181
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.3.gz
140
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.4.gz
134
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.5.gz
251
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.6.gz
110
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.7.gz
100
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.8.gz
gzip: access.log.8.gz: No such file or directory
0
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.9.gz 
1
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.10.gz 
0
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.11.gz 
0
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.12.gz 
0
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.13.gz 
0
root@forum-app:/var/log/nginx# zgrep -c forgot_password access.log.14.gz 
0

분명히 이 검색으로는 합법적인 요청을 걸러낼 수 없습니다. 오늘과 어제의 로그를 수동으로 검토해 보니 몇 건의 합법적인 요청(반복되는 IP 주소가 아닌 것)을 발견했습니다. 대부분은 며칠마다 바뀌는 동일한 IP 주소에서 발생하고 있습니다. 시스템에는 큰 부담은 되지 않지만, 수신하는 사용자에게는 부담이 됩니다. 제가 할 수 있는 유일한 일은 nginx를 설정하여 IP 주소를 거부하는 것인데, IP가 계속 바뀌니… 아마 1~2주 동안 수동으로 확인하고 업데이트하면 그 사람이 시도를 멈출 수도 있지만, 아마도 잠시뿐일 것입니다. 피해자는 처음에 이런 일이 발생한 것이 약 1년 6개월 전이라고 말합니다.

3개의 좋아요

누군가가 내 대신 "비밀번호 찾기"를 반복적으로 트리거하게 되면 분명히 짜증나는 일이죠 .. 하지만 이걸 근거로 사용자의 비밀번호 재설정 기능을 차단할 수는 없습니다. 비밀번호 재설정 기능을 차단하는 것 역시 일종의 괴롭힘(griefing)에 해당하기 때문이죠. :thinking:

현재 분당 여러 번 수준으로 속도 제한(rate limit)이 설정되어 있다고 생각하는데, @riking 이 코드 경로를 검토해 주셔서 해당 기능이 여전히 정상 작동하는지 확인해 주시겠어요? 한도를 높일 수는 있지만, 그렇게 하더라도 “하루 몇 번” 수준의 악용을 안전하게 막을 수는 없습니다.

또한 관리자 > 로그 > 차단된 IP(Admin, Logs, Screened IPs)를 통해 IP 주소를 차단하면 해당 IP 주소가 비밀번호 재설정 요청을 보내는 것을 막을 수 있을 것으로 생각되는데, 이 부분도 @riking 이 정상 작동하는지 확인해 주시면 좋겠습니다.

10개의 좋아요

가짜 요청으로 스팸을 받는 사람은 바로 저입니다.
시간당 여러 번씩 발생하네요.

2FA와 리셋 키를 사용 중인데도 비밀번호 재설정 시 이메일을 보내지 않도록 하는 옵션이 없습니다.

방문한 일부 웹사이트에서는 비밀번호 재설정을 요청하기 전에 이메일로 전송될 것이라고 명시하며 IP 주소를 표시합니다.

이 모든 것은 매우 사소한 귀찮음일 뿐입니다. 저는 이 이메일을 거의 확인하지 않으니까요. 모든 이메일은 필터링되어 "메시지를 읽음으로 표시"하도록 설정되어 있어 읽어야 할 메일이 있는 것처럼 보이지 않습니다. 1월에 이 필터를 설정해 두고 오늘 해당 폴더(Gmail의 레이블)를 확인해 보았습니다.

3개의 좋아요

1번째 답변에 포함할 수 없었던 이미지입니다.
Gmail에서 동일한 제목의 메시지를 두 개 이상 받으면, 해당 메시지들을 한 그룹으로 묶어줍니다.
같은 제목의 메시지가 100개를 넘으면, 다음 100개 메시지로 넘어가는 것 같습니다.

5개의 좋아요

좋은 정보네요. 내일 @riking님과 함께 이 부분을 좀 더 진행해 봅시다.

6개의 좋아요

간단한 우회 방법을 하나 소개합니다. 이메일 주소를 test@gmail.com에서 test+SOMESECRETONLYYOUKNOW@gmail.com으로 변경해 보세요.

Discourse에서 보내는 이메일은 평소와 마찬가지로 기존 Gmail 계정으로 전달되지만, 다른 사람은 비밀번호를 잊어버린 경우의 재설정 링크를 보내거나, 안전한 해시를 추측할 수 없게 됩니다.

실용적인 관점에서 볼 때, 이 상황에서 가장 좋은 방법이라고 생각합니다.

비율 한도를 일주일에 한 번으로까지 낮춘다 해도 여전히 번거로울 것입니다. + 주소를 사용하면 이 문제를 완전히 해결할 수 있습니다.

12개의 좋아요

특정 사용자의 요청 에 대해 속도 제한을 적용하는 것 외에도, 특정 위치 에서 온 요청에 대한 제한(현재 꽤 잘 작동하고 있음)도 설정할 수 있습니다. "이메일을 기다려 주세요"라고 안내하기 전에, 만료되지 않은 재설정 토큰을 최대 2개까지 발급하는 것은 어떨까요?

6개의 좋아요

다른 접근 방식으로는 토큰 간 3시간과 같은 시간 제한을 비밀번호 재설정 이메일에 적용하는 것입니다.
쿨다운 기간 전에 비밀번호 재설정 이메일을 요청한 경우, 간단한 메시지를 표시할 수 있습니다:
“이미 비밀번호 재설정 이메일을 보냈습니다. 받은 편지함을 확인해 주세요. 2시간 이내에 이메일이 도착하지 않으면 %contact_email%로 사이트 관리자에게 도움을 요청해 주세요.”

2개의 좋아요

포럼의 이메일 주소를 'email+something@gmail.com’으로 변경하고, 다른 브라우저에서 시크릿 모드(Incognito)로 테스트해 보았습니다. 여전히 통과되었습니다. 아마도 요청이 항상 실제 이메일 주소가 아닌 단순히 발신자 이름(from username)으로만 이루어지기 때문일 것입니다.

현재는 Dan이 해당 개인에게 사적으로 문제를 해결했거나 다른 수단을 통해 조치를 취했기 때문에 모든 가짜 요청이 중단되었습니다.

사용자 수준에서 활성화할 수 있는 보안 질문 옵션이 있다면, 트롤은 답을 알 수 없으므로 모든 요청을 줄이는 데 큰 도움이 될 것입니다. “가장 좋아하는 영화는 무엇인가요?” 또는 “가장 좋아하는 식당은 어디인가요?” 같은 질문 말이죠.

이 문제를 해결하기 위해 신속하게 답변해 주신 모든 분들께 감사드립니다. 안타깝게도 이것은 첫 번째 문제였으며, hopefully 마지막이 되기를 바랍니다.

3개의 좋아요

문제는 포럼에서 사용자 이름을 수집한 뒤, 비밀번호 찾기 요청을 대량으로 보내는 트롤링이 가능하다는 것 같습니다.

비밀번호 찾기를 사용할 때 이메일 주소를 정확히 입력해야 하는 모드를 추가하면 어떨까요? '비밀번호 찾기 엄격 모드’라고 하고, 기본값은 꺼져 있게 하면 좋겠습니다.

일주일에 한 번만 트롤링을 당해도 너무 스트레스를 받습니다. 이 문제는 요청 제한(rate limiting)으로는 해결할 수 없어요.

11개의 좋아요

일정 시간 내에 정확히 입력하도록 강제하기 전에, 먼저 하나 또는 두 번의 “무료” 재설정을 제공하는 방법이 있을까요? 아니면, 개인 계정에 대해 여러 번 재설정을 시도한 후에만 정확히 입력하도록 하지만, 전역적으로 자동으로 적용하는 방식은 어떨까요? :thinking:

우리 중 일부는 진짜로 오늘이 무슨 요일인지도 모를 정도로, 정확한 이메일 주소를 매번 빠짐없이 기억하는 게 쉽지 않거든요.

:crossed_fingers: @Chinaski, 이 문제가 당신에게도 빨리 그리고 마침내 해결되기를 바랍니다.

8개의 좋아요

답변해 주셔서 감사합니다. 위 방법이 현재 가장 직접적인 해결책인 것 같아 잘 작동하기를 바랍니다. 다만, 스팸이 줄어든 이후로 직접 테스트해 보지는 않았습니다. (공격자로 추정되는 사용자는 자신의 WiFi에서 게스트 네트워크를 꺼두었다고 주장하지만, 그것이 실제 원인이었는지 확신할 수 없습니다.)

2개의 좋아요

수천 명의 활성 사용자가 있는 상황에서 (아직 Discourse로의 마이그레이션 과정에 있습니다) 여러분의 고충을 잘 이해합니다. 사람들이 어떤 이메일을 사용했는지 잊어버리는 등의 문제가 너무 자주 발생해서, 이는 수년간 우리의 가장 빈번한 지원 요청 중 하나였습니다. 정말 놀라운 일입니다.

2개의 좋아요

비밀번호를 잊었을 때 이메일 입력을 요구하는 기능은 절대 기본값으로 설정될 일은 없을 것입니다.

하지만 OP(원포스터)의 사례처럼 포럼이 공격을 받고 있는 상황이라면, 이 짜증나는 해킹을 막기 위해 몇 주 동안 켜두었다가 꺼도 되는 간단한 스위치로 사용할 수 있습니다.

5개의 좋아요

Per

규칙을 강화하여 최악의 경우에도 사용자가 하루에 최대 6회만 리셋할 수 있도록 했습니다. 이렇게 하면 이메일 발송을 어느 정도 제한할 수 있을 것입니다.

또한 @riking 님의 조언을 따랐으며, 스크리닝된 이메일을 존중하도록 했습니다. 따라서 관리자가 IP를 차단하면 해당 IP는 더 이상 이 프로세스에 참여할 수 없습니다.

@riking 님, 여기 한 가지 큰 누락이 있는데, 자구(Self-medication)에 도움이 될 수 있는 부분입니다. “비밀번호 리셋” 이메일에는 이를 초기화한 사람의 IP 주소가 포함되어 있지 않습니다:

@codinghorror 님, 비밀번호 설정 이메일에 초기화 요청자의 IP 주소를 추가하는 것(일부러 약간 숨기는 방식도 가능)에 대해 어떻게 생각하시나요? 이렇게 하면 자구(Self-medication)가 훨씬 더 잘 이루어질 것입니다.

Jane이 공격을 받음
Jane이 12.12.12.12가 계속 비밀번호를 리셋하고 있다고 사이트 관리자에게 알림
관리자가 12.12.12.12를 차단

사람들은 여러 IP에 접근할 수 있으므로 여전히 고양이와 쥐의 게임이 될 수 있지만, 이전보다는 낫고 제한 사항이 더 엄격해졌습니다.

Facebook은 제가 구현을 어느 정도 지지하는 이 트릭을 사용합니다:

이 방식은 이메일에 IP 주소를 포함하는 것을 피할 수 있게 해줍니다. 서버 측에서 이를 추적하고 링크에는 데이터베이스의 ID만 포함됩니다. 즉, 이는 악용자를 차단하는 것이 1클릭 작업이 될 수 있음을 의미합니다.

참고로 Facebook은 비밀번호 리셋에 이메일을 요구합니다(전통적인 의미의 비밀번호 리셋 기능이 없고, 단순히 이메일을 통한 로그인만 수행합니다).

10개의 좋아요

가짜 요청 100건을 확인해 보니 패턴이 발견되었고, 스크립트 사용이 의심됩니다.
이 패턴은 Gmail에서 한 그룹으로 묶인 100건의 가짜 요청 전반에 걸쳐 일관되게 나타납니다.

3개의 좋아요