LY Corporation Tech Blog

LY Corporation과 LY Corporation Group(LINE Plus, LINE Taiwan and LINE Vietnam)의 기술과 개발 문화를 알립니다.

기기와 앱의 무결성 보장부터 서비스 요청 보호까지: LINE의 기기 증명 서비스 - 1편

들어가며

안녕하세요. Security R&D 팀의 김도연, 김영현, 박경준, 후바인 찰스, 안상환입니다. Security R&D 팀은 LY 그룹 서비스의 전반적인 보안을 강화하기 위해 보안 기술 연구 및 모듈 개발, 컨설팅 업무를 담당하고 있습니다. 이번 글에서는 사용자의 서비스 요청이 위변조되지 않은 기기와 앱에서 전송됐다는 것을 증명할 수 있는 기기 증명(device attestation) 서비스를 소개하고자 합니다.

기기 증명 서비스 개발 배경

LY의 서비스가 사회의 핵심 인프라가 되면서 이를 악용해 부정한 목적을 달성하려는 남용 사례도 함께 증가했습니다. 공격자들은 계정 탈취나 스패밍(spamming), 피싱(phishing), 사기 등을 목적으로 서비스를 이용하며, 이를 위해 자동화된 프로그램을 사용해 대량의 서비스 요청을 보내거나 앱을 변조해 악의적인 작업을 수행하기도 합니다.

그런데 기존의 소프트웨어 기반 보안 대책에는 허점이 있습니다. 우선 공격자가 루트 권한을 얻었다고 가정한 위협 모델에서는 공격자가 앱의 실행 결과를 얼마든지 조작할 수 있기 때문에 이를 보호하기 위한 자체 보안 검사를 올바르게 수행할 수 없습니다. 또한 공격자는 앱의 바이너리를 분석해 가짜 클라이언트를 만들어 서비스를 남용하기도 하는데요. 이런 가짜 클라이언트에서 발생한 요청은 정상적인 서비스 요청과 구별하기가 매우 어렵습니다. 게다가 최근 사용자 제작 콘텐츠의 양과 그 다양성이 폭발적으로 증가하면서, 이에 대응하기 위해서 대량의 다양한 콘텐츠와 광범위한 공격을 처리할 수 있는 포괄적이고 확장 가능한 남용 방지 대책이 필요해졌습니다.

이런 상황에서 각 서비스별로 개별적으로 대응하는 것에는 한계가 있기 때문에 근본적으로 어떤 기점에서 서비스 남용이 발생하는지에 집중할 필요가 있는데요. 저희는 비정상적인 요청의 대부분이 합법적인 기기 및 앱에서 생성된 것이 아니라는 점에 착안해 하드웨어 기반의 증명 방식을 도입, 신뢰할 수 없는 출처에서 발생한 서비스 요청을 근본적으로 차단하면서 기존의 남용 방지 대책과 조합해 그 효용성을 개선할 수 있는 기기 증명 서비스를 개발했습니다.

기기 증명 서비스는 Auth & Account Dev 팀과 Account Product App Dev 1 팀, Platform Product Management 팀과 협업해 2023년 12월에 LINE 서비스에 성공적으로 적용했으며, 다양한 형태의 서비스 요청 검증 및 모니터링에 활용하고 있습니다. 또한 금융 서비스와 같이 높은 보안 수준이 요구되는 서비스에 기기 증명 서비스를 통합하는 작업도 함께 진행하고 있습니다.

이제 기기 증명 서비스가 구체적으로 어떤 방식으로 작동하는지 자세히 살펴보겠습니다.

기기 증명 서비스의 목표 및 구조

기기 증명 서비스는 서버가 받는 사용자의 서비스 요청이 아래와 같다는 것을 증명하는 기능을 제공합니다.

  • 위변조되지 않은 기기와 앱에서 생성됨
  • 서비스 요청 또한 변조되거나 조작되지 않음

구체적으로, 기기 증명 서비스는 다음과 같은 사례에 해당하는 서비스 요청을 '잠재적으로 위험성이 높은 요청'으로 간주하고 모니터링해서 서비스 남용을 방지하는 것을 목표로 합니다.

기기 증명 서비스는 공개키 기반의 인증 시스템(Public Key Infrastructure, PKI)을 기반으로 하고 있습니다. 아래는 기기 증명 서비스를 간단히 도식화한 그림입니다.

  • 신뢰 실행 환경(trusted execution environment, 이하 TEE): 기기 내에 하드웨어적으로 격리돼 보안 관점에서 안전한 실행 환경을 통칭합니다. 이 환경에서 키 생성 및 생성된 키를 사용한 작업을 수행합니다. 기기 증명 서비스에서는 TEE에서 비대칭키를 생성하고 그 중 비밀키를 TEE에 저장하며, 이는 OS 레벨에서 절대 추출될 수 없습니다.
  • 기기 증명 클라이언트(device attestation client): 기기 증명 서비스를 제공하는 클라이언트 모듈입니다.
  • 기기 증명 서버(device attestation server): 기기 증명 서비스를 제공하는 서버 모듈입니다. TEE에서 생성된 비대칭키 중 공개키는 기기 증명 서버에 저장됩니다.

작동 방식을 간단히 설명하면, 먼저 기기 증명 클라이언트가 서비스 요청이 잠재적으로 위험성이 높은 요청인지 검증하기 위해 기기 증명 서비스에 필요한 데이터를 생성합니다. 이 과정에서 TEE는 TEE에서 생성된 비밀키로 서비스 요청을 서명해 서비스 요청의 합법성을 확보합니다. 기기 증명 클라이언트에서 생성된 데이터는 기기 증명 서버로 전송되며, 서버는 이 데이터를 검증해서 서비스 요청의 잠재적 위험 여부를 판단한 뒤 검증 결과를 기기 증명 클라이언트로 전달합니다.

위와 같은 방식으로 사용자가 앱에서 작업(로그인, 결제, 송금 등)을 실행하는 동안 서버에서 기기 증명 서비스를 이용해 사용자의 서비스 요청이 위변조되지 않은 합법적인 기기 및 앱에서 발생했는지 확인합니다. 만약 확인 결과 문제가 있는 경우, 서버는 이를 해결하기 위한 조치를 결정할 수 있습니다.

기기 증명 서비스는 Android에서 제공하는 키 증명(Key Attestation)과 iOS에서 제공하는 앱 증명(App Attest) 기능을 기반으로 구현했습니다. Android와 iOS 양쪽에서 일관된 보안 아키텍처를 구현하기 위해 WebAuthn 스펙을 기반으로 설계했으며, 라이브러리로도 제공하므로 앱/서버 개발자 기기 증명 기능을 서비스에 간단하게 통합할 수 있습니다.

다음으로 기기 증명 서비스에서 사용되는 인증 프로토콜인 증명(attestation)과 어설션(assertion)이 무엇인지 살펴보고, 클라이언트와 TEE, 서버 사이에서 어떤 프로세스로 진행되는지, 또한 이 과정에서 어떤 방식으로 위변조 여부를 검증할 수 있는지 기술적인 부분을 자세히 설명하겠습니다.

증명

증명은 인증에 사용되는 어설션 키(assertion key)를 등록하는 과정입니다. 키 생성 환경의 신뢰성을 보증하는 핵심 단계로 다음을 보장합니다.

  • 신뢰점(Root of Trust) 확인: 키가 기기의 보안 영역 안에서 생성되었다는 것을 기기의 신뢰점을 통해 증명합니다.
  • 기기 속성 식별: 사용 중인 기기의 특정 속성(개인 키 보호 방법, 부트 상태 검증 여부 등)을 식별합니다.

이를 통해 클라이언트는 생성된 어설션 키 쌍이 부트 레벨에서 변조되지 않은 순정 OS 및 Android의 ARM TrustZone이나 StrongBox 또는 iOS의 Secure Enclave와 같은 기기 내에서 하드웨어적으로 격리된 안전한 영역에서 생성됐다는 것을 입증합니다. 서버는 보안 수준이 높은 환경에서 키가 생성됐고, 기기가 루팅이나 탈옥 같은 보안 위협을 받지 않는 안전하고 신뢰할 수 있는 상태라는 것을 확인할 수 있습니다. 증명 과정에서 앱의 무결성에 대한 정보도 함께 전달돼 검증되므로 올바른 앱이 신뢰할 수 있는 환경에서 실행되고 있다는 것도 보장될 수 있습니다.

증명은 또한 서명을 통해 어설션 공개키가 서버로 전송되는 동안 위변조되지 않도록 보호하는 역할도 수행합니다. 이를 통해 키의 생성부터 전송까지 전 과정을 안전하게 관리하며 키의 무결성과 진위성을 보장합니다. 이러한 메커니즘을 통해 서버는 클라이언트의 요청이 신뢰할 수 있는 출처에서 온 것임을 확신할 수 있습니다.

증명 과정

증명 과정은 재전송 공격을 방지하기 위해 챌린지-응답 방식(Challenge-Response Protocol)을 통해 아래와 같은 흐름으로 서버와 상호 작용합니다.

  1. 클라이언트는 서버에게 챌린지를 요청해 전달받습니다. 이 값은 일회성으로 사용하는 랜덤값으로 재전송 공격을 막기 위해 필요합니다.
  2. 클라이언트는 TEE에서 비대칭키인 어설션 키 쌍을 생성합니다. 개인키는 해당 키의 생성을 요청한 앱만 사용할 수 있으며, 보안 수준이 높은 전용 하드웨어 안에서 생성 및 보호되기 때문에 해당 환경 밖에서 외부 코드로 읽거나 변조 및 조작할 수 없습니다.
    • Android: ARM TrustZone 또는 StrongBox에서 어설션 키 쌍과 인증서 체인을 생성합니다.
    • iOS: Secure Enclave(SE)에서 어설션 키 쌍만 생성합니다.
  3. 클라이언트는 어설션 공개키와 기기 및 앱과 관련된 정보들을 안전하게 서버까지 전달하기 위해 여러 가지 보안 메커니즘을 통해 증명 객체(attestation object)를 생성합니다. 증명 객체는 플랫폼별로 차이가 있으므로 자세한 설명은 아래 증명 객체 섹션의 내용을 참조하시기 바랍니다.
    • Android: 클라이언트는 TEE에서 생성된 어설션 키가 포함된 인증서의 목록과 챌린지를 포함한 여러 정보를 기반으로 생성한 서명(signature) 등으로 증명 객체를 생성합니다.
    • iOS: 클라이언트는 생성된 어설션 공개키와 여러 검증을 위한 정보를 Apple 서버로 전달하고 증명 객체 생성을 요청합니다. Apple 서버는 전달 받은 데이터를 검증합니다. 이상이 없다면 어설션 공개키 및 챌린지와 검증에 필요한 정보들의 조합을 SHA-256으로 해싱한 논스(nonce)를 담은 x.509 인증서를 생성합니다. 이 인증서를 포함한 인증서 체인은 증명 객체에 포함되며, 증명 객체는 최종적으로 클라이언트로 전달됩니다.
  4. 생성된 증명 객체를 서버로 전달합니다.
  5. 증명 객체를 전달받은 서버는 각 플랫폼별 루트 인증서로 증명 객체 내의 x.509 인증서 체인 전체의 유효성과 서명, 챌린지 값 및 앱의 서명값을 포함한 고유 정보들을 검증합니다. 이를 통해 전달받은 어설션 공개키가 신뢰할 수 있는 기기 및 변조되지 않은 앱에서 생성됐다는 것을 보장할 수 있습니다. 검증 결과에 문제가 없다면 최종적으로 어설션 키를 사용자 정보와 함께 등록하는 것으로 증명 과정은 완료됩니다.

x.509 인증서 체인 검증

어설션 키 쌍이 신뢰할 수 있는 전용 하드웨어에서 생성됐다는 것을 증명할 필요가 있습니다. 이 장치의 신뢰 루트 기반으로 생성된 인증서 체인을 검증함으로써 키의 진위성과 증명의 신뢰성을 보장할 수 있습니다.

증명 객체 내 x.509 인증서 체인은 크게 세 가지 인증서로 구성됩니다.

  • 리프 인증서(leaf certificate): 인증서 체인 내 최하위 인증서로 생성된 어설션 공개키를 포함하고 있습니다. 제조사가 주입한 기기의 증명 키(attestation key)로 서명되고, 상위 인증서(Intermediate certificate)로 진위를 확인할 수 있습니다.
  • 중간 인증서(intermediate certificate):  기기 내 주입된 증명 키의 정보를 포함하고 있습니다. Android 8~12 버전의 경우 이 키를 제조사가 관리하며, CA(certificate authority, 인증기관)가 발행한 최상위 인증서(루트 인증서)로 진위를 확인할 수 있습니다. 최신 Android 버전과 iOS의 경우 Google과 Apple이 각각 중간 인증서와 최상위 인증서를 관리하여 보안을 강화하고 있습니다.
  • 루트 인증서(root certificate): CA에서 증명 루트 키(attestation root key)로 자체 서명한 최상위 인증서로, AppleGoogle이 CA가 됩니다.

인증서 체인은 어설션 키 정보가 포함된 최하위 인증서(리프 인증서)에서 시작해 루트 인증서로 끝나는 인증서 목록으로 구성됩니다. 각 인증서는 그 상위 단계의 인증서로 검증하는 과정을 반복하며 루트 인증서에 도달할 때까지 계속해서 역추적합니다. 이 과정을 통해 루트 인증서까지 성공적으로 검증되면 어설션 키가 신뢰할 수 있는 기기 및 변조되지 않은 앱에서 생성된 것임을 보장할 수 있습니다.

증명 객체

증명 객체(attestation object)는 증명에 필요한 인증 데이터를 담고 있는 데이터 구조입니다. FIDO2 WebAuthn에서 정의한 증명 객체 구조를 따르며 아래 그림과 같습니다.

iOS는 AppAttest API를 통해 이미 WebAuthn의 증명 객체 형식으로 직렬화된 데이터를 반환하는 반면, Android는 생성된 키에 대한 인증서 체인 자체를 반환합니다. 따라서 형식 불일치가 발생하는데요. 저희는 서버 로직을 최대한 통합하고 두 플랫폼의 요청을 모두 처리할 수 있도록 Android에서도 같은 구조의 증명 객체를 사용하기로 결정했습니다.

증명 객체의 기본 구조는 Android와 iOS 모두 크게 세 가지로 나뉩니다.

  • attStmt: 증명문(attestation statement)입니다. 위변조되지 않은 기기에서 키가 생성됐다는 것을 보장하는 인증서 체인(certificate chain, x5c)과 인증자 데이터(authData) 및 챌린지를 개인키로 서명한 값이 포함돼 있습니다. 이후 서버는 증명 객체를 검증할 때 인증서 체인을 검증해 위변조되지 않은 기기에서 키가 생성됐다는 것을 확인하고, 인증자 데이터를 공개키로 검증해 인증 데이터가 변조되지 않았다는 것을 확인합니다.
  • fmt: 증명문 형식(attestation statement format)입니다. "packed", "tpm", "android-key", "android-safetynet", "fido-u2f", "none", "apple" 등의 값이 들어가며, 증명문 형식의 값에 따라 attStmt의 형식이 달라집니다.
  • authData: 인증자 데이터(authenticator data)로, 어설션 공개키 및 증명 과정과 관련된 데이터가 들어갑니다.

fmt는 플랫폼 및 인증자에 따라 그 값이 다릅니다. 기기 증명 서비스의 인증자에서 증명 객체의 fmt은 Android의 경우 android-key를 사용하며, iOS에서는 apple-appattest를 사용합니다.

fmt에 따라 달라지지만, attStmt의 형식은 기본적으로 alg와 sig, x5c의 세 가지로 구성됩니다.

  • alg: 알고리즘은 P256 타원 곡선을 기반으로 한 ECDSA인 ES256을 사용합니다(iOS는 이 필드가 존재하지 않습니다).
  • sig: authData와 챌린지 등을 조합해 어설션 개인키로 서명한 값입니다.
    • Android: 이 값을 통해 증명 객체 내의 데이터가 위변조되지 않았음을 보장합니다.
    • iOS: 이 필드가 존재하지 않습니다. 대신 authData와 챌린지의 해시를 결합한 뒤 다시 해시해 생성된 nonce 값을 x.509 인증서 안에 추가해서 데이터가 위변조되지 않았음을 보장합니다.
  • x5c: 리프 인증서와 중간 인증서를 가지고 있습니다. 루트 인증서는 Android와 iOS의 공식 사이트(Android, iOS)에서 확인하실 수 있습니다.

authData는 아래 값들로 구성됩니다.

  • RP ID Hash: Android와 iOS 모두 앱 ID값을 SHA256 해시 연산한 값이 들어갑니다.
    • Android: attStmt 내 인증서 체인에 포함된 AttestationApplicationId를 검증해 앱의 위변조 유무를 확인할 수 있습니다.
    • iOS: 서버는 공식 앱 ID를 가지고 있기 때문에 RP ID Hash 값과 비교해 앱의 변조 여부를 확인할 수 있습니다. RP ID는 앱의 App ID를 해시한 값으로, 여기에는 10자리 팀 식별자, 마침표, 앱의 Bundle ID 값이 포함됩니다. 만약 제3자가 앱을 변경하려면 Apple로부터 새로운 Bundle ID와 프로비저닝 프로파일을 받아야 하므로 RP ID 해시 값이 달라집니다. 그러므로 서버는 앱의 위변조 유무를 확인할 수 있습니다.
  • flags: authData의 상태(state)를 나타내는 1 바이트 길이의 플래그입니다. 각 비트는 각각 'ED', 'AT', 'BS', 'BE', 'UV', 'UP' 값으로 가질 수 있습니다. AT는 아래 나오는 'attested cred data'를 포함하는 비트로, 이 값이 1이면 인증 데이터에 attested cred data가 포함돼 있음을 의미합니다. 증명 객체의 경우 AT는 1입니다.
  • counter: 서명 카운터로 증명 객체에서는 값이 0입니다. 증명이 정상적으로 완료되면 자격 증명(credential)의 서명 카운터가 0으로 설정되고, 이후 어설션이 정상적으로 완료될 때마다 1씩 증가합니다.
  • attested cred data: 'Attested credential data'의 약자입니다.
    • aaguid: 'Authenticator attestation global unique identifier'의 약자이며, 128비트의 식별자입니다.
    • credentialIdLength: 부호 없는 빅 엔디언 정수(unsigned big-endian integer) 값으로 아래 credentialId의 길이를 나타냅니다.
    • credentialId: 생성된 어설션 키의 식별자입니다.
    • credentialPublicKey: 어설션 공개키 값이 COSE_Key 형식으로 인코딩돼 있습니다.
  • extensions: 추가적인 데이터를 넣을 때 사용하는 필드로, 기기 증명의 인증자에서는 사용하고 있지 않습니다.

어설션

어설션(assertion)은 증명을 통해 확보한 신뢰를 바탕으로, 클라이언트가 인증키를 소지하고 있다는 것을 증명함으로써(proof of possession) 앱과 서버 간의 안전한 통신을 보장합니다.

어설션 과정은 일반적으로 앱 내에서 중요한 이벤트가 발생할 때 수행합니다. 어설션 수행 시 앱은 서버에게 챌린지 값을 받아 이를 어설션 개인키로 서명한 후 서버로 전송합니다. 서버는 수신한 서명을 검증해 요청이 신뢰할 수 있는 앱에서 온 것인지 확인할 수 있습니다. 어설션 과정에서 앱의 무결성에 대한 정보도 함께 전달돼 검증되므로 앱의 변조 유무도 함께 증명할 수 있습니다. 또한 어설션은 증명 과정에서 확보한 키의 안전성을 기반으로 작동하므로 키의 기밀성과 무결성도 유지됩니다.

어설션 과정

증명 과정과 마찬가지로 재전송 공격을 방지하기 위해 챌린지-응답 방식을 통해 다음과 같은 흐름으로 서버와 상호 작용합니다.

  1. 클라이언트는 서버에게 챌린지를 요청해 전달받습니다.
  2. 클라이언트는 증명 과정을 통해 등록된 어설션 개인키로 어설션 관련 정보와 챌린지 등을 서명합니다.
  3. 클라이언트는 생성된 서명을 포함해 어설션 객체를 생성합니다(어설션 객체에 대해서는 아래에서 자세히 설명합니다).
  4. 어설션 객체가 서버로 전송되면, 서버는 어설션 객체의 정보와 증명 과정 수행후 저장한 어설션 공개키를 사용해 서명을 검증해서 클라이언트와 앱이 정상적인 환경에서 작동하고 있는지 확인합니다.

어설션 객체

어설션 객체(assertion object)는 서명값과 인증 데이터값을 포함한 데이터 구조입니다. 인증 데이터 형식은 증명 객체의 인증 데이터 형식과 동일합니다.

  • signature: authenticatorData 값과 clientData를 SHA256 해시 연산한 값을 연결(concatenate)하고 이 값을 어설션 개인키로 서명한 값입니다.
  • authenticatorData
    • RP ID Hash: Android와 iOS 모두 앱 ID값을 SHA256 해시 연산한 값이 들어갑니다.
      • iOS: RP ID Hash를 통해 서버는 애플리케이션의 무결성을 확인할 수 있습니다. 또한 iOS의 AppAttest 서비스를 실행하는 iOS 데몬은 애플리케이션 번들 ID를 기반으로 ACL을 관리합니다. 이 ACL은 특정 번들 ID에만 키 접근을 허용합니다. 따라서 앱이 변조되어 번들 ID가 변경되면 새로운 번들 ID를 인식하지 못해 원래의 키에 접근할 수 없습니다.
      • Android: RP ID Hash를 서버에서 검증하지는 않지만, 플랫폼 ACL 관점에서는 본질적으로 iOS와 동일합니다. 만약 공격자 또는 제3자가 앱을 변조하려면 애플리케이션을 다시 서명해야 하므로 서명값이 변경됩니다. Android의 KeyMaster 서비스는 각 키에 대한 접근 권한 목록(ACL)을 관리하며, 이 ACL은 특정 애플리케이션 서명에만 키 접근을 허용합니다. 따라서 앱이 변조돼 다시 서명되면, KeyMaster는 새로운 서명을 인식하지 못해 원래 키에 접근할 수 없습니다.
    • flags: AT값이 0으로 세팅돼 있습니다. 즉, 앞서 증명 객체에서 살펴본 attested cred data가 어설션 객체에는 없습니다.
    • counter: 서명 카운터로 어설션 키의 누적 사용 횟수를 나타내며, 재전송 공격을 방지하는 보조 수단으로 활용합니다. 첫 어설션에서 이 값은 반드시 0보다 커야 하며, 서버는 어설션마다 counter가 이전 값보다 큰지 확인해서 어설션 키의 비정상적 사용을 탐지할 수 있습니다.

보안 강화 대책

기기 증명 서비스는 앱의 보안 수준을 최대한 높이기 위해 다음과 같은 보안 강화 대책을 수립했습니다.

API를 어설션에 바인딩

사용자가 결제나 송금과 같은 보안 관점에서 중요한 작업을 수행할 때, 해당 API의 파라미터 값들을 어설션에 바인딩해 요청의 진위성을 보장할 수 있습니다.

예를 들어 사용자가 결제나 송금을 서버로 요청할 때 앱에서 해당 요청 관련 정보를 어설션 객체에 포함시키면, 서버에서는 어설션을 검증함으로써 해당 정보가 합법적인 클라이언트로부터 생성됐다는 것을 확인할 수 있고, 이를 통해 API의 보안 수준을 크게 높일 수 있습니다.

잠재적으로 신뢰할 수 없는 실행 환경 탐지

Android는 증명 객체 내 인증서 체인에 키 증명 확장 데이터 스키마가 포함돼 있습니다. 이 스키마의 각 요소의 값을 확인하면 실행 환경과 관련된 상세한 정보를 얻을 수 있습니다. 

SecurityLevel ::= ENUMERATED {
    Software  (0),
    TrustedEnvironment  (1),
    StrongBox  (2),
}
 
RootOfTrust ::= SEQUENCE {
    verifiedBootKey  OCTET_STRING,
    deviceLocked  BOOLEAN,
    verifiedBootState  VerifiedBootState,
    verifiedBootHash OCTET_STRING,
}
 
VerifiedBootState ::= ENUMERATED {
    Verified  (0),
    SelfSigned  (1),
    Unverified  (2),
    Failed  (3),
}

위 스키마의 각 요솟값이 아래와 같은 경우 '잠재적으로 신뢰할 수 없는 실행 환경'으로 간주합니다.

  • attestationSecurityLevel값이 Software로 설정된 경우
    • 보안 수준이 낮은 기기(하드웨어 기반의 키 저장소가 제공되지 않음) 또는 에뮬레이터에서 실행되고 있을 가능성이 높습니다.
  • deviceLocked 값이 False로 설정된 경우
    • 부트 로더가 잠금 해제돼 있습니다. 이는 잠재적으로 서명되지 않은 기기 이미지가 플래시될 수 있는 상태라는 것을 의미합니다. 이 경우 서명되지 않은 이미지를 통해 애플리케이션 서명 검증을 위조하거나 KeyMaster ACL을 우회할 수 있습니다. 부트 로더가 잠금 해제된 상태에서는, 공격자가 부트 상태가 검증된 상태에서 공식 이미지를 사용하여 증명을 통과한 후 서명 검증을 위조하고 키 ACL을 우회하는 수정된 이미지를 플래시할 수 있습니다.
  • verifiedBootState값이 Verified로 설정되지 않은 경우
    • 기기 제조 업체가 제공하는 공식 기기 이미지가 아니라 수정된 상태입니다. 신뢰할 수 없습니다.

기본적으로 attestationSecurityLevel이 TrustedEnvironment나 StrongBox이고, deviceLocked이 True, VerifiedBootState가 Verified인 경우 신뢰할 수 있는 환경으로 간주합니다. 그 외 키 증명 확장 데이터 스키마에서의 각 요소, 예를 들어 OS 패치 수준이 임곗값보다 너무 낮을 경우 등의 정보를 바탕으로 보다 정교한 보안 정책을 수립할 수 있으며, 해당 환경에서의 요청을 차단하거나 기존의 이상 탐지 시스템에서 리스크 가중치를 부과하는 식으로 활용할 수 있습니다  

증명 키 유출 대책

증명 키는 정품 Apple 하드웨어 및 Google CTS(Compatibility Test Suite)를 통과해 인증된 Android 하드웨어에서만 사용할 수 있습니다. Google과 Apple에서는 만약 증명 키가 유출됐거나 모바일 기기 제조사에서 증명 키를 잘못 처리했거나 공급망에서 공격자의 공격으로 의심되는 추출이 발생하는 등 여러 가지 이유로 증명 키를 신뢰할 수 없게 된 경우 키를 폐기할 수 있는데요. Google은 해당 키를 인증서 취소 상태 목록(Certificate Revocation List, CRL)에 추가하고 Apple은 해당 기기에 대한 증명 발급을 중단합니다.

따라서 저희는 증명 과정에서 해당 어설션 키의 유효성을 검증할 때, 인증서 체인의 각 인증서 상태를 공식 인증서 취소 상태 목록(CRL)과 비교해 확인하고 있습니다. 이 목록은 Google에서 관리하며 이 사이트에서 확인할 수 있습니다. 자세한 내용은 Google의 인증서 취소 상태 목록에 대한 공식 가이드를 참고하시기 바랍니다.

기기 증명 우회 방지 대책

공격자는 기기의 운영 체제를 직접 수정하지 않고도 애플리케이션 및 커널 취약점을 이용해 루트 권한을 얻을 수 있습니다. 이 경우, 부트 레벨의 무결성이 손상되지 않으므로 공격자는 증명과 어설션 과정을 우회하거나 조작하도록 만들 수 있습니다. 그 결과 변조된 기기를 통해 다른 장치들(봇, 에뮬레이터 등)에게 어설션을 제공할 수 있으며, 공격자는 이러한 방식으로 서비스 요청을 남용할 수 있습니다. 따라서 이러한 방식의 공격에 대한 보호가 필요합니다.

이런 행위를 완벽히 감지하는 것은 불가능에 가깝지만, 이상 탐지를 바탕으로 단일 기기에서 요청된 증명 횟수를 측정해 위험 가능성을 평가하도록 추가 보안 계층을 구축했습니다. 

마치며

이번 글에서는 기기와 앱, 서비스 요청의 무결성을 보장하는 기기 증명 서비스를 소개했습니다. 기기 증명 서비스는 현재 LINE 앱에 통합된 후 안정화 단계에 이르렀고, 서비스 관련 데이터를 수집해 분석하고 있습니다. 앞으로 이 데이터를 활용해 기존의 이상 탐지 기반 안티 어뷰징 시스템을 개선하고, 그 결과를 후속 블로그 포스팅을 통해 공유할 계획입니다.

또한 기기 인증 서비스를 LINE과 같은 글로벌 규모의 서비스에 통합하는 과정에서 다양한 시행착오를 겪었는데요. 이 자리를 빌려 그 과정에서 큰 도움을 주신 Auth & Account Dev 팀, Account Product App Dev 1 팀, Platform Product Management 팀에게 진심으로 감사의 말씀을 전합니다. 아울러 Auth & Account Dev 팀에서 곧 글로벌 LINE 서비스에서의 기기 증명 서비스 적용 과정과 결과를 블로그로 공유할 예정이니 많은 관심과 기대 부탁드립니다. 긴 글 읽어주셔서 감사합니다.

Name:김도연

Description:Security R&D 팀에서 기기 증명 및 FIDO2 서비스와 보안 컨설팅을 담당하고 있습니다.

Name:김영현

Description:Security R&D 팀에서 보안 및 개인 정보 보호 기술의 연구/개발 업무를 담당하고 있습니다.

Name:박경준

Description:Security R&D 팀에서 기기 증명 및 FIDO2, 보안 컨설팅 관련 AI 서비스 개발을 담당하고 있습니다.

Name:후바인 찰스

Description:LINE Plus에서 보안과 암호화 관련 기능 연구 및 개발을 담당하고 있습니다.

Name:안상환

Description:LY Corp. 보안 개발 팀에서 보안 컨설팅 및 제품 개발 관리를 담당하고 있습니다.