관리 메뉴

Information Security

SSL Pinning 우회 코드 분석 본문

모바일/Frida

SSL Pinning 우회 코드 분석

HackingPractice 2020. 12. 25. 16:47

SSL Pinning.apk를 jadx파일을 열어 AndroidMainfest.xml에서 package 이름을 확인했다.

그림 1-1 AndroidMainfest.xml

PinnedSSLDemoActivity 클래스 내의 onSubmit() 메서드가 호출되었을 때, SSL Pinning 사용 체크박스에 체크가 되어 있다면 sslContext 라는 변수에 getPinnedSSLContext() 메소드의 반환 값이 저장된다. 체크가 되어 있지 않다면 기본값인 NULL이 저장된다. 이 sslContext 의 값에 따라 SSL Pinning이 적용된 암호화 통신을 할지 안 할지 결정하는 것을 알 수 있다. sslContext의 값을 결정하는 getPinnedSSLContext() 메서드의 로직을 확인해 볼 필요가 있다.

그림 1-2 onSubmit

해당 메소드의 반환 값은 SSLContext 객체이고, 이 객체는 PinnedSSLContextFactory 클래스의 getSSLContext() 메서드의 반환값이다. 이 메소드의 인자로 전달되는 input 값은 load-der.crt 라는 인증서 파일을 로드한 것이다. 이 파일은 Resources 디렉토리 내에 assets 디렉토리에 존재한다.

그림 1-3 getPinnedSSLContext

해당 인증서 파일은 Resources 디렉토리 내에 assets 디렉토리에 존재한다. load-der.crt를 Burp Suite 인증서로 교체한 후 다시 apk 파일로 리패키징 후 컴파일 과정을 거치면 SSL Pinning 우회 과정 없이 통신 패킷을 Burp Suite로 인터셉트할 수 있지만, 이는 해당 앱이 무결성 검증을 하지 않는 경우에만 가능하다.

그림 1-4 load-der.crt

return문을 보니 인자값으로 전달 받은 input 값이 loadCertificate() 메소드의 인자 값으로 전달되고, 이 메소드의 반환값이 createKeyStore() 메소드의 인자 값으로, 그 반환값이 다시 createTrustManager() 메소드의 인자 값으로, 마지막으로 그 반환값이 createSSLContext() 의 인자 값으로 전달되어 반환되는 값을 최종적으로 반환하고 있다. 

 

[안드로이드 SSL 통신 시 클라이언트 인증서 사용 순서]

1. 클라이언트 인증서 로드
2. 클라이언트 인증서를 이용하여 KeyStore 생성
3. 클라이언트 인증서를 이용하여 TrustManager 생성
4. KeyStore, TrustManager를 이용하여 SSLContext 생성

그림 1-5 PinnedSSLContextFactory

CertificateFactory 라는 클래스의 getInstance() 메소드를 통해 반환되는 인스턴스의 generateCertificate() 메소드의 인자 값으로 인증서 파일이 전달되어 반환되는 값을 리턴하고 있다. 이 CertificateFactory 클래스는 자바에서 제공하는 기본 클래스로, java.security.cert.CertificateFactory 이다. 이 로직에서 중요한 것은 인자 값으로 전달 받은 input 변수인데, 이 변수값을 조작하여 assets 내에 있는 인증서가 아닌 이전에 다운로드 받은 Burp Suite 인증서 파일로 바꿔서 SSL Pinning을 우회해 보자.

그림 1-6 Certificate

FileInputStream 클래스를 이용하여 Burp Suite 인증서를 로드한 후에 generateCertificate() 메소드의 인자 값으로 전달하였다. 

그림 1-7 소스코드

두 번째로 KeyStore를 생성하기 위해 호출하는 createKeyStore() 메소드의 로직을 확인했다.

그림 1-8 KeyStroe

KeyStore는 인증서 증명을 위한 키 값들을 저장한 것으로, 이 로직은 그대로 사용하면 된다.

그림 1-9 소스코드

세 번째로 TrustManager를 생성하는 createTrustMangager() 메소드의 로직을 확인해 보자. 

그림 1-10 TrustManager

해당 메소드의 로직 동일하게 작성하면 된다.

그림 1-11 소스코드

이 메소드를 호출할 때 위에서 생성한 TrustManager 배열 객체를 전달하고, 해당 객체를 SSLContext 클래스의 init() 메소드의 두 번째 인자 값으로 전달한다. 

그림 1-17 createSSLContext

 init() 메소드를 재작성하여 위에서 생성한 tmf_get 변수를 인자 값으로 전달하도록 하자. 물론 위에서 TrustManager를 생성하는 코드를 작성했을 때 처럼 init() 메소드를 직접 호출해도 되지만, 재작성을 통해 다른 로직은 원래 작성되어 있던 코드대로 진행하도록 할 것이다.

그림 1-18 소스코드

Pinned SSL Demo 실행 후 SSL connection 체크 후 Submit을 하면 Connection refused 되는 것을 알 수 있다.

그림 1-19 Pinned SSL

자바스크립트를 실행하였다.

그림 1-20 frida

Burp Suite에서 확인을 하면 Request 패킷이 잡히는 것을 알 수 있다.

그림 1-21 Request

'모바일 > Frida' 카테고리의 다른 글

SSL Pinning 우회  (0) 2020.12.24
Frida - sieve.apk BruteForce PIN  (0) 2020.12.21
Frida - sieve.apk 로그인 우회  (1) 2020.12.20
Uncrackable1 - 암호화  (0) 2020.12.18
UnCrackable - Level1  (0) 2020.12.17