Don't disable certificate validation
Matched methods replace the certificate validation of a TLS client or server: ServicePointManager.ServerCertificateValidationCallback, HttpClientHandler.ServerCertificateCustomValidationCallback (or its DangerousAcceptAnyServerCertificateValidator), SslClientAuthenticationOptions.RemoteCertificateValidationCallback (used by SocketsHttpHandler), an SslStream constructor taking a callback, the obsolete ServicePointManager.CertificatePolicy, or Kestrel's ClientCertificateValidation. These callbacks are mostly written to accept a self-signed or expired certificate, which means trusting any certificate: a vulnerability to man-in-the-middle attacks https://en.wikipedia.org/wiki/Man-in-the-middle_attack
This is CWE-295 Improper Certificate Validation.
Flagged Code
This is CWE-295 Improper Certificate Validation.
Flagged Code
public HttpClient CreateClient() {
var handler = new HttpClientHandler();
// flagged: any certificate is trusted, a man-in-the-middle goes unnoticed
handler.ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => true;
return new HttpClient(handler);
}
Fixed Codepublic HttpClient CreateClient() {
// The issuing CA is installed in the machine trust store: the default
// validation checks the whole chain, no callback is needed.
var handler = new HttpClientHandler();
return new HttpClient(handler);
}How to fix
Install the issuing CA in the machine trust store, or pin the expected certificate thumbprint inside the callback instead of returning true. Never ship DangerousAcceptAnyServerCertificateValidator outside a development build. Suppress issues for legitimate custom validation procedures that still verify the chain.
CQLinq source
This rule is written in CQLinq, C# LINQ over the NDepend code model. It ships with every new NDepend project: you can read it, adapt it, or use it as a starting point for your own custom rules.
// <Name>Don't disable certificate validation</Name>
// <Id>ND3103:DontDisableCertificateValidation</Id>
warnif count > 0
// Third-party members are part of the code model only when the application uses them.
let certificateValidationOverrides = ThirdParty.Methods.Where(m =>
m.ParentNamespace.Name.StartsWithAny("System.Net", "Microsoft.AspNetCore") &&
(m.SimpleNameEqualsAny(
"set_ServerCertificateValidationCallback", // ServicePointManager, HttpWebRequest, WebRequestHandler
"set_ServerCertificateCustomValidationCallback", // HttpClientHandler
"get_DangerousAcceptAnyServerCertificateValidator",// HttpClientHandler
"set_RemoteCertificateValidationCallback", // SslClientAuthenticationOptions, SslServerAuthenticationOptions (SocketsHttpHandler.SslOptions)
"set_CertificatePolicy", // ServicePointManager (obsolete ICertificatePolicy)
"set_ClientCertificateValidation") || // Kestrel HttpsConnectionAdapterOptions
// new SslStream(stream, leaveOpen, RemoteCertificateValidationCallback)
(m.IsConstructor && m.ParentType.FullName == "System.Net.Security.SslStream" && m.Name.Contains("RemoteCertificateValidationCallback"))))
.ToHashSetEx()
where certificateValidationOverrides.Any()
from m in Application.Methods.UsingAny(certificateValidationOverrides)
let certificateValidationOverridesUsed = m.MethodsCalled.Intersect(certificateValidationOverrides).ToArray()
select new {
m,
certificateValidationOverridesUsed,
Debt = 30.ToMinutes().ToDebt(),
Severity = Severity.High
}
//<Expl>
// The *{0}* overrides certificate validation through *{1}*.
// A callback that returns true (or *DangerousAcceptAnyServerCertificateValidator*)
// makes the client trust any certificate, opening the door to *man-in-the-middle attacks*.
//</Expl>
//<Desc>
// Matched methods replace the certificate validation of a TLS client or
// server: *ServicePointManager.ServerCertificateValidationCallback*,
// *HttpClientHandler.ServerCertificateCustomValidationCallback* (or its
// *DangerousAcceptAnyServerCertificateValidator*),
// *SslClientAuthenticationOptions.RemoteCertificateValidationCallback*
// (used by *SocketsHttpHandler*), an *SslStream* constructor taking a
// callback, the obsolete *ServicePointManager.CertificatePolicy*, or
// Kestrel's *ClientCertificateValidation*. These callbacks are mostly
// written to accept a self-signed or expired certificate, which means
// trusting any certificate: a **vulnerability to man-in-the-middle
// attacks** https://en.wikipedia.org/wiki/Man-in-the-middle_attack
//
// This is CWE-295 *Improper Certificate Validation*.
//
// **Flagged Code**
// ```csharp
// public HttpClient CreateClient() {
// var handler = new HttpClientHandler();
// // flagged: any certificate is trusted, a man-in-the-middle goes unnoticed
// handler.ServerCertificateCustomValidationCallback = (msg, cert, chain, errors) => true;
// return new HttpClient(handler);
// }
// ```
//
// **Fixed Code**
// ```csharp
// public HttpClient CreateClient() {
// // The issuing CA is installed in the machine trust store: the default
// // validation checks the whole chain, no callback is needed.
// var handler = new HttpClientHandler();
// return new HttpClient(handler);
// }
// ```
//</Desc>
//<HowToFix>
// Install the issuing CA in the machine trust store, or pin the expected
// certificate thumbprint inside the callback instead of returning true.
// Never ship *DangerousAcceptAnyServerCertificateValidator* outside a
// development build. Suppress issues for legitimate custom validation
// procedures that still verify the chain.
//</HowToFix>
Open in the interactive Rules Explorer · All default rules
Security: all 39 items
- Software Composition Analysis (SCA) ND3120
- Transitive Software Composition Analysis (SCA) ND3121
- Don't hard-code secrets in constants ND3114
- Review credentials built from hard-coded values ND3115
- Don't use insecure deserializers ND3110
- Don't use weak hash algorithms (MD5, SHA1) ND3109
- Don't use DES/3DES/RC2 weak cipher algorithms ND3102
- Don't use weak password-based key derivation ND3123
- Don't use the ECB encryption mode ND3132
- Don't disable certificate validation ND3103
- Don't hard-code TLS/SSL protocol versions ND3122
- Review commands vulnerable to SQL injection ND3107
- Review data adapters vulnerable to SQL injection ND3108
- Review raw SQL built from composed strings ND3128
- Review LDAP filters composed from strings ND3137
- Don't enable external XML entity resolution (XXE) ND3111
- Review processes started with a composed arguments string ND3124
- Review web endpoints building file paths from their parameters ND3129
- Review custom archive extraction (Zip Slip) ND3135
- Review assemblies and types loaded from runtime-provided names ND3125
- Review web endpoints without [Authorize] nor [AllowAnonymous] ND3118
- Review state-changing endpoints opened to anonymous callers ND3130
- Review state-changing MVC actions without anti-forgery validation ND3119
- Review HTML-encoding bypasses ND3133
- Review explicitly disabled request validation ND3134
- Review redirects to a URL that is not validated as local ND3126
- Review request-influenced outbound HTTP calls (SSRF) ND3136
- Review insecure ASP.NET Core CORS policies and unguarded developer exception page ND3116
- Review cookies created without HttpOnly and Secure flags ND3117
- Review regular expressions without a match timeout (ReDoS) ND3112
- Review secrets compared with non-constant-time equality ND3113
- Review secrets passed to logging methods ND3127
- Review security operations that log nothing ND3131
- Don't use System.Random for security purposes ND3101
- Don't use CoSetProxyBlanket and CoInitializeSecurity ND3100
- Review publicly visible event handlers ND3104
- Pointers should not be publicly visible ND3105
- Seal methods that satisfy non-public interfaces ND3106
- Restrict sensitive APIs to reviewed components ND3138