아키텍쳐 /대용량 아키텍쳐

REST API에 대한 보안

Terry Cho 2013. 10. 28. 00:10

REST API 보안

조대협

REST API에 대한 보안에 대해서 알아보자. API 에 대한 보안은 인증, 메세지 암호화, 무결성 크게 3가지 관점에서 고민해볼 수 있다.


1)  인증

인증은, REST API를 호출한 사람(클라이언트)가 적절한 사용자 인가를 판단해주는 것이다. 아무나 API를 호출하는 것이 아니라 인증을 받은 사람많이 API를 호출해주게 하는 것인데, 쉽게 생각하면 사용자의 id,passwd로 서비스에 로그인을 하는 개념을 생각할 수 있다.

API Key 방식

API에 대한 인증 방법은 몇가지가 있는데, 그 중에서 가장 기초적인 방법은 API Key를 이용하는 방법이다. API Key, 특정 사용자만 알 수 있는 일종의 문자열이다. 현재 Amazon이 이 방식을 사용하고 있는데 API를 사용하고자 할때, 개발자는 API 제공사의 포탈 페이등에서, API Key를 발급 받고, API를 호출할때, API Key를 메세지 안에 넣어서 호출한다. 서버는 메세지 안에서 API Key를 읽어서, API가 누가 호출한 API인지를 인증하는 흐름이다.

OAuth 방식

가장 기초적이고 구현이 쉬운 방법이지만, 이 방법의 경우에는 표준이 없으며, API 서비스를 제공하는 쪽의 디자인 표준을 따르기 때문에, 근래에는 OAuth라는 형식의 인증 방식을 API 인증에 많이 사용한다. 구글이 이 방식을 사용하는데, OAuth Provider로 부터, 인증을 받으면, OAuth Token이라는 것이 생성된다. API를 호출하는 입장에서는 이 OAuth Token API 호출시 함께 넣어서 호출을 해서, 인증을 받는 방식이다.  OAuth의 경우 API Key 방식보다 조금 더 높은 보안 방식을 제공하고, 표준화가 되어 있기 때문에, API 서비스 제공자 입장에서는 서비스 확산을 위해서 권장되는 방법이다. OAuth의 경우에는 OAuth 인증 표준을 제공하는 인증 서버를 구축해야 하기 때문에, 구현 난이도가 API Key 방식에 비해서 높다.

Bi-diretional Certification

가장 높은 수준의 인증 방식을 제공할 수 있는 개념으로, 보통 HTTPS 통신을 사용할때, 서버에 인증서를 놓고, 단방향으로 SSL을 제공한다. 이 방식은 클라이언트에도 인증서를 놓고, 양방향으로 SSL을 제공하면서, API 호출에 대한 인증을 클라이언트의 인증서를 통해서 하는 방식이다. 가장 구현 방법이 복잡한 방식이기는 하지만, 공인 기관에서 발행된 인증서를 사용한다면 API 를 호출하는 쪽의 신원을 확실하게 할 수 있고, 메세지 까지 암호화 되기 때문에, 가장 높은 수준의 인증을 제공한다. 이런 인증 방식은 일반적인 서비스에서는 사용되지 않으며, 몇몇 높은 인증 수준을 제공하는 서비스나 특정 서버간의 통신을 위해서 사용 하는 것이 좋다.


2)  메세지 암호화

API 내용안에 다른 사람이 봐서는 안될 내용이 있다면 API 메세지를 암호화 해야 한다. 메세지를 암호화 하는 방법은 몇가지 접근 방법이 있는데, 그중에서 가장 손쉬운 방법이 HTTPS를 사용하는 방식이다. 이 방식의 경우에는 서버 설정만으로도 가능하고, 가장 널리 쓰이는 방식이기 때문에 신뢰할만하다.

그런데, HTTPS는 인증서를 이용해서, 초기 통신시에 SSL handshake를 통해서 Secure Connection을 제공하는 방식인데, HTTPS Client Server 사이에서 인증서를 바꿔치면, 중간에 이 인증서를 바꿔친 사람은 메세지를 볼 수 있다. 이를 Man in middle attack이라고 하는데, Server A Client B에게 인증서를 내려줄때, 중간에 Hacker C Server A의 인증서를 자신의 인증서로 바꿔서 Client B에게 전달한다. Client B Hacker C의 인증서로 메세지를 암호화해서 보내면, Hacker C가 중간에 메세지를 자신의 인증서를 이용해서 복호화해서 본후에, Server A가 보낸 원래 인증서로 다시 암호화 해서, 보내면, Server A는 문제가 없다고 판단한다. 실제로 중국 정부의 경우, 중국의 외부에서 들어오는 Traffic을 이러한 방법으로, 인증서를 바꿔쳐서 메세지를 복호화해서 필터링한다고 한다.

이런문제를 해결 하기 위해서는 Server A 에서 발급하는 인증서가 공인된 인증 기관의 인증서임을 확실하게 해주면 된다. 이렇게 인증서를 공인해주는 기관을 CA라고 하는데 Verisign 등이 대표적인 기관이다. 이렇게 공인된 인증서인지는 Client B가 인증서를 받아보고, 해당 인증서가 공인된 기관에서 발급된 인증서인지를 확인하면 된다. (클라이언트 쪽에, 인증서가 공인된 인증서인지를 확인하는 로직을 넣으면 Man in middle attack을 방지할 수 있다.)

데이타 레벨의 암호화

다음으로는 간단하게 암호화가 필요한 특정 필드만 애플리케이션단에서 암호화 해서 보내는 방법이 있다.



http://www.javamex.com/tutorials/cryptography/ciphers.shtml 를 참고하면, 대칭키 기반의 암호화 알고리즘 속도를 비교해놓은 것이 있다. 일반적으로 AES256을 사용하면 빠른 암호화 속도와 높은 보안성을 보장 받을 수 있다. (위, 대칭키 기반의 암호화 알고리즘 속도 비교)


3)  무결성 보장

무결성이란, 서버 입장에서 API 호출을 받았을때, 이 호출이 신뢰할 수 있는 호출인지, 아닌지를 구별하는 방법이다. Hacker가 중간에서 메세지를 가로챈후에, 내용을 변조해서 Server에 보냈을때, 내용이 변조되었는지 여부를 판단하는 방법인데, 일반적으로 HMAC을 이용한 방식이 널리 사용된다. 어떤 원리로 작동하는지 살펴보도록 하자.

먼저 전제는 Rest API를 호출하는 클라이언트와, 서버간에는 대칭키 기반의 암호화 키 “Key”를 가지고 있다고 전제하자. Key는 앞에서 설명한 API Key가 될 수 도 있고, OAuth 토큰이 될 수 도 있고, 또는 사용자가 임의로 정한 키가 될 수 도 있다.



(1) 먼저 클라이언트는 호출하고자 하는 REST API URL을 앞에서 정의한 Key를 이용해서 HMAC 알고리즘을 사용하여 Hash 값을 추출한다.

* 중요 : 여기서는 편의상 URL을 가지고 HMAC 해쉬를 생성하였는데, 전체 메세지에 대한 무결성을 보장하려면 URL이 아니라 메세지 전문 자체에 대해서 Hash를 추출해야 한다.

(2) 그리고 API를 호출할때, 메세지 (또는 URL)에 이 추출한 HMAC을 포함해서 호출한다.

(3) 서버는 호출된 URL을 보고 HMAC을 제외한 나머지 URL을 미리 정의된 Key를 이용해서, HMAC 알고리즘으로 Hash 값을 추출한다.

(4) 서버는 (3)에서 생성된 HMAC값과, API 호출시 같이 넘어온 HMAC 값을 비교해서, 값이 같으면 이 호출을 유효한 호출이라고 판단한다.

만약에 해커가 메세지를 중간에서 가로채서 변조하였을 경우, 서버에서 Hash를 생성하면 변조된 메세지에 대한 Hash가 생성되기 때문에 클라이언트에서 변조전에 보낸 Hash 값과 다르게 된다. 이를 통해서 메세지가 변조되었는지 여부를 판단할 수 있다.

Time stamp를 이용한 replay attack의 방지

그런데, 위의 알고리즘 상의 문제는, 만약에 메세지를 변경하지 않고, Hacker가 동일한 요청을 계속 보낸다면? 메세지를 변조하지 않았기 때문에 서버는 이를 유효한 호출로 인식할 수 있다. 이를 replay attack이라고 하는데 이를 방지하기 위해서는 time stamp를 사용하는 방법이 있다.

HMAC을 생성할때, 메세지를 이용해서만 Hash 값 생성하는 것이 아니라, timestamp를 포함해서 메세지를 생성하는 것이다.

HMAC (Key, (메세지 데이타+timestamp) )

그리고, API를 호출할때, timestamp 값을 같이 실어서 보낸다.

http://service.myapi.com/restapiservice?xxxxx&hmac={hashvalue}&timestamp={호출시간}

이렇게 하면 서버는 이 메세지가 호출된 시간을 알 수 있게 되고, 호출된 시간 +- 10(아니면 개발자가 정한 시간 폭) 만큼의 호출만 정상적인 호출로 인식하고 시간이 지난 호출의 메세지는 비 정상적인 호출로 무시해버리면 된다.

* 참고 : Hacker timestamp URL등을 통해서 볼 수 있다고 하더라도, Key값을 모르기 때문에, timestamp 를 변조할 수 없다. timestamp를 변조할 경우에는 원본 Hash가 원본 timestamp로 생성되었기 때문에, timestamp가 변조된 경우 hash 값이 맞지 않게 된다.

HMAC을 구현하는 해쉬 알고리즘은 MD5,SHA1등이 있는데, 보통 SHA-1 256bit 알고리즘을 널리 사용한다.

HMAC 기반의 REST Hash 구현 방법은

http://www.thebuzzmedia.com/designing-a-secure-rest-api-without-oauth-authentication/

에 설명이 잘나와 있으니 참고하기 바란다.

또한 HMAC 알고리즘 구현은 위키 http://en.wikipedia.org/wiki/HMAC 를 보면 각 프로그래밍 언어별로 예제 링크가 나와 있으므로 참고하기 바란다.

지금까지 간단하게 나마 REST API 보안 방식에 대해서 알아보았다. 보통 REST API를 디자인하는데, 가장 신경 안쓰는 부분 중의 하나가 API 에 대한 보안이다. 대신 한번 뚤리기 시작하면 걷잡을 수 없이 문제를 만드는 부분이 또 보안이다. API 디자인시에는 반드시 보안에 대한 부분을 고려하고, 위의 3가지 관점에 따라서 API 보안을 반영하기 바란다.


글이 예전 내용이라서 새 글이 업데이트 되었씁니다.

REST API 이해와 설계 - #1 개념 잡기 http://bcho.tistory.com/953

REST API 이해와 설계 - #2 디자인 가이드  http://bcho.tistory.com/954

REST API 이해와 설계 - #3 보안 가이드  http://bcho.tistory.com/955



그리드형