안녕하세요.
테크니컬 라이터 Janghyun lee입니다.
백 번, 천 번을 강조해도 과함이 없는 보안 이야기.
그중에서도 ‘API 보안’에 대해 이야기해보고자 합니다.
보안을 중심으로 풀어본 Rest API, GraphQL 그리고 HMAC 인증 이야기...
이걸 다?....
그럼 시작하겠습니다!
- 여타 개발 지식과 마찬가지로, 국문(한국어)으로 이해하기보다는 영문 자체로 받아들이고 이해할 수 있도록 개념에 익숙해집시다.
- 정보의 표현에 집착하기보다는 내용과 개념 파악에 집중합니다.
보안의 기초 개념 두 가지입니다.
공통점은 두 가지 모두 connection attempt에 대한 일종의 확인이라는 점입니다.
[참고]
• 스프링 시큐리티의 기술 문서에서는 인증을who are you?
라고 표현하고 인가를what are you allowed to do?
라는 문장으로 비유하고 있습니다.
위 그림을 봅시다.
인증과 권한의 관계가 잘 표현되어 있습니다.
요청하는 주체를 유저(user, subject, principal 다 같은 의미)라고 합니다.
유저의 궁극적인 목표는 Resource에 접근하는 것이죠.
참고로 웹에서의 리소스는 웹 페이지, 텍스트, 이미지, 특정 html element 등으로 의미가 다양합니다.
그러기 위해서 인증과 권한의 필수 절차를 거쳐야 합니다. 반복해서 설명합니다.
Authentication은 본인의 신분을 증명하고 신분증을 받는 것과 같고,
Authorization은 문지기에게 신분증을 보이고 문을 통과하는 것과 같습니다.
웹에서 인증을 요청하는 유저는 서버에 두 가지 정보를 제시해야 합니다.
- 나는 '누구'이며
- 내가 그 유저인 '증거'다.
가장 쉬운 예시는 ID와 PW죠.
고객의 대출과 채무를 관리해야 하는 뱅킹 사이트처럼 보안이 중요한 웹사이트는 ID-PW로 로그인한 뒤, 공인인증서 로그인을 추가로 요구하는 경우가 있죠.
이렇게 이중 인증 방식을 two-factor authentication이라고 합니다. 줄여서 2FA.
세 번 이상 인증을 하면 multi-factor authentication이라고 합니다.
이외에도 지문 인식, 안면 인식 등의 물리적인 인증 방식도 있습니다.
API에 대한 인증 방식에는 여러 가지 방식이 있으며 각 방식에 따라 보안 수준과 구현 난도가 달라서, 각 방식의 장단점을 잘 이해하여 서비스 수준에 맞는 적절한 API 인증 방식을 선택하도록 할 필요가 있습니다.
authorization에 두 가지 중요한 포인트가 있습니다.
1. 권한 부여(grant authority)
사용자 인증을 성공적으로 마쳤다면 이제 유저에게 권한을 부여합니다.
예를 들어 같은 웹사이트에 로그인해도 admin 계정으로 로그인하면, 일반 사용자들에게는 보이지 않던 관리 메뉴(또는 admin 콘솔 페이지)가 하나 더 생기기도 하죠.
이런 경우에 일반 사용자는 '일반' 권한을, admin은 '관리자+일반' 권한을 가지고 있는 겁니다.
보안이 제대로 동작하는 웹사이트를 구축하려면 로그인한 유저에게 적절한 권한을 부여하고, 부여한 권한을 잘 관리해야 합니다.
2. 리소스 가로채기(intercept)
리소스를 권한이 있는 유저에게만 제공하는 일은 권한 관리의 핵심입니다.
보안이란 본래 권한이 없는 자들이 원천적으로 리소스에 접근할 수 없도록 막는 것입니다.
그런 의미에서 적절한 권한을 가진 자만 해당 자원에 접근할 수 있도록 자원의 외부 요청을 원천적으로 가로채는 것(Intercept).
Intercept는 Authorization의 중요한 원칙입니다.
네트워크 레벨 암호화
HTTP
에서의 네트워크 암호화는 일반적으로 HTTPS
기반의 프로토콜을 사용합니다.메시지 무결성 보장
메시지 본문 암호화
API Gateway
를 통해서 메시지를 열어보고, 메시지 기반 라우팅 변환 작업은 어렵기 때문에 일반적으로 전체 암호화보다는 보안이 필요한 특정 필드만 암호화하는 방식을 사용합니다.API는 내·외부 데이터를 손쉽게 제공하고, 디지털 전환 시대에 다양하게 활용되고 있다.
잘 설계된 API는 프로그램 개발을 더 쉽게 해주기 때문에 기업에서의 API 사용은 빠르게 증가하는 추세다. 반면 보안 위협은 갈수록 커지고 있다. API 보안 인식이 부족하고, 보안이 허술하기 때문이다.올해 상반기 API 공격 시도는 지난해보다 수백 배 급증했고, API 남용과 데이터 침해 사고는 2024년도까지 약 2배가량 증가할 것으로 예측됐다. API는 민감한 데이터가 저장된 백엔드 데이터베이스에 직접 연결되기 때문에 해커는 이를 노리고 API 기반 인프라 경로를 표적 삼아 데이터를 훔쳐낸다.
API 보안사고는 데이터 유출, 데이터 스크래핑(Data Scraping), 액세스 노출, 최종 사용자 추적, 계정 탈취 등이 있으며, 기업의 상당수는 API 관련 문제를 겪고 있다.해외 시장은 이미 API 보안에 대해 주목하며 경각심을 불러일으키고 있다.
가트너(Gartner)에 따르면 “2022년부터 API 남용이 가장 빈번한 공격 경로로 대두돼 기업의 웹 애플리케이션 침해가 발생할 것”이라고 분석했다. 데이터 분석가 샤민 필라이(Shameen Pillai)는 “2024년까지 API 남용 및 관련 데이터 침해가 거의 두 배로 증가할 것”으로 예측했다. 또한 가트너는 “2025년까지 기업 API의 50%가 ‘관리되지 않은 상태’로 있을 것”이라고 진단했다.
출처: https://m.boannews.com/html/detail.html?idx=108678-API 보안에 대한 기사 중 일부
IT 서비스에서 클라이언트가 서버 쪽 BE와 통신할 수 있는 방법은 여러 가지가 있겠지만, API 통신이 대표적인 방법이라고 할 수 있습니다. 근래 대부분의 서비스 시스템은 API를 기반으로 통신한다고 보시면 되는데요.
앱과 서버 간의 통신 또는 자바스크립트 웹 클라이언트와 서버 간 대부분의 통신이 이 API들을 이용해서 이루어지기 때문에 한번 보안이 뚫리면 개인 정보가 탈취되는 것뿐만 아니라 더 많은 문제를 일으킬 수 있습니다.
기업은 API를 이용해 서비스를 연결하고 데이터를 전송하는데 API가 손상, 노출 또는 해킹되면 주요 데이터 보안 유출 사고의 원인이 됩니다. 이로 인해 민감한 의료, 금융 및 개인 정보가 노출됩니다.
모든 데이터가 동일한 게 아니므로 이를 보호하는 방식도 달라야 하는데요. API 보안 접근 방식은 전송되는 데이터의 종류에 따라 달라지게 됩니다.
여기서 잠깐, Rest API와 자주 비교되는 GraphQL라는 녀석을 짚고 넘어가겠습니다.
주로 Rest API와 차이점을 부각하며 비교 분석해놓은 정보들을 어렵지 않게 찾을 수 있는데요.
이번 포스트는 이 주제가 요점이 아니기에 간단히 정리만 하고 넘어가겠습니다.
당연한 이야기이지만, GraphQL은 API에 대한 새로운 패러다임으로 여겨지고 인기를 얻었습니다.
GraphQL에서는 API 서버에서 엄격하게 정의된 endpoint에 요청하는 대신, 한 번의 요청으로 정확히 가져오고 싶은 데이터를 가져올 수 있게 도와주는 쿼리를 보낼 수 있습니다.
GraphQL은 FE와 BE의 협업 방식에 많은 변화를 가져왔다고 하는데요. BE에서의 많은 로직을 FE로 분산할 수 있었다고 합니다. (참고 - Part3, [GraphQL vs. REST, API를 고민하다])
그런데 말입니다.
이렇게 Rest API와 GraphQL를 비교 분석하며
각각의 분명한 장단점을 알고 넘어가는 것만으로는
어쩐지 찜찜합니다.
겉핥기식으로 겪었을 때는 모든 기술이 멋지고 유용해 보입니다만, 실제 프로덕션에 적용했을 때는 어떤 예기치 못한 에러와 문제가 발생할지는 두고 보아야 합니다.
GraphQL이 페이스북에 의해 오픈소스로 공개된 것도 5년이 지났습니다. 개발부터의 시간을 따지면 8년이 된 기술입니다. 이제는 ‘신기술’이라고 말하기에는 조금은 부적절할 수 있을 것 같습니다.
많은 관련 툴, 라이브러리들이 제작되었고 이제는 Rest API에 비해 관련 툴과 라이브러리가 적다고 할 수도 없을 정도입니다. 전 세계의 많은 개발자들이 GraphQL에 크게 관심을 가지며 유지, 보수, 개발해 나가고 있습니다. 개발 블로그, stackoverflow 등 커뮤니티에 레퍼런스도 많이 쌓여 가고 있습니다.Rest API 역시 오랫동안 사랑 받았으며, 지금도 여전히 유용한 패러다임입니다. 현재 구현된 대부분의 API 서비스가 REST를 따른다고 말해도 과언이 아닙니다. (과연 정말 RESTful 한지는 열어 봐야 아는 것이겠지만요..)
모두가 사용하고 따르는 기술은 무엇이든 그럴 만한 이유가 있습니다. 사용성이 좋다거나, 호환성이 좋다거나.. 여러 많은 잣대가 포함될 수 있습니다.
출처: https://hwasurr.io/api/rest-graphql-differences/
그렇다면, GraphQL or RESTful API 둘 중 어떤 것을 사용하는 것이 좋을까?
GraphQL
서로 다른 모양의 다양한 요청들에 대해 응답할 수 있어야 할 때
대부분의 요청이 CRUD에 해당할 때
RESTful
HTTP와 HTTPs에 의한 Caching을 잘 사용하고 싶을 때
File 전송 등 단순한 Text로 처리되지 않는 요청들이 있을 때
요청의 구조가 명확하게 정해져 있을 때 ( 요구사항 변동이 거의 없는 경우)즉, 둘 중 하나를 선택할 필요는 없다는 것입니다.
예를 들어 하나의 Endpoint를 GraphQL용으로 만들고, 다른 RESTful API용 Endpoint를 만들어 놓아도 됩니다.
하지만, 하나의 목표를 위해 2가지 API 구조를 섞어놓는 것은 API의 품질을 떨어트릴 수 있다는 점입니다.
(예로 들면 사용자 정보를 등록하는 것은 RESTful API로, 사용자 정보를 수정하는 것은 GraphQL API로.)
출처: https://choseongho93.tistory.com/320
진짜 결론
Rest API가 가지는 한계 때문에 개발된 GraphQL이지만, GraphQL이 완벽하게 Rest API를 대체할 수는 없다는 점을 배웠습니다.
개발할 코드의 양은 많아질 수 있으나, 하나의 엔드포인트는 GraphQL로 통신하고, 다른 엔드포인트들은 REST API를 제공하여 두 API 서비스를 함께 제공할 수도 있습니다.
REST에 더 적합한 서비스에는 REST가 사용되는 것이 바람직하므로,
GraphQL과 REST의 장단점을 파악해
서비스에 맞는 방식을 고르는 것이 중요하겠습니다.
MAC는 Message Authentication code(메시지 인증 코드)의 줄임말로, 메시지를 인증하기 위해 사용하는 정보입니다.
유저 A가 인터넷으로 연결된 유저 B에게 메시지를 보냈다고 가정합니다.
유저 A가 보낸 메시지는 매우 중요한 정보를 담고 있으며 위변조되면 안 된다고 가정합시다.
메시지가 보안 과정 없이 인터넷을 가로지르면 아래의 두 가지 보안 위험에 노출됩니다.
- 메시지 변조 : 중간에 누군가가 메시지를 가로채서 내용을 변조해서 전송한다.
- 메시지 위조 : 악의적인 사용자가 올바른 메시지인 것처럼 위조해서 전송한다.
위 문제를 해결하기 위해서는 메시지의 무결성과 메시지 인증이 담보되어야 합니다.
MAC은 메시지에 붙이는 작은 정보로 이것을 이용해 무결성과 인증 문제를 해결합니다.
정리
유명한 서비스의 REST API를 사용하려면 secret access key id(보안 액세스 키 ID)와 secret access key(보안 엑세스 키)를 생성해서 등록해야 사용 가능한 경우가 많습니다.
출처: https://haneepark.github.io/2018/04/22/hmac-authentication/
출처: https://www.joinc.co.kr/w/man/12/hmac#
이를 위해서는 수신 측과 송신 측이 같은 MAC 함수를 사용해야 하며, Authentication Key(이하 Key)도 일치해야 합니다. Key는 메시지와 송신자가 안전한 방법으로 미리 공유해야 합니다.
정리하겠습니다.
Rest API가 요청을 받았을 때, 이 요청이 신뢰할 수 있는 호출인지 확인하는 방법으로 HMAC을 사용합니다.
즉 이 요청이 해커에게서 온 부적절한 요청인지, 또는 정상적으로 요청된 것인지 확인할 수 있습니다. API 응답에 회원 정보 같은 민감한 내용이 포함되어 있는 경우, 요청에 대한 인증도 없이 아무에게나 중요한 정보를 주면 안 되겠죠.
서버에게서 자원을 받아내려면 인증과 권한 과정을 거쳐야 한다는 것.
Rest API에서는 서버에 요청을 보내는 행위 자체가 자원을 요구하는 것이고, 이에 대한 인증/권한 과정을 구현하는 여러 방식 중에 하나가 HMAC인 것이죠.
정리
HMAC은 MAC의 특정한 구현입니다.
MD5, SHA-1과 같은 해시 기반 함수를 이용해서 MAC 정보를 만듭니다. 어떤 알고리즘을 사용하느냐에 따라서 HMAC-SHA1, HMAC-MD5라고 부릅니다. 단방향 해시 함수라면 어떤 것이든 이용할 수 있습니다. 따라서 HMAC의 암호 강도는 어떤 크기의 해시를 사용하느냐에 따라 달라집니다.
HMAC의 취약점도 존재하는데요.
HMAC 적용된 메시지는 위변조를 할 수 없습니다. 하지만 메시지를 가로챌 수 있으며 이 경우 목적지로 다시 보내는 replay 공격에 노출될 수 있습니다.
이 취약점은 아래의 방법으로 대응할 수 있습니다. (*replay attach: 동일한 url을 반복 호출하는 기법)
Amazon S3 Rest API를 예로 들어 HMAC을 이용한 클라이언트 인증 방식을 살펴보겠습니다.
AWS는 발급받은 "AWS 보안 액세스 키 ID"를 Authorization 헤더에 추가해서 보내야 하며 본문은 "보안 엑세스 키"를 사용해서 HMAC 방식의 인증을 거쳐야 API 사용이 가능합니다.
Authorization: AWS AWSAccessKeyId:Signature
AWS S3의 Rest API는 내부적으로 해시 기반 메시지 인증(HMAC; Hash-based Message Authentication Code)이라는 보안 기술을 기반하고 있다는 걸 엿볼 수 있습니다.
HMAC 인증 방법
Shared Secret
, 대칭키)를 이용하여 생성된 서명(Signature
)으로, 매번 클라이언트로부터의 요청이 올바른지 인증합니다.TLS
가 적용된 HTTPS 프로토콜을 사용하는 것으로 자연스럽게 수행됩니다. Signature는 단지 요청한 클라이언트가 진짜인지 가짜인지를 증명하는 역할을 수행합니다.SHA256
이 사용됩니다. 업계 표준으로 쓰이고 있어 신뢰할 수 있으며 CPU에 가해지는 부담이 적습니다.
HMAC 인증 절차
Authorization
요청 헤더에 서명을 담아 전송하도록 명시하고 있습니다.
HMAC 서명의 생성과 검증
HMAC 인증 장점
HMAC 인증 단점
이렇게 해서 '보안'을 키워드로 조금은 억지스럽게 엮은 것으로 보일 수 있지만,
세 가지(Rest, GraphQL, HMAC 인증) 개념을 알아봤습니다.
긴 글 읽어주셔서 감사합니다.
Published by Technical writer, Janghyun lee