이번에는 쇼핑몰 보안을 위해 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)이라고 부릅니다.
2. HPKP(HTTP Public Key Pinning) 생성 방법
그러면 이러한 HPKP(HTTP Public Key Pinning)를 어떻게 생성할 수 있을까요?
2.1. 제공 웹사이트에서 얻기
가장 간단한 방법같은데요. 아래 사이트에 접속해 사이트 주고만 치면 알아서 뽑아줍니다. 금방 뽑아줍니다.
아래 사이트는 IP나 사이트 주소를 입력하면 SSL 보안성을 테스트해주고 더 나아가 필요한 HPKP(HTTP Public Key Pinning)도 뽑아줍니다.
시간은 조금 걸립니다. 테스트하고 등등
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"
Code language: PHP (php)
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
Code language: PHP (php)
2.2.3. Let’s Encrypt 인증 프라이빗 키 생성
이제는 Let’s Encrypt 인증 프라이빗 키를 생성합니다.
여기에서는 ISRG Root X1, Let’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
Code language: PHP (php)
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;';
Code language: PHP (php)
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;";
Code language: PHP (php)
2.2.5. 테스트
제대로 작동하는 지 테스트해봐야겠죠?
이는 위에서 소개한 Report URIs HPKP Analyser 에서 테스트해볼 수 있고, SSL Security Test 에서도 테스트해 볼 수 있습니다..
새롭게 뉴스레터를 시작했습니다.
1️⃣ 주식 등 투자 정보 : 기업 분석, IB 투자의견 등 투자 관련 내용
..... 테슬라 실적 및 IB들의의 테슬라 투자의견
2️⃣ 사례 및 트렌드 : 사례연구와 트렌드 관련 괜찮은 내용
.....유튜브와 경쟁대신 구독 전환한 비디오 플래폼 비메오 사례