SSL 피닝(SSL Pinning)을 우회할 수 있을까?
1. SSL 피닝(SSL Pinning)이란 무엇이며 어떻게 동작하나요?
기본적으로 SSL(Secure Socket Layer) Pinning은 클라이언트 쪽에서 개발자가 **중간자 공격(man-in-the-middle)**을 막기 위해 사용하는 기술입니다.
이 기술을 쓰면 개발자는 개발 단계에서 신뢰할 수 있는 인증서 목록을 클라이언트 앱에 포함(pin)해 두고, 실행 중에는 이 목록을 서버 인증서와 비교합니다.
클라이언트는 SSL 핸드셰이크 이후에도 서버 인증서를 다시 검증합니다. 서버 인증서와 로컬에 저장된 인증서 사본이 일치하지 않으면 연결이 그대로 끊기며, 사용자 데이터는 그 서버로 더 이상 전송되지 않습니다.
2. SSL 피닝이 있을 때와 없을 때의 차이는?
이 제한 덕분에 사용자 기기는 신뢰할 수 있는 서버와만 통신합니다.
따라서 SSL 피닝은 자체 서명 인증서를 생성하는 중간자 앱이 앱의 동작 방식과 서버와의 통신을 분석하지 못하도록 막는 데 자주 사용됩니다.
예시로 Proxyman을 사용해 Product Hunt와 Dropbox의 트래픽을 캡처해 보겠습니다.
보시다시피 Product Hunt 클라이언트는 SSL 피닝을 사용하지 않습니다. 따라서 Proxyman은 서버와 클라이언트 역할을 모두 맡아 Product Hunt로 오가는 모든 데이터를 통신하고 캡처할 수 있습니다.
Proxyman에 Product Hunt 트래픽이 캡처된 모습
반면 SSL 피닝이 적용된 Dropbox 클라이언트는 Proxyman의 CA가 미리 정의된 인증서 목록에 없다는 것을 감지하고, 서버로 보내는 모든 요청을 끊습니다.
Proxyman에서 캡처되지 않는 Dropbox 트래픽
3. SSL 피닝을 우회할 수 있을까?
피닝으로 신뢰하는 인증서 집합을 제한하면 공격자를 막을 수 있다는 것은 이제 알겠습니다. 그렇다면 이 프로토콜을 우회할 방법이 있을까요? 답은 "예"이기도 하고 "아니요"이기도 합니다 (:
-
회사의 개발자가 아니라면 앱 클라이언트와 통신할 수 있는 유효한 인증서를 제공하기가 대개 어렵습니다.
-
반면 회사의 개발자라서 원본 인증서와 개인 키를 가지고 있다면, 그 키를 중간자 앱에 추가해 SSL 피닝을 우회할 수 있습니다.
다만 모든 중간자 앱이 이 프로토콜을 우회하기 위해 키를 추가하는 기능을 지원하는 것은 아닙니다 (:
4. 이제 어디로 가야 할까요?
이 미니 블로그는 개발자가 앱과 주고받는 트래픽을 왜 때때로 검사할 수 없는지에 대한 기본적인 이해를 제공합니다.
더 안전한 테스트 방법
먼저 같은 기기에서 https://google.com 같은 일반 HTTPS 사이트를 엽니다. Proxyman에서 해당 응답은 읽을 수 있는데 앱에서만 SSL 오류가 나타난다면 SSL 피닝이 원인일 가능성이 높습니다. 직접 개발한 앱이라면 피닝을 끄거나 테스트 인증서를 신뢰하도록 설정한 디버그 빌드를 사용합니다. 피닝이 켜진 제3자 앱은 Proxyman으로 복호화할 수 없으며, 허가 없이 앱을 검사해서는 안 됩니다.
SSL 피닝의 작동 원리와 앱에 이를 구현하는 방법은 여기의 RWL 강의를 참고하면 됩니다.
또한 중간자 앱인 Proxyman을 사용해 앱의 SSL 피닝을 테스트할 수도 있습니다 (:
Proxyman은 iOS 기기, iOS 시뮬레이터, Android 기기에서 앱과 도메인의 HTTP/HTTPS 요청을 확인할 수 있게 해 주는 고성능 macOS 앱입니다.
https://proxyman.com에서 다운로드할 수 있습니다.

