IT_Programming/Objective-C · Swift · iOS

서버와 APNS(애플 Push 서버)와의 보안 메커니즘

JJun ™ 2015. 1. 14. 21:44

 


 출처: http://bcho.tistory.com/m/post/960


 

애플 iOS 디바이스로 서버가 푸쉬를 보내고자 할때는, APNS 서비스를 거쳐야 한다.

푸쉬 메시지를 보내고자 하는 Provider 서버가 APNS로 푸쉬 요청을 보내면, APNS 서버가
디바이스로 푸쉬를 보내는 구조이다
.

 

이때 APNS 서버와 Provider 서버를 어떻게 신뢰하는 지를 알아보자.

APNS 서버 입장에서는 Provider 서버가 해커가 아냐? 진짜 Provider 맞아? 하는 의문을 가질 수 있고, Provider 서버도 APNS 서버가 진짜 APNS 서버가 맞는지를 확인할 수 있어야 한다.

이를 양방향 SSL(TLS:Transport Level Security)를 이용해서 해결 한다.

 

먼저 SSL 메커니즘에 대해서 알아보자 SSL 을 비대칭 (PKI) 키 구조의 암호화를 이용하는데, Public Key Private Key 두개를 가지고 있다. Public Key로 암호화를 할 수 있지만, 반대로 암호를 푸는 복호화는 Private Key를 통해서만 가능하다.

 

그래서 서버가 SSL 연결을 보낼 때, Public Key를 클라이언트에 내려 보내면, 클라이언트는 그 Public Key를 사용해서 메시지를 암호화 해서 서버에 전송하고, Private Key를 가지고 있는 서버만이 그 메시지를 해석할 수 있는 구조이다.


Main In The Middle attack

 

그런데 이 과정에서 취약점이 발생하는데, 서버가 Public Key를 내려보낼 때 중간에 해커가 서버서부터 온 Public Key를 낚아채고, 자신이 새로운 Public Key A1 Private Key A2 페어를 만든 후, 새롭게 만든 Public Key A1을 클라이언트로 내려보낸다. 그러면 클라이언트는 이 Public Key A1을 가지고 암호화를 해서 중간에 해커에게 보내고, 해커는 이 메시지를 자신의 Private Key A2로 열어서 본후에, 다시 원래 서버가 준 Public Key로 메시지를 암호화 해서 서버에 보낸다.

 

이 때 클라이언트와 서버는 Public Key Private Key로 안전하게 통신하는 것 처럼 보이지만, 사실은 사실은 중간에 해커에 의해서 메시지가 도청되고 있는 상황이 된다. 이런 Attack 방식을 Man In The Middle attack (MITM)


Signing

 

이러한 Public Key가로채기를 막을려면 Public Key를 받는 클라이언트 쪽에서 이 Public Key APNS에서 온 것이 맞는지를 확인하면 되는데, 보통 이 Public Key는 인증서(Certificate)안에 넣어서 클라이언트에게로 배달된다. 이 때 메시지 변조를 막기 위해서 Certificate는 안에 들어 있는 메시지로 생성된 일종의 해쉬값과 같은 signature 값을 가지고 있어서, 만약에 내부 메시지가 변경이 되면 원래 signature와 비교하여 메시지가 변경되었는지를 확인할 수 있다.

 

이를 생성하는 것을 싸이닝(Signing) 이라고 하는데, Signing Private 키로 생성되고, 이에 대한 비교는 Public Key를 통해서 할 수 있다. (Sign을 확인하기 위해서는 Sign에 사용된 Private Key에 대한 페어 Public Key를 가진 인증서를 가지고 있어야 한다. Public Key를 통해서 싸이닝을 확인할 수 있다.)


 

 


 

Channing

signature를 통해서 전달되는 메시지가 변조되는 것을 막을 수 는 있지만 위의 MITM attack 처럼 인증서 자체를 통째로 바꿔칠 수 있기 때문에, 이 인증서가 믿을만한 인증서인지를 확인해야 한다. 인증서에는 인증서를 발급한 기관 (CA : Certificate Authority)정보가 들어 있는데, “XXX에서 인증서를 발급함이라는 정보가 들어 있다.

 

그런데 문제는 이 인증서를 발급한 기관을 믿을 수 있냐는 거다. 구멍가게가 될 수 도 있고

은행과 같은 인증된 기관이 될 수 도 있다. 그래서 사용하는 기법에 인증서 Channing 기법인데, 인증서를 발급한 사람이 이 인증서를 신뢰된 기관에 가서 인증을 받은 후, 그 인증 정보를 인증서에 추가하는 방식이다.

 

아래 그림을 보자, 맨 아래의 Engineering CA는 자체 적으로 인증서를 발급하였다. 이 인증서를 USA CA certificate에 보내서 추가 인증을 받는다. 그런데, USA CA certificate 인증서는 이미 신뢰된 기관으로부터 인증을 받은 인증서이기 때문에, 이 신뢰된 기관의 인증 정보가 추가되게 된다. (신뢰된 인증 기관으로부터 인증서에 서명을 받으려면 회사 정보,신상 정보 등을 받은 후에 신원 확인 절차를 거쳐야만이 서명을 받을 수 있다.)


 

 


(출처 : https://developer.mozilla.org/en-US/docs/Introduction_to_Public-Key_Cryptography)

그래서 최종 인증서 모양은


 

 

 


 

이러한 형태가 되고, 클라이언트는 이 인증서 chain을 통해서 Root CA가 신뢰된 인증서인지를 확인하면 이 전체 인증서가 신뢰된 인증서임을 확인할 수 있다. (네트워크를 통해서 Root CA가 맞는지를 확인하게 되고, 만약에 Root CA라도 외부로 노출이 되었을 경우에 Revoked List라는 유출된 인증서 목록을 유지함으로써 인증서가 문제가 없는 인증서인지를 확인할 수 있다.)

 

이러한 절차를 거치면 MITM Attack을 통한 감청을 막을 수 있다.

다음 문제는 클라이언트 입장에서는 서버가 신뢰할 수 있는 서버인지를 알 수 있다. (Provider는 이 Root CA를 통해서 서버가 APNS 서버임을 알 수 있다.)


Mutual SSL

그러나 서버 입장에서는 클라이언트가 Provider서버가 맞는지? 를 확인할 필요가 있다. 이것이 인증 (authentication) 과정인데, TLS(SSL) 연결이 안전하게 설정된 후에, 사용자 ID,PASSWD를 넣어서 클라이언트(Provider)를 확인하는 방법도 있지만, 조금 더 확실한 방법으로, 클라이언트가 발급한 인증서를 사용하는 방식을 사용한다.

 

이 방식이 양방향 SSL 방식 (Mutual SSL) 인데, SSL 연결이 될 때 서버가 클라이언트에게 Public Key 를 내려 보내는 방식과 마찬가지로 클라이언트가 서버에게 Public Key를 전송하고 메시지를 클라이언트의 Private Key를 이용해서 암호화 해서 보내는 방법이다.

 

이 때 클라이언트에서 서버로 전송하는 Public Key는 인증서를 통해서 전달이 되게 되고, 인증서에는 인증서 발급 기관등의 정보가 들어가 있기 때문에, 이를 통해서 클라이언트를 인증을 할 수 있다.


APNS CSR

그래서 APNS의 경우에는 Service Provider Private/Public Key pair 를 생성한 후에, Public Key만을 담은 인증서를 생성하여, 웹사이트를 통해서 Service Provider 업체에 대한 정보와 함께, 싸인을 요청한다.

 

싸인을 진행할 때 애플은 인증서에 대한 고유 ID등을 통해서 이 인증서를 통한 호출이 어느 기관(업체)에서 들어오는지를 맵핑 해놓고, 향후 양방향 SSL 연결시에 이 정보를 가지고 클라이언트를 판독할 수 있다.

 

이를 기반으로 전체 서버간의 플로우를 보면

 

<!--[if !supportLists]-->1.  <!--[endif]-->ProviderPrivate Key를 생성한다

<!--[if !supportLists]-->2.  <!--[endif]--> Private Key를 기반으로 *.csr 파일(인증서 싸인 요청 파일)을 만든다. 이 파일에는 Public key가 들어 있는 인증서와 싸이닝을 요청하는 Provider의 업체 정보들이 들어가 있다.

<!--[if !supportLists]-->3.  <!--[endif]-->Provider는 애플 포탈에 들어가서 이 csr 파일을 업로드 한다.

<!--[if !supportLists]-->4.  <!--[endif]-->애플 포탈은 csr 파일을 기반으로 인증서(certificate)를 생성한후에, 애플의 인증서를 이용해서 싸인을 추가해서 Provider에게 돌려준다.

<!--[if !supportLists]-->5.  <!--[endif]-->Provider 4에서 받은 인증서(public key가 들어 있는)1에서 생성된 Private KeyProvider 서버내에 설치 한다.

<!--[if !supportLists]-->6.  <!--[endif]-->이때 1에서 생성한 Private Key,그리고 애플이 싸이닝하여 추가된 Public Key 가 들어 있는 인증서, 인증서 체인에 사용된 모든 인증서를 추가해서 한 파일(*.p12)에 넣는다.(*.p12 파일 포맷은 X.509를 지원하는 파일 포맷중에 유일하게 Private Key를 같이 넣을 수 있는 포맷이다.)

 

 

 

 

 

 

APNS Provider간의 Trust

 

   다음 통신이 이루어지게 되면, 아래 그림과 같이

 

<!--[if !supportLists]-->1.  <!--[endif]-->Provider ServerTLS 연결을 요청한다.

<!--[if !supportLists]-->2.  <!--[endif]-->APNS 서버는 certificate(인증서) public key를 넣어서 내려 보낸다.

<!--[if !supportLists]-->3.  <!--[endif]-->Provider는 이 인증서의 Root CA를 확인하여, 이 인증서가 애플에서 온 정상적인 인증서임을 확인한다. (Provider가 상대편이 APNS임을 확인함)

<!--[if !supportLists]-->4.  <!--[endif]-->Provider는 앞의 CSR에 의해 생성된 인증서를 APNS에 보낸다.

<!--[if !supportLists]-->5.  <!--[endif]-->APNS 4에서 온 인증서에 애플의 인증서로 Sign 이 되어 있는 것을 확인하고, 클라이언트가 (Provider) 합법적인 클라이언트임을 확인하고,어떤 사용자인지를 판독한다. (APNS Provider가 누구인지를 확인하였다.)

<!--[if !supportLists]-->6.  <!--[endif]-->마지막으로 양 서버간의 신뢰돈 TLS(SSL)연결이 성립되었다.