CAA 레코드: 아무도 안 거는 인증서 자물쇠

모든 공개 CA는 2017년부터 CAA 레코드를 지킬 의무가 있다. 공짜에 DNS 한 줄이면 되는데, 9년이 지난 지금도 채택률은 겨우 15%다.

웹 보안에서 다른 거의 모든 것에 없는 성질을 가진 보안 통제가 하나 있다. 어려운 부분이 이미, 전 세계적으로, 의무화로 끝나 있다는 것.

2017년 9월 8일부터 CA/Browser Forum의 Baseline Requirements에 속한 모든 인증서 발급기관(CA)은 인증서를 발급하기 전에 CAA 레코드를 확인해야 한다. 권장이 아니다. 의무다. Ballot 187은 투표한 CA들 사이에서 19대 1로 통과했고 참여한 브라우저 셋 모두 찬성했다. 그 순간 CAA 확인은 괜찮은 아이디어에서 컴플라이언스 의무로 바뀌었다. 도메인의 CAA 레코드를 어기고 인증서를 발급한 공개 CA는 오발급(misissuance)을 저지른 것이고, 오발급은 CA가 불신임당하고 문을 닫는 경로다.

그러니까 집행 장치는 살아 있고, 전 지구적이고, CA가 실제로 두려워하는 유일한 위협으로 뒷받침된다. 이걸 쓰려고 당신이 할 일은 DNS 레코드 한 줄을 게시하는 것뿐이다.

거의 아무도 안 한다.

2024년 중반 기준으로 Qualys 데이터는 TLS를 지원하는 상위 15만 사이트 중 CAA 채택률을 15.4%로 집계했다. 같은 해 CSC 리포트는 Forbes Global 2000 — 지구에서 가장 큰 2천 개 기업, 보안 예산이 있는 그 회사들 — 중 겨우 9.5%만 CAA 레코드를 가졌다고 밝혔다. 확인이 의무화된 직후인 2017년 12월로 거슬러 올라가면, Scott Helme의 Alexa 100만 일일 스캔에서 CAA를 가진 사이트는 약 3,400개였다. 그 이후 곡선은 완만하게 우상향하지만, 이렇게 싼 것치고는 있어야 할 곳 근처에도 못 간다.

이 레코드가 실제로 하는 일

CAA 레코드는 당신 도메인에 대해 어느 CA가 발급해도 되는지를 적은 목록이다. 그게 전부다. 한 줄:

example.com.  CAA  0 issue "letsencrypt.org"

이건 이런 뜻이다: example.com의 인증서를 발급할 수 있는 유일한 CA는 Let’s Encrypt다. 당신 도메인의 인증서 요청을 받은 — 누구로부터든 — 준수하는 CA는 당신 CAA 레코드를 조회하고, 목록에 없음을 확인하고, 거부할 의무가 있다. 여럿 나열할 수도 있다. issuewild를 더해 와일드카드를 따로 통제할 수도 있다. 0 issue ";"어떤 CA도 발급 못 하게 잠글 수도 있는데, 공개 인증서가 절대 있어선 안 되는 도메인을 봉인하는 깔끔한 방법이다.

이게 뭘 바꾸는지 생각해 보라. CAA가 없으면, 당신 도메인의 유효한 인증서를 찍어낼 수 있는 기관의 집합은 전부다 — 모든 루트 저장소의 모든 공개 CA, 그중 하나가 당신 이름으로 발급하면 브라우저가 받아들이는 인증서가 나온다. CAA 레코드가 있으면 그 집합을 당신이 실제로 쓰는 CA 한둘로 줄인 것이다. 오발급을 불가능하게 만든 건 아니지만, 공격 표면을 ~150개 기관에서 당신이 고른 소수로 잘라냈고, 부주의하거나 자동화된 오발급 한 부류 전체를 명백한 위반으로 만들었다.

RFC 6844가 2013년에 이걸 정의했다. RFC 8659가 2019년에 대체했는데, 주로 DNS 조회를 비효율적으로 만들던 과도하게 복잡한 tree-climbing 알고리즘을 고치기 위해서였다. 표준은 성숙했다. 도구는 사소하다 — SPF용 TXT 레코드 추가하는 것과 똑같은 DNS 레코드다. 비용이 없다. 벤더가 없다. 연회비가 없다. 그런데 업계는, 집단적으로, 어깨를 으쓱했다.

왜 숫자가 낮게 머무는가

건강에 안 좋을 만큼 이걸 생각해 봤는데, 딱 게으름은 아닌 것 같다. CAA가 인센티브의 사각지대에 앉아 있는 게 문제다.

잘 작동할 때 안 보인다. SPF, DKIM, DMARC는 그래도 피드백 루프가 있다 — 메일이 반송되고, 누가 항의하고, 레코드를 고친다. CAA는 눈에 보이는 게 아무것도 없다. 게시하면… 사이트가 전과 똑같이 돌아간다. 이게 중요해지는 유일한 순간은 어떤 CA가 발급하면 안 되는 인증서를 발급할 뻔한 날인데, 당신은 그 일이 일어난 걸 영원히 모른다. 조용히 안 일어났다는 게 요점이니까. 성공이 아무것도 안 한 것과 구별되지 않는 통제는 바쁜 팀에게 팔기 어렵다.

그리고 밑에 진짜, 만만찮은 두려움이 깔려 있다: 잘못 걸면 내 인증서 갱신을 내가 깨뜨린다. 레코드에 엉뚱한 CA를 넣거나, 발급기관을 옮길 때 새 CA 추가를 깜빡하면, 내 ACME 클라이언트가 발급에 실패하기 시작한다. 많은 팀에게 머릿속 계산은 “단점: 내가 나를 잠근다. 장점: 내가 직접 겪은 적 없는 위협을 막는다”가 된다. 이 계산은 매번 진다. 지기 전까지는.

정직한 한계

과대포장은 안 하겠다. CAA를 걸 가치가 있는 이유가 곧 이게 은탄환이 아닌 이유이기도 하니까.

CAA는 준수하는 CA에게만 권고적이다. 브라우저가 강제하지 않는다 — 방문자의 Chrome은 인증서를 신뢰하기 전에 당신 CAA 레코드를 확인하지 않고, 할 수도 없다. 인증서가 제시되는 시점엔 발급이 이미 끝났으니까. 그래서 침해당했거나, 강요받았거나, 그냥 규칙을 무시하는 CA는 당신 CAA 레코드를 어기고 발급할 수 있고, 그 인증서는 여전히 클라이언트에게 신뢰받는다. CAA는 비용을 올리고 우발적 경로를 닫는다. 작정한 악성 기관을 막지는 못한다. 그건 Certificate Transparency와, 나쁜 짓 하는 CA를 처형하려는 루트 프로그램의 의지가 할 일이다.

두 번째 틈이 있다. CAA는 DNS에 살고, CA는 발급 시점에 그걸 확인한다. 공격자가 바로 그 순간 당신 DNS를 스푸핑할 수 있으면 — 레코드를 억누르거나 허용하는 걸 위조하면 — 확인은 거짓말 위에서 통과한다. RFC 8659는 바로 이 이유로 CA에게 DNSSEC로 검증된 응답을 선호하라고 말하지만, 상당수 도메인은 존에 서명을 안 하므로 이 보호는 그 밑의 DNS만큼만 강하다. CAA는 당신 DNS가 신뢰할 만하다고 가정한다. 웹의 많은 부분에서 그 가정은 무거운 짐을 지고 있다.

그러니 아니다, DNS 한 줄이 인증서 공격에 대한 면역을 주지는 않는다. 그게 하는 일은 “150개 CA 중 아무나”라는 문제 — 진짜로 터무니없는 기본값 — 를 당신이 의도적으로 신뢰하는 것들로 좁히는 것이다. 공짜로, 의무로 지켜지며, DNS 레코드 하나 추가하는 정도의 시간에. 원한다면 정교한 옵션도 있다: RFC 8657이 accounturivalidationmethods를 더해, 발급을 CA만이 아니라 특정 ACME 계정과 특정 챌린지 방식에 고정할 수 있다. 이것도 거의 아무도 안 쓴다.

나를 괴롭히는 부분

대부분의 보안 조언은 물리나 경제와의 싸움이다. “DNSSEC 채택”은 깨지기 쉬운 키 관리와 나쁨에서 전무함까지 걸치는 레지스트라 지원에 부딪힌다. “MTA-STS 배포”는 정책 엔드포인트를 세우라고 한다. “인증서를 더 빨리 교체”는 자동화를 더 만들라는 뜻이다. 이건 진짜 비용이고, 낮은 채택률이 최소한 말은 된다.

CAA엔 그런 게 하나도 없다. 비싼 부분 — 지구의 모든 CA가 레코드를 지키게 하는 것 — 은 2017년에 위원회 표결로 해결됐고 이후 조용히 돌아가고 있다. 남은 싼 부분, 도메인 소유자가 할 그 한 가지는 한 줄을 게시하는 것이다. 그리고 9년이 지났는데, 일곱 도메인 중 여섯은 그걸 안 했다.

표준 절차가 제 일을 했고, CA들이 제 일을 했고, 마지막 1마일 — 쉬운 1마일 — 만 아무도 안 걸은 드문 경우다. 도메인을 운영하고 이번 주에 5분을 낸다면, 당신은 그걸 한 15%에 들어간다.

토론 참여

← 블로그로 돌아가기