ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [WWDC21] Mitigate fraud with App Attest and DeviceCheck
    테크 2023. 8. 17. 17:30

     

    ※ 본 내용은 WWDC21에서 발표된 <Mitigate fraud with App Attest and DeviceCheck> 내용을 정리한 내용입니다.

     

    Mitigate fraud with App Attest and DeviceCheck - WWDC21 - Videos - Apple Developer

    Discover how to use App Attest and DeviceCheck, Apple's powerful anti-fraud tools, created to safeguard your apps and content. Unlock the...

    developer.apple.com

     

    목차

    • DeviceCheck
    • App Attest
    • App Attest Flow
    • Risk Metric Service

     

    DeviceCheck

    앱에 새로운 기능을 추가했다고 가정하자. 이 기능을 홍보하기 위해서 무료로 한 번 사용할 수 있게 하자. 그러면 어떤 사람은 이 기능을 남용하기 위해서 앱을 지웠다가 다시 설치해서 이 기능을 무한번 사용할 수 있다. 이를 방지하기 위해서 디바이스당 한 번 그 기능을 사용하게끔 할 수 있다. 이를 도와주는 것이 DeviceCheck이다.

     

    DeviceCheck는 fraudlent activity를 추적하기 위해서 2 bits와 timestamp를 저장한다. 각각의 bit가 어떤 의미를 가지고 있는지는 개발자의 설계에 따라 달렸다. 이 2 bits는 일종의 상태이며 Apple이 이 정보를 계속 가지고 있다.

     

    한 개발자로부터 만들어진 모든 앱들은 공통 bits를 공유한다. 이 bits는 앱을 재설치를 한다고 하더라도 유지되며, 사용자간 디바이스 이전을 하더라도, 모든 컨텐츠 및 세팅들을 지운다고 하더라도 계속 유지된다. 만약 일정 기간이 지나면 bits를 리셋하고 싶은 경우에 timestamp를 이용해서 리셋하면 된다.

     

    App Attest

     

    App Attest를 설명하기 이전에 간단한 용어 정리를 하고 넘어가겠다.

    • 앱: 클라이언트 사이드를 의미한다.
    • 서비스: 서버 사이드를 의미한다. 서비스는 앱의 요청(request)을 처리하고 응답(response)을 앱으로 전달한다.
    • App Attest 서비스: App Attest 서비스를 제공해주는 Apple 서버를 의미한다.
    • Secure Enclave: Apple에서 보안 목적으로만 사용되는 독립된 하드웨어이다. (iPhone 5S부터 지원)

    서비스가 앱으로 요청을 받았을 때, 이 요청이 정말 우리가 만든 앱(genuine app)에서 온건지 알기가 어렵다. 악의적인 목적을 가진 공격자가 우리의 앱을 수정(modified version app)해서 서비스에 요청을 날릴 수 있기 때문이다. App Attest는 요청의 일부로 hardware-backed assertion을 넣는다. 그러면 우리의 서비스는 이 assertion을 사용해서 요청이 정말 Apple 기기(genuine Apple device)에 설치된 genuine app으로부터 온 것인지 검증할 수 있다. 간단히 말하자면, App Attest는 genuine app과 modified version app을 구분해준다.

     

    App Attest는 서비스로 보내는 요청이 아래의 3가지 조건을 모두 만족하는 앱으로부터 오는 것인지를 검증한다.

    1. genuine Apple device로부터 요청된 것인가?
    2. genuine app에서 요청된 것인가?
    3. request payload가 변조되지 않았는가?

     

    핵심은 안전한 키 쌍(secure key pair)Apple에 의해 서명된 증명(attestation)이다.

     

    키 쌍은 genuine Apple device에서 생성된 것이어야한다. 이 때 비밀키(private key)는 App Attest API를 사용해서만 Secure Enclave에 저장이 되며 접근할 수 있다.

     

    앱은 서비스에 보내는 요청을 App Attest API를 이용해서 만든 키 쌍 중 개인키를 이용해서 서명한다. 서비스는 전달받은 요청이 genuine Apple device에서 생성되었는지 서명 검증을 통해 확인할 수 있다.

    → genuine Apple device로부터의 요청인지 확인 가능

     

    앱을 Apple device에서 사용하려면 반드시 서명되어야 한다. 만약 이 앱을 무단으로 수정하려고 하면 개발자 ID가 수정되며 이는 필연적으로 App ID가 수정된다. Attestation을 할 때 자동으로 App ID를 해쉬해서 넣는다. Attestation에 포함되어 있는 App ID를 비교함으로써 이 앱이 modified version인지 genuine인지 알 수 있다.

     genuine app으로부터의 요청인지 확인 가능

     

    서비스에 요청을 보내기 전에 아까 만들었던 키를 페이로드의 다이제스트(digest)에 서명한다. 즉, 페이로드의 assesrtion을 생성하는 것이다. 앱은 서비스에 요청을 보낼 때 assertion도 반드시 같이 보내야 한다. 서비스는 assertion을 검증함으로써 페이로드가 변조되지 않았다는 것을 알 수 있다.

     request payload가 변조되지 않았는지 확인 가능

     

    Attestation은 하드웨어 ID를 포함하고 있지 않기 때문에 완전히 익명이라 device tracking을 할 수 없다.

     

    App Attest를 위한 키 쌍들은 앱을 설치할 때마다 새로 생성된다. 즉, 앱 재설치를 하게 되면 이전의 App Attest key는 유효하지 않게 되며 어딘가에 백업되지도 않는다. 또한 디바이스끼리 공유되지도 않는다.

     

    App Attest Flow

    0. App Attest 사용 가능 여부 체크

    isSupported 프로퍼티를 이용해서 해당 디바이스가 App Attest를 지원하는지 확인한다. Secure Enclave가 있는 디바이스만 App Attest를 지원한다. 예외적으로 App Extensions은 항상 False를 리턴한다.

     

    만약 False가 리턴되면 접근을 차단하는 것이 맞을까? 접근을 차단하는 것 보다는 위험 시그널(risk signal)로 Failure를 사용하는 것이 좋다. 그렇게 되면 요청 호출자(caller)를 untrusted로 분류할 수 있게 되고, risk assessment logic에 따라서 해당 호출자가 sensitive feature를 사용할 수 있는지에 대해서 평가할 수 있다. 또 다른 방식으로는 서비스에 요청을 보낼 때 App Attest를 서포트하지 않는 요청이 갑자기 증가하는지 모니터링할 수 있다. 만약 App Attest를 서포트하는 디바이스의 비율이 급격하게 줄어들면...? 위험 시그널로 생각할 수 있다.

     

    1. App Attest Key 생성

    generateKey 메소드를 이용해서 App Attest 키 쌍을 생성한다. 이렇게 되면 Secure Enclave에서 키 쌍이 생성되며, 비밀키는 오직 리턴된 key ID를 이용해서만 접근이 가능하다.

     

    2. 키 증명 (Key Attestation)

    attestKey 메소드를 이용해서 키 증명을 할 수 있다. 이 때 서비스 측에서 생성한 one-time challenge를 attestKey 메소드의 파라미터로 전달해서 MITM 및 리플레이 공격을 막을 수 있다. 만약 user count ID 또는 다른 값들과 attestation을 연결하고 싶다면, challenge랑 해당 값들을 같이 해쉬해서 clientDataHash를 만든다. 이 값과 이전에 생성된 key ID를 이용해서 attestKey 메소드를 사용할 수 있다. 

     

    attestKey 메소드는 hardware attestation request를 생성하기 위해 비밀키를 사용한다. 그리고 검증을 위해 Apple 서버에 이 요청을 보낸다. Apple에서 어떤 검증을 하는지에 대한 내용은 알려진게 없으나... 아마도 공개키를 이용해서 요청 복호화를 하고 추가 작업을 하겠지? 어쨌든 검증이 성공적으로 완료되면 (anonymous) attestation object를 리턴한다.

     genuine Apple device 체크 완료

     

    앱은 attestation object를 서비스에 보내서 이 object를 검증한다. 서비스에서 어떤 식으로 attestation object를 검증하는지 알기 위해선 attestation object에 어떤 값들이 들어있는지 알아야 한다. Attestation object는 Web Authentication 표준을 따른다. 크게 세 가지 파트로 나눠진다.

    • Apple에 의해 서명된 인증서 리스트 (A list of certificates signed by Apple)
    • 인증 데이터 (Authenticator data)
    • 리스크 측정 리십트 (Risk metric receipt)

     

    먼저 Apple에 의해 서명된 인증서 리스트로는 leaf CA와 intermediate CA를 가지고 있다. App Attest Root CA는 Apple Private PKI repository에서 볼 수 있다. Full certificate chain 검증을 통해서 이 앱이 genuine Apple device라는 것을 알 수 있다. 참고로 아까 만들었던 clientDataHash 값으로부터 만든 nonce는 leaf certificate에 포함되어 있다. 위조(tampering)를 막기 위해서 이 nonce 또한 서비스에 보내서 검증을 한다.

     

    Authenticator data는 App ID 해쉬 값을 포함한 여러가지 값들을 포함하고 있다.

     

    Attestation object는 Apple에 risk metric을 요청하기 위해 저장하는 정보인 receipt도 포함하고 있다.

     

    서비스에서 검증이 완료되면...

     genuine app 체크 완료

     

    ※ App Attest 요청은 네트워크 기반이고 Apple server를 거쳐야하기 때문에 daily active user가 백만명 정도면 하루에 거쳐서 점진적으로 요청을 해야 한다. 만약 daily active user가 10억명 이상이라면 한 달에 걸쳐서 요청을 해야 한다.

     

    3. Assertion

    On-device에서 assertion object를 생성하며 서비스에서 이를 검증한다. 아까 attestation할 때랑 비슷하게 서비스에서 생성한 unique challenge를 가져오고 페이로드의 digest를 생성한 후에 generateAssertion 메소드를 호출한다. 이 메소드는 nonce 계산을 위해 digest를 사용하며 이를 App Attest 비밀키로 서명한다. 최종적으로 assertion object를 리턴한다.

     

    이 페이로드와 assertion object를 서비스에 보내서 검증을 한다. 서비스에서 어떻게 assertion object를 검증하는지 알기 위해서는 assertion object에 어떤 값들이 들어있는지 알아야 한다.

    • 서명 (Signature)
    • 인증 데이터 (Authenticator Data)

    공개키로 서명을 검증한 후 nonce를 구성하는 과정을 역순으로 진행하면 된다. 서명의 내용이 유효하면 페이로드는 수정되지 않았음을 의미한다.

     

    인증 데이터는 App ID 해쉬 값을 가지고 있다. App ID 해쉬값을 검증함으로써 이 assertion object가 genuine app으로부터 왔다는 것을 알 수 있다. 또한 리플레이 공격을 막기 위해 ever-increasing count를 포함하고 있다. 이 카운트 값은 서비스 쪽에서 저장을 해야한다.

     

    Assertion은 Apple 서버를 콜하진 않지만 cryptographic operation이 있기 때문에 어느 정도의 지연시간이 있다. 따라서 App Attest를 앱에 넣을 때 지연시간이 있다는 것을 생각해야만 한다. 즉, 중요한 작업이지만 그리 많은 호출을 하지 않는 작업에 assertion을 도입하는 것이 좋다.

     

    Risk Metric Service

    공격자는 하나의 디바이스에 modified version app을 여러 개 깔고, 여러 개의 App Attest key를 생성해서 우리의 서비스와 통신을 시도할 수 있다.

     

    이런 행위를 감지하기 위해서 한 디바이스에 몇 개의 키가 생성되었는지 대략적으로 알 수 있는 App Attest Risk Metric Service를 제공한다. 아까 전에 attestKey 메소드가 attestation object랑 receipt를 리턴한다고 이야기 했다. 서비스는 risk metric 정보를 수집하기 위해 이 receipt를 App Attest Risk Metric Service로 보내고 새로운 receipt를 받는다. 이 새 receipt에는 risk metric 정보가 포함되어 있다.

     

Designed by Tistory.