패스키는 문제가 있지만, 무시한다면 여러분에게도 문제가 생길 것입니다.

Jason Meller - Passkeys Have Problems, but So Will You If You Ignore Them

작성자
Ruby on Rails Youtube
발행일
2025년 09월 16일

핵심 요약

  • 1 패스키(Passkeys)는 기존 다단계 인증(MFA)의 피싱 취약점을 해결하는 강력한 대안이며, Ruby on Rails 애플리케이션에 효과적으로 통합될 수 있습니다.
  • 2 Uber 해킹 및 실시간 피싱 공격 사례를 통해 비밀번호와 OTP, 푸시 알림 기반 MFA가 '원본 바인딩' 부족으로 인해 얼마나 쉽게 우회될 수 있는지 강조합니다.
  • 3 Ruby on Rails 개발자는 `webauthn-ruby` 젬을 활용하여 패스키를 MFA 옵션으로 추가하고, `signed_id` 기반 매직 링크, 유사 모드(pseudo mode), 강력한 비밀번호 정책 등 추가 보안 조치 도입을 고려해야 합니다.

도입

이 강연은 1Password의 엔지니어링 VP이자 Collide의 창립자인 Jason Meller가 Rails World에서 진행한 발표입니다. 그는 DHH의 '패스키는 문제가 많다'는 블로그 게시물 이후, 패스키에 대한 오해를 해소하고 Ruby on Rails 개발자들이 패스키를 더 효과적으로 구현할 수 있는 방안을 제시하고자 합니다. 특히 기존 인증 방식의 취약점을 지적하며, 패스키가 단순한 비밀번호 대체가 아닌 피싱 방지형 다단계 인증(MFA)으로서의 가치를 강조합니다.

기존 인증 방식의 취약점과 공격 사례

  • Uber 해킹 (2022년 9월): 다크웹에서 탈취한 직원 자격 증명과 Duo Push 기반 MFA를 악용한 사회 공학적 공격으로 시스템이 완전히 침해되었습니다. 공격자는 직원을 속여 MFA 승인을 유도하여 VPN에 접근했고, 이후 내부 시스템을 장악했습니다.

  • 실시간 피싱 (Real-time Phishing): 이 공격은 ‘인증 경험 역방향 프록시(authentication experience reverse proxy)’라는 악성 소프트웨어를 사용하여 사용자로부터 실시간으로 자격 증명과 OTP를 탈취합니다.
    • 공격 방식: 교묘한 피싱 링크를 통해 사용자를 가짜 로그인 페이지로 유도하고, 사용자가 입력한 정보를 즉시 실제 서비스에 전달하여 세션을 탈취합니다. 사용자는 오류 메시지를 받지만, 공격자는 이미 세션을 확보하여 자동화된 스크립트로 데이터를 유출하거나 추가적인 악성 행위를 수행합니다.
    • Mailchimp/Troy Hunt 사례: 유명 보안 전문가인 Troy Hunt조차 실시간 피싱에 당하여 Mailchimp 계정이 침해되고 API 키가 생성되어 모든 이메일 주소가 유출되었습니다.
    • 확장성 증가: 과거에는 비용이 많이 들고 인간 개입이 필요했지만, AI(LLM)의 발전으로 CAPTCHA 우회 및 공격 후 스크립트 작성이 쉬워져 공격의 규모와 성공률이 크게 증가했습니다.
  • ‘원본 바인딩(Origin Binding)’의 실패: 비밀번호, SMS OTP, 푸시 알림, 이메일 매직 코드 등 대부분의 기존 인증 방식은 사용자의 장치와 실제 서비스 간의 ‘원본 바인딩’이 부족하여 피싱 공격에 취약합니다. 공격자가 사용자 장치에서 인증을 완료하여 공격자 장치에서 세션을 활성화할 수 있습니다.

피싱 방지형 인증 솔루션

  • 매직 링크 (Magic Links):
    • 개념: 이메일로 전송된 고유 링크를 클릭하여 로그인하는 방식입니다. ‘원본 바인딩’을 통해 피싱을 방지할 수 있습니다.
    • Ruby on Rails 구현: Rails 7의 signed_id 기능을 활용하면 쉽게 구현할 수 있습니다. 유효 기간 설정 및 이메일 변경 시 링크 무효화 등의 주의 사항을 준수해야 합니다.
    • 신뢰할 수 있는 장치 (Trusted Device): 매직 링크와 함께 신뢰할 수 있는 장치 개념을 적용하여, 새로운 장치에서는 추가 인증(예: 매직 링크)을 요구하고, 신뢰된 장치에서는 일반 인증 흐름을 허용하는 것이 좋습니다.
  • 패스키 (Passkeys) / WebAuthn:
    • 개념: 웹 인증을 위한 SSH 키와 유사하게 공개-개인 키 쌍을 사용하는 방식입니다. ‘WebAuthn’은 이 키의 생성, 사용, 저장을 정의하는 프로토콜 및 API입니다.
    • 작동 방식: 웹사이트(Relaying Party)가 챌린지를 발행하면, 브라우저가 이를 인증자(Authenticator)에 전달합니다. 인증자는 사용자 확인(Touch ID, PIN 등) 후 챌린지에 서명하고, 브라우저는 이 서명을 웹사이트에 전달하여 인증을 완료합니다.
    • 인증자 유형:
      • 플랫폼 인증자 (Platform Authenticators): 1Password와 같이 장치에 내장되거나 앱 형태로 존재하며, 장치 간 동기화가 가능하여 사용이 편리합니다. (예: 1Password, iCloud Keychain)
      • 로밍 인증자 (Roaming Authenticators): YubiKey와 같은 물리적 하드웨어 키로, 높은 보안 격리성을 제공하지만 백업 및 사용 편의성 측면에서 단점이 있습니다.
    • GitHub의 패스키 구현: GitHub는 패스키를 로그인 방식 및 선호 MFA 방식으로 활용하며, 기존 FIDO2/U2F 키를 패스키로 업그레이드하고, 데스크톱에서 모바일 장치를 통한 패스키 생성을 지원하는 등 사용자 경험을 최적화했습니다.
    • Ruby on Rails 구현 팁:
      • webauthn-ruby 젬을 활용하면 수백 줄의 코드로 패스키를 구현할 수 있습니다.
      • 로그인 폼의 사용자 이름 필드에 autocomplete="webauthn"autofocus="true" 속성을 추가하여 자동 프롬프트를 유도합니다.
      • 최신 브라우저는 네이티브 WebAuthn API를 지원하므로 별도의 JavaScript 라이브러리가 필요 없습니다.
      • FidoMetadata 젬을 사용하여 패스키 정보를 시각화하고, 사용자에게 여러 개의 패스키 등록을 허용하며, 팀 기반 앱에서는 관리자가 패스키 인증을 필수로 지정할 수 있도록 합니다.
      • 계정 복구: 복구 코드는 일반 MFA 흐름과 분리하여 별도의 ‘매우 중요한’ 프로세스로 취급해야 합니다. 복구 시에는 새로운 패스키 생성을 유도하여 신뢰를 재구축해야 합니다.

추가적인 보안 권장 사항

  • 비밀번호 재입력 (Pseudo Mode): GitHub의 ‘유사 모드’와 같이 민감한 작업(API 키 생성, 설정 변경 등) 수행 전에 비밀번호나 MFA 재인증을 요구하여 세션 탈취 후의 피해를 최소화합니다. Rails의 before_action으로 구현할 수 있습니다.

  • 강력한 비밀번호 정책:
    • Zxcvbn 젬: Dropbox에서 개발한 이 젬은 사전 공격 등을 통해 비밀번호 강도를 측정하고 사용자에게 안전한 비밀번호를 권장합니다.
    • Pwned 젬: Troy Hunt의 Have I Been Pwned 서비스를 활용하여 사용자가 입력한 비밀번호가 유출된 적이 있는지 확인합니다. K-익명성 모델을 통해 비밀번호 전체를 전송하지 않고도 확인할 수 있습니다.
  • Passkeys.Directory: 패스키 지원 여부를 홍보하고 다른 앱들의 지원 현황을 확인할 수 있는 디렉터리입니다.

결론

기존 비밀번호와 OTP 기반 MFA는 실시간 피싱 공격에 취약하며, AI의 발전으로 이러한 공격의 규모와 성공률이 더욱 높아지고 있습니다. Ruby on Rails 개발자들은 이러한 위협에 대응하기 위해 `signed_id` 기반 매직 링크와 특히 피싱 방지 기능을 제공하는 패스키(WebAuthn)를 적극적으로 도입해야 합니다. 패스키는 수백 줄의 코드로 구현 가능하며, 사용자 경험을 개선하고 애플리케이션의 전반적인 보안 수준을 크게 향상시킬 수 있습니다. 또한, 유사 모드와 강력한 비밀번호 정책 등 추가적인 보안 조치들을 함께 적용하여 사용자 자산을 보호하는 것이 중요합니다.

댓글 0

로그인이 필요합니다

댓글을 작성하거나 대화에 참여하려면 로그인이 필요합니다.

로그인 하러 가기

아직 댓글이 없습니다

첫 번째 댓글을 작성해보세요!