그룹 매개변수는 설계상 공개되어 있으며, 바로 그 공개성이 매개변수를 무시하기 쉽게 만든다. 유한체 Diffie-Hellman에서는 모듈러스와 생성자가 공유되지만, 개인 지수와 그로부터 나오는 세션 키는 공유되지 않는다. 수체 체 공격의 값비싼 단계는 하나의 교환이 아니라 그룹에 달려 있으므로, 어디서나 쓰이는 하나의 약한 그룹은 공유된 부채가 된다. 매개변수를 공개라고 부르는 것은 정확하지만 요점은 아니다. 재사용되는 비용은 바로 그 그룹을 공격하는 비용이기 때문이다.

공개된 절반은 취약한 절반이 아니다, 그게 함정이다

흔한 반쪽 논리는 매개변수가 표준에 공개되어 있으므로 공격자가 이미 알고 있고 숨겨도 아무것도 바뀌지 않는다고 말한다. 두 명제 모두 참이며 어느 것도 다른 것에서 따라 나오지 않는다. 함께 배포되는 기본 그룹은 공개이며, 지난주에 생성한 사설 그룹도 핸드셰이크를 마치는 누구에게나 보인다. 비밀성은 결코 통제 수단이 아니었다. 강도와 검증이 통제 수단이다.

달라지는 것은 같은 약점을 공유하는 장소의 수다. 자체 2048비트 그룹을 생성하는 조직은 자기 공격 비용을 지불하지만, 수백만이 선택하는 프로토콜 기본값은 하나의 비용을 그들 모두에게 분할 상각한다. 그런 의미에서 흔치 않은 그룹이 자동으로 더 나은 것은 아니다. 너무 작은 흔치 않은 그룹은 감시하는 눈이 더 적은, 더 작은 공유 비밀일 뿐이다.

검증은 크기만큼 중요하다. 작은 인수를 가진 모듈러스나 프로토콜이 기대하는 형태가 아닌 모듈러스를 보내는 상대는 비트 길이가 괜찮아 보여도 개인 지수에 대한 정보를 흘릴 수 있다. 입력 단계에서 잘못된 매개변수를 거부하는 라이브러리는 실제로 일을 한다. 그래서 직접 작성한 매개변수 파싱은 노력을 아끼기에 나쁜 장소다.

사전 계산이 공격자에게 실제로 주는 것

수체 체에는 소수에만 의존하는 단계가 있고, 그 출력은 그 소수를 사용하는 모든 교환에 대해 재사용할 수 있다. 이것이 역사적 우려의 전체 메커니즘이다. 값비싼 부분은 한 번 지불되고, 이후 각 세션의 한계 비용은 떨어진다. 새로운 지수는 그룹이 체를 실행 불가능하게 만들 만큼 충분히 큰 한, 각 개별 교환을 수동적 관찰자로부터 여전히 보호한다. 두 진술은 양립하며, 이 주제의 논쟁 대부분은 하나를 골라 다른 하나를 버리는 데서 생긴다.

2015년 Logjam 논문은 512비트 수출 등급 Diffie-Hellman으로의 다운그레이드를 보여주었고, 상당한 자원으로 더 크고 널리 재사용되는 그룹을 공격하는 비용을 추정했다. 시연은 구체적이었고, 추정은 추정이었으며, 어느 것도 특정 VPN 세션이 복호화되었다는 증거는 아니었다.

논문은 메커니즘과 시연된 다운그레이드 때문에 인용해야 하며, 자신의 배포에 대한 측정으로 인용해서는 안 된다. 얼마나 많은 서버가 기본 그룹을 공유했는지에 대한 오래된 통계는 그해의 인터넷을 설명하며, 오늘 검사할 수 있는 네트워크가 아니다. 가져갈 만한 유용한 것은 질문이다. 당신의 장치는 여전히 작거나 약하게 검증된 그룹을 협상하는가.

표준화되어 있다는 것은 약하다는 뜻이 아니다

RFC 7919는 이름 있는 유한체 그룹을 정의하여 양쪽 끝이 식별자로 그룹에 합의하고 일관된 정책을 적용하게 한다. 표준화되어 있다는 것은 장점이다. 협상의 모호함을 없애고 구현이 지원하지 않는 크기를 거부할 수 있게 한다. 이름 있는 그룹이 약한 것은 그 크기가 따른다고 주장하는 정책 아래에 있을 때뿐이며, 문서에 등장하기 때문이 아니다. 같은 논리가 타원 곡선 그룹에도 적용되며, 이들은 구조와 실패 방식이 다르다.

그것들에 대해 생각할 때 구성은 분리해 두어라. 유한체 Diffie-Hellman에 대한 결론은 X25519에 대해 아무것도 말하지 않고, 1024비트 MODP 그룹에 대한 결론은 3072비트 그룹에 대해 아무것도 말하지 않는다. 강도 정책은 메커니즘별, 크기별, 프로토콜 버전별이며, 그래서 강한 암호라는 표현은 검토 가능한 진술이 아니다.

인증은 나머지 절반이며 대체하지 않는다. 상대 검증이 없는 강한 그룹은 공격자를 중간에 남기고, 유효한 인증서는 768비트 교환을 구할 수 없다. 두 개의 독립된 선으로 검토하고, 그다음 둘 다 실제로 협상되는지 확인하라.

실제 연결에서 협상된 그룹을 읽어라

협상된 그룹은 구성 템플릿이 아니라 장치에서 읽어라. 템플릿은 의도를 기술하고, 흥미로운 값은 마지막 핸드셰이크에서 양쪽이 합의한 값이다. IPsec 끝점에서 상태 출력은 보통 선택된 제안을 인쇄하며, MODP 그룹을 포함한다.

정책 변경 전후에 그 줄을 기록하고, 둘 다 변경 기록에 보관하라. 비교가 증거다.

ipsec statusall | grep -Ei "proposal|ESP|IKE"
openssl dhparam -in /etc/vpn/dh3072.pem -check -noout

변경 후에도 상태가 이전 그룹을 보여 준다면, 연결이 재협상하지 않았고 구성 편집은 아무것도 증명하지 못한 것이다. 상대를 다시 시작하거나 보안 연관을 지우고, 그다음 상태를 다시 읽어라. 새 연결에만 적용되는 정책은 오래 사는 터널을 살아 있는 동안 이전 매개변수에 남겨 둘 것이다.

그룹과 상대의 신원을 따로 확인하라

그룹이 보호하는 것과 반대편에 누가 있는지를 분리하라. 키 교환 방식, 그룹 크기, 인증 방식을 세 필드로 기록하라. 이들은 독립적으로 실패하기 때문이다. 3072비트 그룹을 협상했지만 아무 인증서나 받아들이는 터널은 상대를 고정하고 2048비트 그룹을 쓰는 터널과 같은 위험이 아니다.

검토가 시작되기 전에 수용 기준을 적어라. 그러면 결과는 의견이 아니라 비교가 된다. 프로토콜 버전별 최소 그룹 크기, 이름 있는 그룹의 허용 목록, 상대 검증 의무화로 결정은 기계적으로 만들 수 있다. 그 목록의 모호함이 검토를 논쟁으로 바꾸고, 논쟁은 교정되지 않는다. 그러면 출력은 명시된 규칙을 위반하는 끝점의 목록이다.

ipsec statusall | grep -Ei "peer|auth|cert"
openssl s_client -connect vpn.acme.example:443 -brief -cipher 'DHE-RSA-AES256-GCM-SHA384'

교정 후 협상된 값을 다시 읽어 고리를 닫아라. 준수하는 구성 파일은 터널이 그것을 받아들였다는 증거가 아니다. 상태 출력과 한 번의 새로운 핸드셰이크가 증거이며, 그것들을 모으는 데는 필요한지에 대한 회의보다 시간이 덜 든다.

관련 글