Android SSL Pinning

2023. 12. 15. 13:53개발/Android

Pinning

  • ssl 인증서에 의존하는 서비스나 사이트의 보안을 향상시키기 위한 선택적 메커니즘
  • 피닝을 쓰면 암호화 id와 호스트를 연결할 수 이씀.
  • pinning은 보안 연결을 설정할때 허용할 특정 id를 클라이언트에 알려줌

SSL Pinning

  • 호스트를 해당 인증서 또는 공개 키와 연결하는 프로세스
  • 호스트의 인증서 / 공개키를 알게되면, 이를 해당 호스트에 pin

→ 사전에 정의된 공개키가 아니면 모두 거부!

이걸 왜 쓰나요?

  • ca로 인증받는 방식에서 끝나게되면,
  • 디바이스의 루트 ca를 해킹하게 되거나, android trust store에 등록하게 되면, 중간에서 중간자 공격이 가능해짐

→ 이를 막기위함!

  1. 중간자 공격으로부터 보호할 수 있고
  1. ca손상에 영향을 받지 않으며
  1. 민감 정보를 보호할 수 있다

SSL Pinning 유형

  1. 인증서 고정 : 서버의 인증서를 다운하여 앱에 묶음. 런타임시 앱은 서버의 인증서를 사용자가 삽입한 인증서와 비교
  1. 공개 키 고정 : 인증서의 공개 키를 검색해 코드에 문자열로 포함할 수 있음. 런타임시 앱은 인증서의 공개 키를 코드에 하드코딩된 키와 비교

  • 안드로이드에서 신뢰할 수 있는 루트 인증서를 보는 방법은
    1. 설정 열기
    1. 보안 및 위치
    1. 암호화 및 자격 증명
    1. 신뢰할 수 있는 자격 증명

Android network 구성

  1. 가장 간단한 network_security_config.xml 구성
    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <domain-config>
            <domain includeSubdomains="true">example.com</domain>
            <pin-set>
                <!-- Pin for the SSL/TLS certificate of example.com -->
                <pin digest="SHA-256">ReplaceWithYourPin</pin>
                <!-- Backup Pin for the SSL/TLS certificate of example.com -->
                <pin digest="SHA-256">ReplaceWithYourPin</pin>
            </pin-set>
        </domain-config>
    </network-security-config>
    • 여기서 핀 값은 X.509 SPKI의 base64로 인코딩된 다이제스트.
    • 신뢰할 수 있는 도메인에 대한 공개 키 또는 인증서의 sha-256해시값. (base64)
      • 서버의 ssl / tls인증서를 검사하여 얻거나

    1. 그 다음은 manifest에 해당 파일 추가
    <application
        android:networkSecurityConfig="@xml/network_security_config"
        ...>
        ...
    </application>

    테스트!

    try {
        // Create a URL object for the target server
        val mURL = URL("https://example.com/api/data")
        with(mURL.openConnection() as HttpsURLConnection) {
            requestMethod = "GET"
            // Add any necessary headers here
            println("URL: ${this.url}")
            println("Response Code: ${this.responseCode}")
            // Perform the actual connection and handle the response
            val responseCode = responseCode
            if (responseCode == HttpsURLConnection.HTTP_OK) {
                // Hooray! Connection successful - time to celebrate!
                // Now, let's process the response and show off our data handling skills! 🤓📊
            } else {
                // Oops! Handle other response codes (e.g., error cases) gracefully 😅
                // Every superhero faces challenges - it's how we handle them that matters!
            }
        }
    } catch (e: Throwable) {
        // Uh-oh! Invalid ssl pinning or some other Network errors - but fear not, we're prepared! 💪🛡️
        // Time to troubleshoot and save the day with proper error handling!
        println(e)
    }

Uploaded by N2T

'개발 > Android' 카테고리의 다른 글

Retrofit API Test  (1) 2024.01.03
메모리 누수를 해결하는 조금 더 자세한 방법  (2) 2024.01.03
Android의 모듈식 접근 방식  (0) 2023.12.15
MenuProvider  (0) 2023.12.15
메모리 누수의 원인 10가지  (0) 2023.12.15