인증서를 확인하지 않거나 인증서 확인 절차를 적절하게 수행하지 않아, 악의적인 호스트에 연결되거나 신뢰할 수 없는 호스트에서 생성된 데이터를 수신하게 되는 보안약점
인증서를 확인하여(①), 검증결과 값이 X509_V_OK 이외의 값을 허용하는지 확인한다(②). 신뢰되지 않은 발급기관으로 받은 인증서를 허용하거나 유효기간이 만료된 인증서를 허용하면 위험하다. 또한 인증서의 Common Name 확인한다.(③)
1:cert = SSL_get_peer_certificate(ssl); ································①
2:if (cert && (SSL_get_verify_result(ssl)==X509_V_OK)) { ···············②
3: SSL_set_hostflags(ssl, X509_CHECK_FLAG_NO_PARTIAL_WILDCARDS);
4: if (!SSL_set1_host(ssl, "www.securecoding_example.com")) { ··········③
5: error(“Invalid Common Name”);
6: return –1;
7: }
8:// 서버와 클라이언트간에 피어 확인을 사용하며 콜백함수는 지정하지 않는다.
9: SSL_set_verify(ssl, SSL_VERIFY_PEER, NULL);
10: ...
11:}
다음 예제는 유효한 인증서인지 확인하지 않고, 인증서를 사용하고 있기 때문에 취약하다고 판정한다.
1:cert = SSL_get_peer_certificate(ssl);
2:if (cert) {
3: // 인증서를 확인하지 않고 작업 수행
4: ...
5:}
안전하지 않은 코드의 예 C
1:if ((cert = SSL_get_peer_certificate(ssl)) && host)
2:foo=SSL_get_verify_result(ssl);
3:if ((X509_V_OK==foo) ||X509_V_ERR_SELF_SIGNED_CERT_IN_CHAIN==foo))
// 자체 서명된 인증서일 수 있다.
1:cert = SSL_get_peer_certificate(ssl);
2:if (cert && (SSL_get_verify_result(ssl)==X509_V_OK)) {
3:/* CN 을 확인하지 않았지만 신뢰하고 진행한다. 이럴 경우, 공격자가 Common Name을
www.attack.com으로 설정하여 중간자 공격에 사용할 경우 데이터가 중간에서 복호화 되고 있음을
탐지하지 못한다. */
4: }
안전한 코드의 예 JAVA
1:private boolean verifySignature(X509Certificate toVerify, X509Certificate signingCert) {
2: /* 검증하려는 호스트 인증서(toVerify)와 CA인증서(signing Cert)의 DN(Distinguished
Name)이 일치하는지 여부를 확인한다.*/
3: if (!toVerify.getIssuerDN().equals(signingCert.getSubjectDN())) return false;
4: try {
5: // 호스트 인증서가 CA인증서로 서명 되었는지 확인한다.
6: toVerify.verify(signingCert.getPublicKey());
7: // 호스트 인증서가 유효기간이 만료되었는지 확인한다.
8: toVerify.checkValidity();
9: return true;
10: } catch (GeneralSecurityException verifyFailed) {
11: return false;
12: }
13:}
출처: 행정안전부 인터넷진흥원 소프트웨어 보안약점 진단 가이드