스웨덴 은행 ID는 스웨덴 거주자 전체는 아니더라도 대부분이 인터넷 제공업체, 온라인 뱅킹 서비스, 베팅 웹사이트, 특히 정부 웹사이트와 같은 여러 서비스에 인증하는 데 사용하는 디지털 ID 형식입니다.
스웨덴에 살면서 항상 해커 사고방식이 머릿속에 맴돌고 있는 저는 이 분야가 보안 연구를 하기에 매우 흥미로운 분야가 될 것이라고 결정했습니다.
이 게시물에서는 BankID 인증 프로토콜의 안전하지 않은 구현으로 인해 대부분의 스웨덴 서비스 제공업체에 존재하는 새로운 취약점을 소개하겠습니다.
이러한 프로토콜의 작동 방식, 취약한 구성의 모양, 이를 악용하는 방법, 해결 방법 및 마지막으로 이러한 유형의 공격이 eID의 전체 구현에 의미하는 바를 간략하게 살펴보겠습니다.
BankID는 사용자의 기기에 설치되는 서비스로, 개인 재정 코드인 스웨덴 영숫자(Persunnumer )가 있는 경우 스웨덴 은행에 요청하여 얻을 수 있습니다. 애플리케이션은 사용자의 장치에 설치되고 재정 코드에 연결되어 본질적으로 해당 애플리케이션에 사용자의 신원을 연결합니다. 이는 종종 전자 식별 시스템이 작동하는 방식입니다. 정부가 승인하고 신뢰할 수 있는 제3자가 특정 개인과 관련된 소프트웨어를 배포한 다음 서비스가 해당 소프트웨어 제공업체와 통합되어 사용자가 자신의 개인 정보를 인증할 수 있도록 합니다. 플랫폼은 서비스가 사람들을 쉽게 인증할 수 있도록 하는 공유 신뢰 모델입니다.
BankID는 다르지 않으며 앞으로는 RP(Relying Party)라고 하는 서비스에 대한 문서를 제공하므로 인증 흐름을 BankID와 쉽게 통합할 수 있습니다. https://www.bankid.com/en/utvecklare/guider/teknisk-integrationsguide/rp-introduktion .
BankID를 사용하면 사용자를 인증하는 데 두 가지 주요 흐름이 사용됩니다.
동일한 기기에서 인증
다른 기기에서 인증하기
이 두 가지 흐름을 곧 다시 살펴보겠습니다. 그러나 두 흐름 모두 RP가 인증 주문을 시작하기 위해 BankID의 API에 요청을 보내는 것으로 시작됩니다. 이 게시 요청에서 RP는 로그인을 시도하는 사용자의 IP가 포함된 endUserIp
매개변수를 지정해야 합니다. 이는 나중에 보고서에서 중요합니다.
/auth
API 엔드포인트는 다음과 같이 응답합니다.
HTTP/1.1 200 OK Content-Type: application/json { "orderRef":"131daac9-16c6-4618-beb0-365768f37288", "autoStartToken":"7c40b5c9-fa74-49cf-b98c-bfe651f9a7c6", "qrStartToken":"67df3917-fa0d-44e5-b327-edcc928297f8", "qrStartSecret":"d28db9a7-4cde-429e-a983-359be676944c" }
orderRef
RP가 /collect
엔드포인트에 대해 사용하여 인증 상태를 확인하고 나중에 해당 사람으로부터 필요한 사용자 정보를 가져올 수 있는 식별자입니다.autoStartToken
클릭하면 BankID 앱이 열리고 사용자에게 자신을 인증하라는 메시지를 표시하는 딥 링크를 생성하기 위해 RP에서 사용하는 토큰입니다( 이는 매우 중요합니다 ). qrStartToken
및 qrStartSecret
아래에서 다루지만 수행되는 보안 연구에 엄격하게 중요하지는 않습니다.
사용자의 IP 외에도 RP는 BankID 애플리케이션에 표시될 텍스트 및 인증 요구 사항 을 포함하여 인증 순서에 대한 추가 매개변수를 지정할 수 있습니다.
인증 요구 사항 중에서 이 게시물에서 중점을 둘 항목은 인증서 정책 이라고 하며 이를 통해 RP는 두 흐름 중 사용자가 선택한 BankID와 통신할 수 있습니다.
사용자가 동일한 장치에서 BankID를 사용하여 인증되도록 선택하면 RP는 autoStartToken
사용하여 다음과 같은 딥 링크를 생성합니다 bankid:///?autostarttoken=7c40b5c9-fa74-49cf-b98c-bfe651f9a7c6&redirect=https://service.com/login
. 그런 다음 이 딥 링크는 사용자의 OS에 의해 선택되어 BankID 애플리케이션으로 전달됩니다.
이 흐름을 조사하는 동안 BankID 측에서 redirect
매개변수에 대한 유효성 검사가 없기 때문에 Open Redirect 취약점이 발견되었습니다. 이 추가 버그가 왜 세션 하이재킹 공격을 더욱 강력하게 만드는지 나중에 알아보겠습니다.
사용자가 다른 장치에서 BankID를 사용하여 인증되도록 선택하면 RP는 qrStartToken
및 qrStartSecret
사용하여 사용자가 자신의 Mobile BankID를 사용하여 스캔할 수 있는 동적 QR 코드(앞서 언급한 /collect
엔드포인트에서 다음 프레임의 데이터를 가져옴)를 생성합니다. 애플리케이션.
이는 인증 주문을 시작할 때 RP에 의해 지정되어야 하며 , 피싱을 완화하기 위해 흐름이 일치하지 않는 경우 BankID가 인증 시도를 거부할 수 있도록 허용합니다. 예를 들어, 사용자가 "동일 장치에서 인증"을 선택한 경우 RP는 이를 BankID에 전달하여 Mobile BankID 및/또는 QR 코드를 사용하여 인증을 시도하는 경우 애플리케이션이 이를 거부할 수 있도록 해야 합니다.
이 외에도 인증이 완료되면 RP는 /collect
API 엔드포인트에서 BankID의 애플리케이션을 여는 데 사용된 ipAddress
가져올 수 있습니다. 그런 다음 사용자가 "동일 장치에서 인증"을 선택한 경우 RP의 사용자 IP 주소와 비교하여 이를 확인 해야 합니다 .
인증 흐름이 변조될 수 없도록 하기 위해 ipAddress
와 함께 인증서 정책을 사용해야 합니다 .
그럼에도 불구하고 이러한 보안 조치가 시행되는 동안 BankID는 그 중요성을 설명하지 못하고 제공된 예제 구현에서도 이를 올바르게 구현하지 않습니다! https://github.com/BankID/SampleCode
그렇다면 이 프로토콜이 안전하게 구현되지 않으면 어떻게 될까요?
처음 bankid:///
딥링크를 봤을 때 저는 BankID로 로그인하여 액세스할 수 있는 대학 지원서를 탐색하고 있었습니다. 처음에는 '이 딥링크를 누군가에게 보내면 어떻게 될까?'라고 생각했습니다. 그래서 나는 그것을 클릭한 내 친구에게 보냈고, 그가 BankID를 열었을 때 놀랍게도 내 앞에 그의 모든 대학 지원서가 있었습니다!
그때부터 나는 BankID의 API를 조사하기 시작했고, 내 자신의 RP를 구현했으며, 방금 설명한 모든 사항에 대해 배웠습니다.
몇 주간의 연구 끝에 저는 30RP가 넘는 bankid:///
딥 링크 수집을 자동화하는 스크립트를 개발했습니다. 이 스크립트는 사용자가 해당 링크를 방문할 때 웹 서버를 시작하고 각 서비스에 대한 경로를 생성합니다. 특정 서비스에 대해 스크립트는 새로운 링크를 가져와 사용자를 해당 링크로 리디렉션합니다. 이로 인해 사용자의 기기에서 BankID 앱이 열리게 되고, 인증 시 사용자 대신 내가 인증됩니다.
제가 이 일을 할 수 있었던 이유는 다음과 같습니다.
RP가 BankID에 인증서 정책을 보내지 않았기 때문에 딥 링크를 가져와 Mobile BankID 앱에 전달할 수 있었습니다.
RP는 링크를 요청한 IP 주소와 인증을 완료한 IP 주소를 비교하지 않았습니다.
"다른 장치에서 인증" 옵션을 선택한 경우에도 RP가 링크를 제공했습니다.
이로 인해 세션 고정 취약점이 발생했습니다.
AmazingSevice AB라는 취약한 서비스가 제공된 샘플 코드에 따라 BankID 흐름을 구현했으며 이러한 구현을 https://amazingservice.se/login/bankid
에서 호스팅하고 있다고 가정해 보겠습니다.
위협 행위자는 AmazingSevice AB에 저장된 사용자 데이터에 관심이 있으며 피해자를 눈에 띄게 합니다. 그는 단순히 bankid:///
링크 수집을 자동화하고 이를 자신의 서버에 호스팅한 다음 악의적인 서버에 대한 링크를 피해자에게 보내면 됩니다. 피싱 좋아요 전달(SMS, 이메일 등)을 선택한 후 그는 AmazingSevice AB로 가장하여 메시지에 링크를 삽입하고 피해자에게 로그인을 요청합니다.
이러한 계정 탈취에는 사회 공학이 거의 포함되지 않습니다. 피해자가 링크를 클릭하면 즉시 BankID를 열라는 메시지가 표시되고 공격자 사이트의 "알 수 없는 영역"을 떠나 훨씬 더 친숙한 인터페이스인 BankID가 사용되기 때문입니다. 또한 피해자가 BankID 애플리케이션에서 보게 되는 인증 요청은 AmazingSevice AB에서 요청하므로 사기 행위를 탐지하는 것이 불가능합니다.
피해자가 인증되면 공격자의 세션이 피해자의 계정에 대해 인증됩니다. BankID에 존재하는 Open Redirect 취약점을 악용하여 공격자가 redirect
매개변수를 https://amazingservice.se/login/bankid
으로 지정할 수 있도록 피해자를 더욱 속일 수 있습니다. https://amazingservice.se/login/bankid
. 이로 인해 피해자는 합법적인 서비스 웹사이트로 리디렉션되어 인증이 성공하지 못했다고 생각하게 됩니다.
나는 분명한 이유로 내가 보고한 회사 중 하나를 사용할 수 없었기 때문에 대신 데모에서는 BankID의 데모 서비스가 이에 취약하다는 것을 보여줍니다!
오른쪽 모서리에는 링크를 받은 피해자의 모습이 있는데, 여기서는 공격자의 웹사이트를 방문하여 시뮬레이션합니다. 피해자가 링크를 방문하면 공격자의 서버는 헤드리스 브라우저를 열고 bankid:///
링크를 추출한 다음 피해자의 휴대폰으로 전달합니다. BankID 앱에서는 BankID 데모 사이트의 합법적인 출처인 "Test av BankID"를 볼 수 있습니다. 또한, 영상 시작 부분에는 VPN을 켜서 인증 시 IP 주소 확인이 이루어지지 않는 것을 확인합니다. 결국, 공격자의 노트북에는 피해자(요한 요한슨)로 로그인되어 있는 것을 확인할 수 있다.
Session Fixation 버그는 Swedish BankID를 인증 공급자로 사용하고 인증서 정책과 ipAddress
확인을 잘못 구현한(또는 전혀 구현하지 않은) 애플리케이션에서 원클릭 계정 탈취를 발생 시킵니다. 사용자를 인증하기 위해 BankID를 사용하는 서비스가 매우 민감한 데이터 및 활동에 액세스하는 경우가 많기 때문에 이는 매우 심각한 문제입니다. 30개 이상의 애플리케이션이 이 공격에 취약한 것으로 밝혀졌으며, 가능한 한 많은 애플리케이션에 연락하여 주요 플랫폼 전반에 걸쳐 11개의 버그 바운티 보고서가 승인되었습니다.
이 취약점을 보고한 서비스 중 하나를 통해 문제가 얼마나 광범위하고 심각한지 스웨덴의 국가 CSIRT에 연락할 수 있었습니다. 대화가 막 시작되었습니다. 업데이트를 받고 싶다면 Twitter(X) @m4st3rspl1nt3r 에서 저를 팔로우하세요.
안전한 BankID RP API 구현이 어떤 모습인지 보여주는 예를 찾고 계시다면 Golang 라이브러리로 사용하거나 마이크로서비스로 사용자 정의 및 배포할 수 있는 예를 만들었습니다. 여기서 찾을 수 있습니다.
영향을 받은 대부분의 서비스, 특히 BBP 및 VDP가 있는 서비스는 내 보고서에 매우 수용적이고 신속하게 응답했습니다. 하지만 뱅크아이디의 반응은 조금 달랐다. 다양한 채널을 통해 여러 번 연락한 후 받은 이메일에서 그들은 문제를 알고 있지만 RP의 "통합 용이성"을 유지하기 위해 할 수 있는 일이 많지 않다고 설명했습니다. 불행하게도 여전히 RP 측에서 변경이 필요한 계획된 완화가 다음과 같이 나에게 전달되었습니다(그러나 어떤 이유로 문서 어디에도 찾을 수 없습니다).
RP가 설정할 수 있는 추가 요구 사항은 위험입니다. 이는 거래에 대해 허용 가능한 위험 수준을 설정합니다. 거래 위험이 필수 한도보다 높으면 거래가 차단됩니다. "낮음" - 위험도가 낮은 주문만 수락합니다. "모더레이트" - 설정된 경우 위험도가 낮고 중간 정도인 주문을 수락합니다. RP가 제공하는 경우 무엇보다도 당사 측에서 IP 확인을 수행합니다. 제공되는 경우 위험이 모니터링되는 다른 위험 매개변수로는 ReferingDomain, userAgent 및 deviceIdentifier가 있습니다.
또한 Open Redirect 취약점을 수정하려는 계획도 마련되어 있습니다.
이에 대한 내 개인적인 의견 은 매우 민감한 사용자 정보를 보호하는 데 종종 사용되는 중요하고 채택률이 높은 인증 공급자를 개발하고 운영하는 경우 RP가 안전하게 통합할 수 있도록 보안 메커니즘을 적절하게 문서화해야 한다는 것입니다. 선택적 보안 기능은 완전히 쓸모가 없습니다. 개발자가 특정 기능/매개변수를 구현하지 않고 시간을 절약할 수 있다면 그런 일이 일어날 것이며 우리는 이를 RP 측에서 비난할 수 없습니다. BankID는 "통합의 용이성"을 유지하기 위해 최대한 많은 사기 방지 및 보안 기능을 제공하기 위해 최선을 다해야 하지만 RP가 구현해야 하는 추가 보안 기능을 적절하게 문서화해야 합니다. 선택사항 이 아닌 필수사항에 주의하세요.
블로그의 이 부분은 순전히 내 의견입니다.
나에게 있어서 이 취약점은 민간 기업이 국가 국민에게 중요한 시스템을 완전히 통제하도록 허용하는 것이 얼마나 위험한지를 보여주는 예입니다. 이것이 소프트웨어 회사의 또 다른 취약점보다 더 심각하다고 생각하는 이유는 BankID가 850만 명 이상의 스웨덴 거주자가 사용하는 것이며 은행, 보험사, 전기 공급자 및 기타 민감한 플랫폼에 로그인하는 데 사용되기 때문입니다. 실제 결과를 가져옵니다.
누군가가 Facebook에서 계정 탈취를 발견하면 일부 사진이 손실될 수 있습니다. 누군가가 해당 국가의 eID 제공업체(종종 비공개)에서 취약점을 발견하면 누군가의 삶에 미치는 영향은 상상할 수 없을 수 있습니다.
점점 더 많은 유럽 국가에서 eID를 채택하고 있으며 EU는 향후 몇 년 내에 자체 EU eID를 출시할 계획입니다(자세한 내용은 여기에서 확인할 수 있습니다).
나는 규제 당국이 eID 제공업체가 공공 기관에 의해 완전히 개발되고 통제되도록 추진하고, 그러한 시스템이 오픈 소스여야 하고 정기적으로 보안 결함에 대한 감사를 받아야 한다는 것을 희망합니다.
우리 사회에서 이렇게 중요한 소프트웨어를 민간 기업이 개발한다면 어떻게 안전하게 받아들일 수 있을까요?
이 블로그 게시물의 주요 주제는 BankID에 대한 세션 고정 공격이었지만, 다른 많은 인증/식별 제공업체도 모두 동일한 결함으로 설계되었음을 발견했습니다. 인증 흐름을 완료하기 위해 다른 장치(종종 휴대폰)를 사용해야 하는 공급자에서 새로운 취약성 클래스가 발견될 수 있습니다.
연구가 진행 중이며, 곧 더 많은 결과와 이러한 취약점을 자동화하고 악용하는 데 사용할 수 있는 도구를 공개할 수 있기를 바랍니다. 다음 주제인 Session Fixation by Design - Cross-Device Authentication Nightmares를 계속 지켜봐 주시기 바랍니다.
그때까지 행성을 해킹하세요!