[쇼핑몰 구축기] 보안을 위한 HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준

이번에는 쇼핑몰 보안을 위해 HPKP(HTTP Public Key Pinning)를 웹서버 Nginx를 기준으로 설정하는 방법에 대해서 살펴봅니다.

[쇼핑몰 보안] HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준

쇼핑몰 구축기를 연재하는 이유

최근 지인이 워드프레스를 이용해 쇼핑몰 구축을 시도하면서 배웠던 배웠던 다양한 경험들을 해당 쇼핑몰 블로그에 연재해 왔는데요.

쇼핑몰이 상품만 파는 것이 아니라 쇼핑몰을 방문하는 고객들에게 열가지 유용한 정보를 제공하는 블로그의 효용성이 높다는 점을 십분 활용하고, 처음 시작하는 쇼핑몰의 신뢰성을 주기 위해 비록 삽질이지만 삽질기를 낱낱히 공개하기로 했다고 하네요.

그 쇼핑몰의 주소는  https://puripia.com로 아직도 공사중이기는 합니다.) 

쇼핑몰 구축 시 도와주었던 인연으로 그 쇼핑몰을 알리고 쇼핑몰 구축 경험담을 보다 널리 알리기 위해서 여기 happist.com에도 같이  공유합니다. 조금 사심이 있기는 합니다.

[쇼핑몰 보안] HPKP(HTTP Public Key Pinning) 설정법 – NGINX 기준

오늘은 쇼핑몰을 비롯해 웨사이트의 보안을 위한 설정 중 HPKP(HTTP Public Key Pinning) 설정 방법에 대해서 살펴보겠습니다.

일반인에 접근하기엔 아주 어려운 개념이라서 저는 방법 소개에 그쳐야 할 것 같아요. 어느 분야든 다 마찬가지이겠지만 이 보안 분야는 특히나 어렵네요.

1. HPKP(HTTP Public Key Pinning)란 무엇인가?

요즘 일반화되고 있는 SSL/TLS 암호화 통신은 상대적으로 중간자 공격(Man In The Middle)에 취약하다고 합니다.

중간에서 인증서를 가로채 악성사이트로 접속시키고도 사용자는 그 사실을 모르는 채 공격을 당할 수 있습니다.

또 보안 장비들은 SSL Decryption 기능을 가지고 중간자(Man In The Middle) 공격 형태로 SSL/TLS 세션을 복호화해 내용을 검증합니다.

즉 보안장비가 SSL/TLS 인증서를 임의로 교쳏 중간에서 데이타를 가로채서 복호화해 검증하는 것이죠. 보안업체가 마음만 먹으면 일개 사이트를 조작하는 것은 아주 쉬운 일이 되겠죠.

그러한 일들을 막기 위해서 SSL/TLS 암호화 통신에 사용할 인증서를 최종 서버의 인증서로 고정(Pinning)해 중간자의 공격이나 보안장비 임의의 인증서를 거부하게 만드는데요.

이를 암호화 통신 인정서 고정이란 의미로 HPKP(HTTP Public Key Pinning)이라고 부릅니다.

HPKP(HTTP Public Key Pinning) 개념도, 이미지 출처 - keycdn.com
HPKP(HTTP Public Key Pinning) 개념도, 이미지 출처 – keycdn.com

2. HPKP(HTTP Public Key Pinning) 생성 방법

그러면 이러한 HPKP(HTTP Public Key Pinning)를 어떻게 생성할 수 있을까요?

2.1. 제공 웹사이트에서 얻기

가장 간단한 방법같은데요. 아래 사이트에 접속해 사이트 주고만 치면 알아서 뽑아줍니다. 금방 뽑아줍니다.

Create your HPKP hash

아래 사이트는 IP나 사이트 주소를 입력하면 SSL 보안성을 테스트해주고 더 나아가 필요한 HPKP(HTTP Public Key Pinning)도 뽑아줍니다.

시간은 조금 걸립니다. 테스트하고 등등

SSL Security Test

2.2. 서버에서 직접 뽑아내기

위와 같이 웹사이트에서 뽑아내는 방법도 있지만 조금 찜찌하다면 서버에서 직접 키를 뽑아낼 수 있습니다.

2.2.1. 먼저 프라이빗 키를 백업하자

먼저 프라이빗 키를 백업합니다. 하나는 RSA이고 하나는 Elliptic Curve관련 키입니다.

이를 위해 아래와 같은 openssl 명령을 사용합니다.

openssl req -nodes -sha256 -newkey rsa:4096 -keyout "MyDomain.com.rsa.key" -out "puripia.com.rsa.csr"
openssl req -nodes -newkey ec:<(openssl ecparam -name prime256v1) -keyout "puripia.com.ec.key" -out "MyDomain.com.ec.csr"

2.2.2.  SPKI 해시 키를 뽑아 내자

다음으로는 SPKI 해시 키를 뽑아 냅니다. 이는 아래와 같은 openssl 명령어를 사용합니다. 이 명령얼 사용해 나온 키를 복사해 놓습니다.

openssl req -pubkey < MyDomain.com.rsa.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

openssl req -pubkey < MyDomain.com.ec.csr | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

2.2.3. Let’s Encrypt  인증 프라이빗 키 생성

이제는 Let’s Encrypt  인증 프라이빗 키를 생성합니다.

여기에서는 ISRG Root X1Let’s Encrypt Authority X3 and Let’s Encrypt Authority X4의 SPKI-hash 값을 뽑아냅니다.

마찬가지로 아래와 같은 opensll 명령을 사용합니다.

curl https://letsencrypt.org/certs/lets-encrypt-x4-cross-signed.pem | openssl x509 -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
curl https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem | openssl x509 -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64
curl https://letsencrypt.org/certs/isrgrootx1.pem | openssl x509 -pubkey | openssl pkey -pubin -outform der | openssl dgst -sha256 -binary | base64

2.2.4. 설정

이제는 각 웹서버에 맞는 형식에 맞추어 위에서 뽑은 다섯개의 키를 적용해 줍니다.

nginx는 아래와 같은 포맷을 사용합니다.

add_header Public-Key-Pins 'pin-sha256="Hash1"; pin-sha256="Hash2"; pin-sha256="Hash3"; pin-sha256="Hash4"; pin-sha256="Hash5"; max-age=60;';

Apache는 아래와 같은 포맷을 사용합니다.

Header always set Public-Key-Pins "pin-sha256=\"Hash1\"; pin-sha256=\"Hash2\"; pin-sha256=\"Hash3\"; pin-sha256=\"Hash4\"; pin-sha256=\"Hash5\"; max-age=60;";

2.2.5. 테스트

제대로 작동하는 지 테스트해봐야겠죠?

이는 위에서 소개한 Report URIs HPKP Analyser 에서 테스트해볼 수 있고, SSL Security Test 에서도 테스트해 볼 수 있습니다..

HPKP(HTTP Public Key Pinning) 적용 상태를 테스트한 결과

LEAVE A REPLY

Please enter your comment!
Please enter your name here