다중 인증(MFA)은 아는 것, 가진 것, 본인의 신체적 특성 가운데 서로 다른 종류의 증거를 두 가지 이상 요구하는 로그인 통제 수단입니다. 서로 다른이라는 말이 핵심인데도 자주 잘못 이해됩니다. 비밀번호에 보안 질문을 더한 것은 하나의 범주, 즉 지식에서 나온 두 가지 증거일 뿐이므로 MFA가 전혀 아닙니다. 요점은 조합에 있습니다. 피싱당한 비밀번호는 사용자의 휴대폰을 갖고 있지 않고, 도난당한 휴대폰은 사용자의 PIN을 알지 못합니다. 어느 요소를 훔치든 공격자에게는 범주 하나가 모자랍니다.
핵심 요약
| 질문 | 답변 |
|---|---|
| 요소 | 아는 것(비밀번호) · 가진 것(디바이스, 키) · 본인의 특성(생체 인식) – 서로 다른 범주에서 |
| MFA vs. 2FA | 2FA = 정확히 두 개, MFA = 두 개 이상, 개수보다 품질이 중요합니다 |
| 순위 | SMS < TOTP < 푸시 < 푸시 + 번호 매칭 < 패스키 / 보안 키 |
| 분기점 | 피싱 방지: 코드는 중계될 수 있지만, 출처에 묶인 암호화는 중계될 수 없습니다 |
| 약한 고리 | 복구 – 재설정 흐름은 그것이 우회하는 로그인만큼 강해야 합니다 |
TOTP의 실제 동작 방식
인증 앱의 원리를 풀어 보면 다음과 같습니다. 검색 상위 페이지들은 이 메커니즘을 설명하지 않습니다(RFC 6238):
등록 QR 코드 = otpauth://totp/app:ada?secret=JBSWY3DP…
→ 이제 앱과 서버가 Base32 비밀 값(SECRET)을 공유
30초마다 양쪽이 각자 독립적으로, 오프라인에서 계산:
code = truncate( HMAC-SHA1( secret, floor(unix_time / 30) ) ) % 10⁶
로그인 사용자가 앱의 6자리를 입력하면 서버도 자체적으로 계산하고,
시계 오차를 고려해 ±1 시간 창까지 허용 → 일치 = 소유 증명
이를 앱의 로그인 흐름에 연결하면 다음과 같습니다:
// JavaScript / Node.js — Back4app JS SDK
// TOTP step-up with the Parse Server mfa auth adapter
// Enroll: prove possession by sending one valid code with the secret
await currentUser.save({
authData: { mfa: { secret: totpSecret, token: codeFromApp } },
});
// server returns single-use recovery codes — show once, store nowhere
// Log in afterwards: password + the current 6-digit code
const user = await Parse.User.logIn('ada', password, {
authData: { mfa: { token: codeFromApp } },
}); // Flutter / Dart — Back4app Flutter SDK
// TOTP step-up with the Parse Server mfa auth adapter
// Enroll: prove possession by sending one valid code with the secret
currentUser.set('authData', {
'mfa': {'secret': totpSecret, 'token': codeFromApp},
});
await currentUser.save();
// server returns single-use recovery codes — show once, store nowhere
// Log in afterwards: password + the current 6-digit code
final user = ParseUser('ada', password, null)
..set('authData', {'mfa': {'token': codeFromApp}});
await user.login(); // iOS / Swift — Back4app Swift SDK
// TOTP step-up with the Parse Server mfa auth adapter
// Enroll: prove possession by sending one valid code with the secret
let enrolled = try await currentUser.link("mfa",
authData: ["secret": totpSecret, "token": codeFromApp])
// server returns single-use recovery codes — show once, store nowhere
// Log in afterwards: password + the current 6-digit code
let user = try await User.login("ada", password: password,
authData: ["mfa": ["token": codeFromApp]]) // Android / Kotlin — Back4app Android SDK
// TOTP step-up with the Parse Server mfa auth adapter
// Enroll: prove possession by sending one valid code with the secret
val enroll = mapOf("secret" to totpSecret, "token" to codeFromApp)
ParseUser.getCurrentUser().linkWithInBackground("mfa", enroll)
// server returns single-use recovery codes — show once, store nowhere
// Log in afterwards: password + the current 6-digit code
val authData = mapOf("token" to codeFromApp)
ParseUser.logInWithInBackground("mfa", authData) // paired with the password check MFA vs. 2FA
| 2FA | MFA | |
|---|---|---|
| 요소 수 | 정확히 두 개 | 두 개 이상 |
| 관계 | MFA의 부분집합 | 상위 개념 |
| 실제 | 대부분의 배포가 실제로 해당하는 것 | 대부분의 배포를 부르는 이름 |
표 하나로 정리됩니다. 더 중요한 질문은 어떤 요소인가입니다. 보안의 상한을 정하는 것은 증거를 몇 개 쌓느냐가 아니라 그중 하나라도 피싱당할 수 있느냐이기 때문입니다.
방법별 순위, 정직하게
CISA 지침은 공개하지만 벤더의 설명 자료는 다루지 않는 비교, 즉 어떤 공격이 어떤 방법을 무너뜨리는지입니다:
| 방법 | 피싱 / 실시간 프록시 | SIM 스와핑 | 푸시 폭탄 공격 | 오프라인 가능? | 결론 |
|---|---|---|---|---|---|
| SMS / 음성 코드 | 뚫림 | 뚫림 | 해당 없음 | 아니요 | 최후의 수단 – NIST가 제한 |
| 이메일 코드 | 뚫림 | 안전 | 해당 없음 | 아니요 | 받은편지함의 보안 수준을 그대로 물려받음 |
| TOTP 앱 | 뚫림 | 안전 | 해당 없음 | 예 | 탄탄한 기준선 |
| 푸시 승인 | 뚫림 | 안전 | 뚫림 | 아니요 | 편리하지만 폭탄 공격에 취약 |
| 푸시 + 번호 매칭 | 뚫림 | 안전 | 저항 | 아니요 | 약점을 보완한 편의성 |
| 패스키 / 보안 키 | 저항 | 안전 | 해당 없음 | 예 | 최고 기준(WebAuthn) |
가장 왼쪽 공격 열에 나타난 패턴이 오늘날의 이야기입니다. 모든 코드와 승인은 피싱 프록시를 통해 중계될 수 있으며, 가짜 로그인 페이지와 맞닥뜨리고도 살아남는 것은 출처에 묶인 암호화뿐입니다.
공격, 쉬운 말로
중간자(AitM) 피싱: 오픈소스 프록시 키트가 피해자와 진짜 사이트 사이에 자리 잡고 비밀번호와 일회용 코드를 실시간으로 중계한 뒤, 그 결과로 생긴 세션 쿠키를 차지합니다. MFA는 “통과”했지만 계정은 빼앗깁니다. 푸시 폭탄 공격: 훔친 비밀번호로 승인 요청을 쏟아부어, 지친 사용자가 한 번 누르게 만듭니다. 번호 매칭(화면에 표시된 숫자를 입력하는 방식)은 생각 없이 승인하는 경로를 없앱니다. SIM 스와핑: 통신사를 설득해 피해자의 번호를 옮긴 뒤 SMS 코드를 받아 냅니다. SMS를 표의 맨 아래로 끌어내린 공격입니다. 공통점은 이렇습니다. 이 공격들은 누군가에게 말해 줄 수 있는 요소를 무너뜨리며, 진짜 출처와만 암호학적으로 대화하는 요소 앞에서는 모두 실패합니다.
복구 문제
모든 MFA 도입은 두 번째 문을 만듭니다. 휴대폰을 잃어버리면 어떻게 됩니까? 백업 코드(일회용이며, 등록 시 생성되고, 오프라인에 보관)가 표준 답안이고, 계정 복구 흐름은 위험한 답안입니다. 헬프데스크 전화나 이메일 재설정으로 MFA를 제거할 수 있다면 공격자는 헬프데스크에 전화합니다. 크게 보도된 침해 사고의 배후에 있던 기법이며, 이렇게 가장 강한 통제가 가장 약한 절차에 의해 무력화됩니다. 규칙은 이렇습니다. 복구는 그것이 대체하는 로그인과 같거나 더 높은 보증 수준을 요구해야 합니다. 여러 개의 등록된 방법, 재설정 시의 단계적 검증, 그리고 MFA 제거를 권한이 필요하고 기록되며 경보를 발생시키는 이벤트로 취급하는 것입니다.
MFA의 실제 효과
자주 혼동되는 두 가지 참인 주장이 있습니다. 크리덴셜 스터핑, 비밀번호 스프레잉 같은 자동화된 공격에 대해 MFA는 거의 완벽합니다. 유명한 99% 수치는 바로 그런 공격을 측정한 대규모 로그인 원격 측정 데이터에서 나왔고, 동료 심사를 거친 후속 연구도 같은 범위에서 약 99%의 침해 감소를 확인했습니다. 반면 실시간 프록시를 동원한 표적 피싱에 대해서는 코드 기반과 푸시 기반 MFA가 우회될 수 있음이 입증되었습니다. 그래서 비판자들은 모든 공격을 아우르는 효과를 훨씬 낮게 평가하며, 정부 기관들도 이제 특별히 피싱 방지 방식을 권장합니다. 정직하게 종합하면 이렇습니다. 어떤 MFA든 비밀번호만으로 충분하던 시대를 끝내지만, 피싱을 끝내는 것은 패스키 수준의 MFA뿐입니다. 모든 곳에 어떤 MFA든 배포하고, 등록의 마찰을 감수할 만큼 위험이 큰 곳에는 피싱 방지 MFA를 배포해야 합니다.
일반적인 사용 사례
- 계정 발급 보호 – MFA는 세션과 토큰이 발급되는 순간을 지키며, 그 뒤의 모든 것은 이 관문을 신뢰합니다.
- 민감한 동작에 대한 단계적 인증 – 로그인 때만이 아니라 결제, 삭제, 키 내보내기 시점에 다시 확인합니다.
- 관리자 및 특권 계정 – MFA가 예외 없이 필수여야 하고 피싱 방지 방식이어야 하는 곳입니다.
- 규정 준수 체계 – 결제, 의료, 공공 부문의 프레임워크는 점점 더 MFA를 명시적으로 요구합니다.
- 소셜 로그인 보완 – ID 공급자에게서 물려받거나, 가치가 높은 동작에 대해 로컬에서 강제합니다.
어떤 MFA 방법을 제공해야 할까? 결정 매트릭스
| 상황 | 제공할 방법 |
|---|---|
| 일반 사용자층, 다양한 디바이스 | 기준선으로 TOTP + 권장 경로로 패스키 |
| 가치가 높은 계정이나 관리자 계정 | 피싱 방지 방식만 – 패스키 / 보안 키 |
| 스마트폰이 없는 사용자 | 기본값 SMS가 아니라 하드웨어 키나 인쇄된 백업 코드 |
| 레거시 사용자층, 다른 대안이 없음 | SMS – 한계를 인식한 채, 표준이 아닌 최저선으로 |
| 앱 내 민감한 동작 | 로그인 요소와 관계없이 단계적 재인증 |
| 복구 설계 | 최소 두 개의 등록된 방법 + 오프라인 코드 |
한계와 트레이드오프
- 마찰은 실재하며 측정 가능합니다. 모든 확인 요청은 전환율과 지원 티켓이라는 비용을 치릅니다. 위험 기반의 적응형 요청은 위험이 있는 곳에만 마찰을 씁니다.
- 피싱 가능한 MFA의 효과는 보기보다 작습니다. 표적 프록시 공격 앞에서 코드와 푸시는 무너집니다. 이들은 피싱 방어구가 아니라 자동화 공격 차단 수단으로 취급해야 합니다.
- 휴대폰은 단일 장애점입니다. 복구 계획 없는 디바이스 분실은 대규모 계정 잠김으로 이어집니다. 등록 UX는 첫날부터 백업 방법을 심어 두어야 합니다.
- 복구 흐름은 계산을 뒤집습니다. 약한 재설정 경로는 전체 체계의 강도를 소리 없이 자신의 수준으로 끌어내립니다.
- 등록은 도입의 절벽입니다. 매끄러운 QR 흐름과 명확한 대체 수단 없이 강제하면 반발을 낳습니다. 최선의 체계는 사용자가 실제로 끝까지 완료하는 체계입니다.
Back4app에서의 MFA
Back4app은 관리형 데이터베이스, 자동 생성되는 REST 및 GraphQL API, 인증, 파일 스토리지, Cloud Code 서버리스 함수를 결합한 오픈소스 Backend as a Service(BaaS) 플랫폼입니다. TOTP는 구축이 아니라 설정으로 제공됩니다. Back4app의 mfa 인증 어댑터는 설정 블록 하나로 시간 기반 코드를 활성화하며, 자릿수, 주기, 알고리즘을 조정할 수 있습니다. 코드 탭은 클라이언트 쪽의 전체 과정을 보여 줍니다. 등록 단계에서는 공유 비밀 값과 유효한 코드 하나를 짝지어 소유를 증명하고, 서버는 일회용 복구 코드를 발급하며, 이후의 로그인은 비밀번호와 현재의 6자리 숫자를 함께 제시합니다. 플랫폼의 세션은 서버 측에서 폐기할 수 있으므로 주변의 보안 위생도 함께 유지됩니다. MFA 설정이 바뀌면 다른 세션을 즉시 종료할 수 있고, Cloud Code 트리거는 등록 이벤트를 기록하고 MFA 제거를 단계적 인증 검사 뒤에 두기에 자연스러운 위치입니다. 이 글이 주장하는 복구 규율을 몇 개의 함수로 표현한 것입니다.
자주 묻는 질문
MFA를 쉽게 설명하면 무엇입니까?
서로 다른 종류의 증거를 두 가지 이상 요구하는 로그인 방식입니다. 예를 들어 비밀번호와 휴대폰으로 받은 코드를 함께 요구하므로, 비밀번호를 도난당해도 그것만으로는 아무것도 열리지 않습니다. 증거는 서로 다른 범주에서 나와야 합니다. 비밀번호에 보안 질문을 더한 것은 여전히 하나의 요소를 두 번 쓴 것에 불과합니다.
MFA와 2FA의 차이는 무엇입니까?
범위의 차이입니다. 2FA는 정확히 두 개의 요소를, MFA는 두 개 이상의 요소를 뜻합니다. 모든 2FA는 MFA이며, 실제로 대부분의 MFA 배포는 2FA입니다. 개수보다 품질이 더 중요합니다. 피싱 방지 요소 두 개가 피싱 가능한 요소 세 개보다 낫습니다.
인증의 세 가지 요소는 무엇입니까?
아는 것(비밀번호, PIN), 가진 것(휴대폰, 하드웨어 키), 본인의 신체적 특성(지문, 얼굴)입니다. 위치와 행동은 보조 신호로 쓰이지만, 그 자체로 독립된 요소가 되기보다는 위험 기반의 적응형 검사를 작동시키는 역할을 합니다.
SMS 2단계 인증은 안전합니까?
비밀번호만 쓰는 것보다는 낫지만, 흔히 쓰이는 방법 가운데 가장 약합니다. SIM 스와핑, 통신 프로토콜 가로채기, 평범한 피싱 모두에 뚫립니다. 표준 기관들은 수년 전부터 SMS 사용을 제한해 왔으며, 현재 정부 지침은 단호합니다. 더 강력한 수단이 있다면 SMS를 두 번째 요소로 사용해서는 안 된다는 것입니다.
TOTP 인증 앱은 어떻게 동작합니까?
등록 시 QR 코드가 앱에 공유 비밀 값을 전달합니다. 그 뒤로 앱과 서버는 그 비밀 값과 현재의 30초 시간 창으로 각자 독립적으로 코드를 계산하며, 코드가 일치하면 소유가 증명됩니다. 완전히 오프라인으로 동작합니다. 네트워크도, 앱 제작사의 계정도 필요 없고, 동기화된 시계와 수학만 있으면 됩니다.
패스키가 MFA를 대체합니까?
대부분의 계정에서는 사실상 그렇습니다. 패스키는 한 번의 동작으로 끝나는 다중 인증으로, 디바이스의 소유와 그 디바이스를 잠금 해제하는 생체 인식 또는 PIN이 결합됩니다. 게다가 서명이 진짜 사이트에서만 유효하므로 피싱 방지 기능도 갖춥니다. 높은 보증 수준이 필요한 환경에서는 그 위에 별도의 요소를 더할 수도 있습니다.
피싱 방지 MFA란 무엇입니까?
가짜 사이트를 통해 중계될 수 없는 MFA입니다. 코드와 푸시 승인은 실시간으로 프록시될 수 있지만, 공개 키 방식, 즉 WebAuthn 기반의 패스키와 하드웨어 보안 키는 응답을 실제 도메인에 암호학적으로 묶습니다. 그래서 유사 사이트가 받아 내는 서명은 다른 어디에서도 쓸모가 없습니다.
MFA 피로 공격이란 무엇입니까?
푸시 폭탄 공격입니다. 비밀번호를 훔친 공격자가 지친 피해자가 승인을 누를 때까지 승인 요청을 계속 보내는 방식으로, 여러 유명한 침해 사고의 배후에 있던 수법입니다. 완화책은 순서대로 승인 요청에 번호 매칭 적용, 시도 횟수 제한, 그리고 궁극적으로 승인할 것이 아예 없는 방식으로의 전환입니다.