NAV Navbar
Logo pro
C#

Overview

Welcome to the Puma Scan rules documentation! Your guide to secure development in Visual Studio, powered by the .NET Compiler Platform Roslyn.

The Puma rule packs attempt to be as accurate as possible, but please understand that false positives and false negatives frequently happen in static analysis. We are always working to improve the quality and accuracy of our rulesets. Please report issues and feature updates (including an example code snippet and data flow) to us at support [at] pumascan [dot] com.

Configuration

Configuration based rules are run by the Roslyn API as additional files at the end of a compilation. During the configuration analysis phase, Puma does the following:

SEC0001 - Debug Build Enabled

Insecure Configuration:

The default value for the debug attribute is false.

<system.web>
   ...
   <compilation debug="true" targetFramework="4.5"/>
   ...
</system.web>

Secure Configuration:

Simply remove the debug attribute, or explicitly set the value to false.

<system.web>
   ...
   <compilation debug="false" targetFramework="4.5"/>
   ...
</system.web>

Binaries compiled in debug mode can leak detailed stack traces and debugging messages to attackers. Disable debug builds by setting the debug attribute to false.

References:

https://msdn.microsoft.com/en-us/library/s10awwz0(v=vs.100).aspx

SEC0002 - Custom Errors Disabled

Insecure Configuration:

The default value for the mode attribute is RemoteOnly.

<system.web>
   ...
   <customErrors mode="Off" defaultRedirect="/home/error"/>
   ...
</system.web>

Secure Configuration:

Explicitly set the mode value to RemoteOnly or On, or simply remove the mode attribute.

<system.web>
   ...
   <customErrors mode="RemoteOnly|On" defaultRedirect="/home/error"/>
   ...
</system.web>

Displaying stack traces in the browser can leak information to attackers and help them gain information for launching additional attacks. Enable custom errors by setting the mode to On or RemoteOnly.

References:

https://msdn.microsoft.com/en-us/library/h0hfz6fc(v=vs.100).aspx

Insecure Configuration:

The default value for the requireSSL attribute is false.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="30" />
    </authentication>
   ...
</system.web>

Secure Configuration:

Explicitly set the requireSSL value to true.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" requireSSL="true"/>
    </authentication>
   ...
</system.web>

Authentication cookies sent over HTTP connections can be stolen by attackers monitoring the network traffic, which can lead to session hijacking attacks. Configure “secure” cookies by setting the requireSSL attribute to true.

References:

https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx

SEC0004 - Forms Authentication: Cookieless Mode

Insecure Configuration:

The default value for the cookieless attribute is UseDeviceProfile, which can allow URL-based authentication tokens.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" />
    </authentication>
   ...
</system.web>

Secure Configuration:

Explicitly set the cookieless attribute to UseCookies.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" cookieless="UseCookies" />
    </authentication>
   ...
</system.web>

Authentication cookies should not be sent in the URL. Doing so allows attackers to gain unauthorized access to authentication tokens (web server logs, referrer headers, and browser history) and more easily perform session fixation / hijacking attacks. Configure cookie-base authentication by setting the cookieless attribute to UseCookies.

References:

https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx

SEC0005 - Forms Authentication: Cross App Redirects

Insecure Configuration:

The default value for the enableCrossAppRedirects attribute is false.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" enableCrossAppRedirects="true" />
    </authentication>
   ...
</system.web>

Secure Configuration:

Explicitly set the enableCrossAppRedirects attribute to false, or simply remove the insecure configuration.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" enableCrossAppRedirects="false" />
    </authentication>
   ...
</system.web>

Enabling cross-application redirects can allow unvalidated redirect attacks via the returnUrl parameter during the login process. Disable cross-application redirects to by setting the enableCrossAppRedirects attribute to false.

References:

https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx

Insecure Configuration:

The default value for the protection attribute is All.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" protection="None|Encryption|Validation" />
    </authentication>
   ...
</system.web>

Secure Configuration:

Explicitly set the protection attribute to All, or simply remove the insecure configuration.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" protection="All" />
    </authentication>
   ...
</system.web>

Forms Authentication cookies must use strong encryption and message authentication code (MAC) validation to protect the cookie value from inspection and tampering. Configure the forms protection attribute to “All” to enable cookie data validation and encryption.

References:

https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx

SEC0007 - Forms Authentication: Weak Timeout

Insecure Configuration:

The default value for the timeout attribute is 30.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="900" />
    </authentication>
   ...
</system.web>

Secure Configuration:

Explicitly set the timeout attribute to an appropriate value.

<system.web>
   ...
   <authentication mode="Forms">
      <forms loginUrl="~/Account/Login.aspx" timeout="15" />
    </authentication>
   ...
</system.web>

Excessive authentication timeout values provide attackers with a large window of opportunity to hijack user’s authentication tokens. Configure the forms timeout value to meet your organization’s timeout policy. If your organization does not have a timeout policy, the following guidance can be used:

App Timeout
High Security 15 minutes
Medium Security 30 minutes
Low Security 60 minutes

References:

https://msdn.microsoft.com/en-us/library/1d3t3c61(v=vs.100).aspx

SEC0008 - Header Checking Disabled

Insecure Configuration:

The default value for the enableHeaderChecking attribute is true.

<system.web>
   ...
   <httpRuntime enableHeaderChecking="false" />
   ...
</system.web>

Secure Configuration:

Explicitly set the enableHeaderChecking attribute to true, or simply remove the insecure configuration.

<system.web>
   ...
   <httpRuntime enableHeaderChecking="true" />
   ...
</system.web>

Disabling the HTTP Runtime header checking protection opens the application up to HTTP Header Injection (aka Response Splitting) attacks. Enable the header checking protection by setting the httpRuntime element’s enableHeaderChecking attribute to true, which is the default value.

References:

https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx

SEC0009 - Version Header Enabled

Insecure Configuration:

The default value for the enableVersionHeader attribute is true.

<system.web>
   ...
   <httpRuntime enableVersionHeader="true" />
   ...
</system.web>

Secure Configuration:

Explicitly set the enableVersionHeader attribute to false, or simply remove the insecure configuration.

<system.web>
   ...
   <httpRuntime enableVersionHeader="false" />
   ...
</system.web>

The Version HTTP response header sends the ASP.NET framework version to the client’s browser. This information can help an attacker identify vulnerabilities in the server’s framework version and should be disabled in production. Disable the version response header by setting the httpRuntime element’s enableVersionHeader attribute to false.

References:

https://msdn.microsoft.com/en-us/library/e1f13641(v=vs.100).aspx

SEC0010 - Event Validation Disabled

Insecure Configuration:

The default value for the enableEventValidation attribute is true.

<system.web>
   ...
   <pages enableEventValidation="false" />
   ...
</system.web>

Secure Configuration:

Explicitly set the enableEventValidation attribute to true, or simply remove the insecure configuration.

<system.web>
   ...
   <pages enableEventValidation="true" />
   ...
</system.web>

Event validation prevents unauthorized post backs in web form applications. Disabling this feature can allow attackers to forge requests from controls not visible or enabled on a given web form. Enable event validation by setting the page element’s eventValidation attribute to true.

References:

https://msdn.microsoft.com/en-us/library/950xf363(v=vs.100).aspx

SEC0011 - View State Mac Disabled

Insecure Configuration:

The default value for the enableViewStateMac attribute is true.

<system.web>
   ...
   <pages enableViewStateMac="false" />
   ...
</system.web>

Secure Configuration:

Explicitly set the enableViewStateMac attribute to true, or simply remove the insecure configuration.

<system.web>
   ...
   <pages enableViewStateMac="true" />
   ...
</system.web>

The ViewStateMac protection prevents tampering with the web forms view state and event validation hidden fields. Disabling this feature can allow attackers to manipulate these fields in the browser and bypass several security features in the .NET framework. Enable the view state mac protection by setting the page element’s viewStateMac attribute to true.

Note: As of .NET version 4.5.1, the ViewStateMac can no longer be disabled.

References:

https://msdn.microsoft.com/en-us/library/950xf363(v=vs.100).aspx

SEC0012 - Request Validation Disabled

Insecure Configuration:

The default value for the validateRequest attribute is true.

<system.web>
   ...
   <pages validateRequest="false" />
   ...
</system.web>

Secure Configuration:

Explicitly set the validateRequest attribute to true, or simply remove the insecure configuration.

<system.web>
   ...
   <pages validateRequest="true" />
   ...
</system.web>

The ValidateRequest protection performs blacklist input validation for XSS payloads found in form and URL request parameters. Request validation has known bypass issues and does not prevent all XSS attacks, but it does provide a strong countermeasure for most payloads targeting a HTML context. Request validation should be enabled by setting the page element’s requestValidation attribute to true. Then, consider making exceptions or overriding the default behavior on individual request parameters.

References:

https://msdn.microsoft.com/en-us/library/950xf363(v=vs.100).aspx

SEC0013 - View State Encryption Disabled

Insecure Configuration:

The default value for the viewStateEncryptionMode attribute is Auto, which only encrypts view state data for controls that request encryption.

<system.web>
   ...
   <pages viewStateEncryptionMode="Never" />
   ...
</system.web>

Secure Configuration:

Explicitly set the viewStateEncryptionMode attribute to Always.

<system.web>
   ...
   <pages viewStateEncryptionMode="Never" />
   ...
</system.web>

The web forms view state hidden field is base64 encoded by default, which can be easily decoded. Applications placing sensitive data into the view state are vulnerable to information leakage issues via the view state parameter. The pages ViewStateEncryptionMode attribute allows an application encrypt the view state data with the .NET machine key.

References:

https://msdn.microsoft.com/en-us/library/950xf363(v=vs.100).aspx

SEC0014 - Insecure HTTP Cookies

Insecure Configuration:

The default value for the requireSSL attribute is false.

<system.web>
   ...
   <httpCookies requireSSL="false" />
   ...
</system.web>

Secure Configuration:

Explicitly set the requireSSL attribute to true.

<system.web>
   ...
   <httpCookies requireSSL="true" />
   ...
</system.web>

Cookies containing authentication tokens, session tokens, and other state management credentials must be protected in transit across a network. Set the httpCookie element’s requireSSL attribute to true to prevent the browser from transmitting cookies over HTTP.

References:

https://msdn.microsoft.com/library/ms228262(v=vs.100).aspx

SEC0015 - Cookies Accessible Via Script

Insecure Configuration:

The default value for the httpOnlyCookies attribute is false.

<system.web>
   ...
   <httpCookies httpOnlyCookies="false" />
   ...
</system.web>

Secure Configuration:

Explicitly set the httpOnlyCookies attribute to true.

<system.web>
   ...
   <httpCookies httpOnlyCookies="true" />
   ...
</system.web>

Cookies that do not have the httpOnly attribute set are accessible in the browser by scripts. This can allow attackers to inject malicious scripts into the site and extract authentication cookie values to a remote server. Setting the httpCookie element’s httpOnlyCookies element to true will help prevent client-side session hijacking attempts.

References:

https://msdn.microsoft.com/library/ms228262(v=vs.100).aspx

SEC0016 - Cleartext Machine key

Insecure Configuration:

Secrets stored in the web.config file are not encrypted by default.

<system.web>
   ...
   <machineKey validationKey="<key value>" decryptionKey="<key value>" validation="SHA1" decryption="AES"/>
   ...
</system.web>

Secure Configuration:

Use the aspnet_regiis.exe utility to encrypt the machineKey element of the configuration file. Run this command from the root of your app.

C:\Windows\Microsoft.NET\Framework\v4.0.30319\aspnet_regiis.exe -pef “system.web/machineKey” . -prov “DataProtectionConfigurationProvider”

<system.web>
   ...
   <machineKey configProtectionProvider="DataProtectionConfigurationProvider">
      <EncryptedData>
        <CipherData>
            <CipherValue>[CIPHER TEXT VALUE HERE]</CipherValue>
        </CipherData>
      </EncryptedData>
    </machineKey>
   ...
</system.web>

The machine key element defines keys to use for encryption and decryption of authentication cookies, view state, and verification of session state identification. The validation and decryption key values should not be stored in configuration files in cleartext. Encrypt the machineKey section of the configuration file using aspnet_regiis.exe.

https://msdn.microsoft.com/en-us/library/w8h3skw9(v=vs.100).aspx

SEC0020 - Weak Session Timeout

Insecure Configuration:

The default value for the timeout attribute is 20 minutes.

<system.web>
   ...
   <sessionState timeout="480" />
   ...
</system.web>

Secure Configuration:

Explicitly set the timeout attribute to attribute to an appropriate value.

<system.web>
   ...
   <sessionState timeout="15" />
   ...
</system.web>

If session data is used by the application for authentication, excessive timeout values provide attackers with a large window of opportunity to hijack user’s session tokens. Configure the session timeout value to meet your organization’s timeout policy. If your organization does not have a timeout policy, the following guidance can be used:

App Timeout
High Security 15 minutes
Medium Security 30 minutes
Low Security 60 minutes

References:

https://msdn.microsoft.com/en-us/library/h6bb9cz9(v=vs.100).aspx

SEC0021 - State Server Mode

Insecure Configuration:

The default value for the mode attribute is InProc, which uses in memory session storage on the web server. Options such as StateServer allow another server to handle session management in a multi-node web farm scenario.

<system.web>
   ...
   <sessionState mode="StateServer" />
   ...
</system.web>

Secure Configuration:

Use a different distributed session state provider, such as SQLServer. Or, implement an external control for system to system authentication and secure transmission, such as IPSec.

<system.web>
   ...
   <sessionState mode="SQLServer" />
   ...
</system.web>

The session StateServer mode transports session data insecurely to a remote server. The remote server also does not require system authentication to access the session data for an application. This risk depends entirely on the sensitivity of the data stored in the user’s session. If the session data is considered sensitive, consider adding an external control (e.g. IPSEC) that provides mutual authentication and transport security.

References:

https://msdn.microsoft.com/en-us/library/h6bb9cz9(v=vs.100).aspx

Cross-Site Scripting

Cross-Site Scripting rules are run against the application source code and in view markup files (.cshtml, .aspx, .ascx). Currently, the following XSS patterns are supported:

SEC0024 - Unencoded Response Write

Insecure Code:

The following example shows the Raw Response.Write method writing a dynamic request parameter to the view without HTML encoding.

string user = Request["user"]?.ToString();
Response.Write("We're sorry" + user + "but that contest is not valid.  Please click your back button and try again.");

Secure Code:

Ensure HTML encoding is applied prior to writing dynamic data to the browser.

string user = Request["user"]?.ToString();
Response.Write("We're sorry" + Encoder.HtmlEncode(user) + "but that contest is not valid.  Please click your back button and try again.");

Data is written to the browser using the HttpResonse.Write method. This can result in Cross-Site Scripting (XSS) vulnerabilities if the data source is considered untrusted or dynamic (request parameters, database, web service, etc.).

Fixing the vulnerability requires the AntiXssEncoder.HtmlEncode method to neutralize dangerous data before writing it the browser.

References:

https://msdn.microsoft.com/en-us/library/1463ysyw(v=vs.110).aspx

SEC0100 - Raw Inline Expression

Insecure Code:

The following example shows a raw inline expression writing a dynamic request parameter to the browser.

<h2>
    Welcome <%= Request["UserName"].ToString() %>
</h2>

Secure Code:

Replace the raw inline expression with the secure HTML encode inline shortcut.

<h2>
    Welcome <%: Request["UserName"].ToString() %>
</h2>

Data is written to the browser using a raw write: <%= var %>. This can result in Cross-Site Scripting (XSS) vulnerabilities if the data source is considered untrusted or dynamic (request parameters, database, web service, etc.).

Instead of using a raw write, use the inline HTML encoded shortcut (<%: var %>) to automatically HTML encode data before writing it to the browser.

References:

https://software-security.sans.org/developer-how-to/developer-guide-xss

SEC0101 - Raw Binding Expression

Insecure Code:

The following example shows a raw binding expression writing a dynamic database value to the browser.

<asp:GridView ID="gv" runat="server" ItemType="Data.Product">
    <Columns>
        <asp:TemplateField HeaderText="Product">
            <ItemTemplate>
                <%# Item.ProductName %>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Secure Code:

Replace the raw binding expression with the secure HTML encode binding shortcut (<%#:).

<asp:GridView ID="gv" runat="server" ItemType="Data.Product">
    <Columns>
        <asp:TemplateField HeaderText="Product">
            <ItemTemplate>
                <%#: Item.ProductName %>
            </ItemTemplate>
        </asp:TemplateField>
    </Columns>
</asp:GridView>

Data is written to the browser using a raw binding expression: <%# Item.Variable %>. This can result in Cross-Site Scripting (XSS) vulnerabilities if the data source is considered untrusted or dynamic (request parameters, database, web service, etc.).

Instead of using a raw binding expression, use the HTML encoded binding shortcut (<%#: Item.Variable %>) to automatically HTML encode data before writing it to the browser.

References:

https://software-security.sans.org/developer-how-to/developer-guide-xss

SEC0102 - Raw Razor Method

Insecure Code:

The following example shows the Raw Razor helper method writing a dynamic value to the view.

<div class="loginDisplay">
    @Html.Raw(string.Format("Welcome <span class=\"bold\">{0}</span>!", Model.UserName))
</div>

Secure Code:

Replace the Raw Razor method with a Razor helper method that automatically HTML encodes the output data.

<div class="loginDisplay">
    Welcome <span class="bold">@Model.UserName</span>!
</div>

Data is written to the browser using a raw Razor helper method: @Html.Raw(Model.Variable). This can result in Cross-Site Scripting (XSS) vulnerabilities if the data source is considered untrusted or dynamic (request parameters, database, web service, etc.).

Instead of using the raw Razor helper method, use a Razor helper that performs automatic HTML encoding before writing it to the browser.

References:

https://msdn.microsoft.com/en-us/library/system.web.webpages.html.htmlhelper_methods(v=vs.111).aspx

SEC0103 - Raw WriteLiteral Method

Insecure Code:

The following example shows the Raw WriteLiteral method writing a dynamic value to the view.

<div class="loginDisplay">
    @{
        WriteLiteral(string.Format("Welcome <span class=\"bold\">{0}</span>!", Model.UserName));
    }
</div>

Secure Code:

Replace the WriteLiteral method with a Razor helper method that automatically HTML encodes the output data.

<div class="loginDisplay">
    Welcome <span class="bold">@Model.UserName</span>!
</div>

Data is written to the browser using the raw WriteLiteral method. This can result in Cross-Site Scripting (XSS) vulnerabilities if the data source is considered untrusted or dynamic (request parameters, database, web service, etc.).

Instead of using the raw WriteLiteral method, use a Razor helper that performs automatic HTML encoding before writing it to the browser.

References:

https://msdn.microsoft.com/en-us/library/system.web.webpages.webpagebase.writeliteral(v=vs.111).aspx

https://msdn.microsoft.com/en-us/library/system.web.webpages.html.htmlhelper_methods(v=vs.111).aspx

SEC0104 - Unencoded Literal Text

Insecure Code:

The following example shows the Literal.Text property set to a dynamic database value.

litDetails.Text = product.ProductDescription;

Secure Code:

Encode data passed to the Literal.Text property with the Web Protection Library’s (aka AntiXSS) appropriate context-specific method.

litDetails.Text = Encoder.HtmlEncode(product.ProductDescription);

Data is written to the browser using the raw Literal.Text method. This can result in Cross-Site Scripting (XSS) vulnerabilities if the data source is considered untrusted or dynamic (request parameters, database, web service, etc.).

Literal controls are often found in HTML contexts, but can also appear in other contexts such as JavaScript, HTML Attribute, or URL. Fixing the vulnerability requires the appropriate Web Protection Library (aka AntiXSS) context-specific method to encode the data before setting the Literal.Text property.

References:

https://msdn.microsoft.com/en-us/library/system.web.ui.webcontrols.literal.text(v=vs.110).aspx

https://wpl.codeplex.com/

SEC0105 - Unencoded Label Text

Insecure Code:

The following example shows the Label.Text property set to a dynamic database value.

lblDetails.Text = product.ProductDescription;

Secure Code:

Encode data passed to the Label.Text property with the Web Protection Library’s (aka AntiXSS) appropriate context-specific method.

lblDetails.Text = Encoder.HtmlEncode(product.ProductDescription);

Data is written to the browser using the raw Label.Text method. This can result in Cross-Site Scripting (XSS) vulnerabilities if the data source is considered untrusted or dynamic (request parameters, database, web service, etc.).

Label controls are often found in HTML contexts, but can also appear in other contexts such as JavaScript, HTML Attribute, or URL. Fixing the vulnerability requires the appropriate Web Protection Library (aka AntiXSS) context-specific method to encode the data before setting the Label.Text property.

References:

https://msdn.microsoft.com/en-us/library/system.windows.controls.label(v=vs.110).aspx

https://wpl.codeplex.com/

Cryptography

Weak cryptography can allow attackers to perform a variety of cryptanalysis attacks and compromise the confidentially and integrity of encrypted and / or hashed data. The following weak cryptography patterns are supported:

SEC0025 - Weak Algorithm: DES

Insecure Code:

The following example shows the DESCryptoServiceProvider algorithm being used to encrypt a sensitive piece of data:

using (MemoryStream mStream = new MemoryStream())
{
    //Input bytes
    byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);

    SymmetricAlgorithm alg = new DESCryptoServiceProvider();

    //Set key and iv
    alg.Key = GetKey();
    alg.IV = GetIv();

    //Create the crypto stream
    CryptoStream cStream = new CryptoStream(mStream, alg.CreateEncryptor(), CryptoStreamMode.Write);
    cStream.Write(inputBytes, 0, inputBytes.Length);
    cStream.FlushFinalBlock();
    cStream.Close();

    //Get the output
    output = mStream.ToArray();

    //Close resources
    mStream.Close();
    alg.Clear();
}

Secure Code:

Use the AesManaged algorithm for symmetric encryption.

using (MemoryStream mStream = new MemoryStream())
{
    //Input bytes
    byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);

    SymmetricAlgorithm alg = new AesManaged();

    //Set key and iv
    alg.Key = GetKey();
    alg.IV = GetIv();

    //Create the crypto stream
    CryptoStream cStream = new CryptoStream(mStream, alg.CreateEncryptor(), CryptoStreamMode.Write);
    cStream.Write(inputBytes, 0, inputBytes.Length);
    cStream.FlushFinalBlock();
    cStream.Close();

    //Get the output
    output = mStream.ToArray();

    //Close resources
    mStream.Close();
    alg.Clear();
}

The DES algorithm is deprecated and not an approved algorithm for performing symmetric encryption.

Do NOT use DES to protect sensitive information. Instead, use the AES (aka Rijndael) algorithm for all symmetric encryption operations.

References:

http://csrc.nist.gov/groups/ST/toolkit/block_ciphers.html https://msdn.microsoft.com/en-us/library/system.security.cryptography.aesmanaged(v=vs.110).aspx

SEC0026 - Weak Cipher Mode: ECB

Insecure Code:

The following example shows the AES algorithm setting the Mode to the CipherMode.ECB option:

using (MemoryStream mStream = new MemoryStream())
{
    //Input bytes
    byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);

    SymmetricAlgorithm alg = new DESCryptoServiceProvider();
    alg.Mode = CipherMode.ECB;

    //Set key and iv
    alg.Key = GetKey();
    alg.IV = GetIv();

    //Create the crypto stream
    CryptoStream cStream = new CryptoStream(mStream, alg.CreateEncryptor(), CryptoStreamMode.Write);
    cStream.Write(inputBytes, 0, inputBytes.Length);
    cStream.FlushFinalBlock();
    cStream.Close();

    //Get the output
    output = mStream.ToArray();

    //Close resources
    mStream.Close();
    alg.Clear();
}

Secure Code:

Set the AES algorithm mode set to CipherMode.CBC option and generate a unique initialization vector for each input:

using (MemoryStream mStream = new MemoryStream())
{
    //Input bytes
    byte[] inputBytes = Encoding.UTF8.GetBytes(plainText);

    SymmetricAlgorithm alg = new AesManaged();
    alg.Mode = CipherMode.CBC;

    //Set key and iv
    alg.Key = GetKey();
    alg.IV = GetIv();

    //Create the crypto stream
    CryptoStream cStream = new CryptoStream(mStream, alg.CreateEncryptor(), CryptoStreamMode.Write);
    cStream.Write(inputBytes, 0, inputBytes.Length);
    cStream.FlushFinalBlock();
    cStream.Close();

    //Get the output
    output = mStream.ToArray();

    //Close resources
    mStream.Close();
    alg.Clear();
}

The symmetric Electronic Codebook (ECB) mode encrypts blocks individually without using an initialization vector. Encrypting data in ECB mode fails to provide entropy for identical plaintext blocks being encrypted with the same encryption key. This can allow attackers to identify patterns and repetition in ciphertext, and may lead to the discovery of the original encryption key. Use the CipherMode.CBC option for symmetric block cipher operations.

Instead, in .NET applications use the CipherMode.CBC mode for symmetric block cipher operations. Generate a random initialization vector for each piece of encrypted data (i.e. do not use hard-coded or static IVs) and store the IV alongside the ciphertext.

Applications decrypting ciphertext values from untrusted sources (request parameters or web service APIs) must verify the ciphertext’s integrity prior to decrypting the value. Consider using HMAC verification prior to decrypting the value.

References:

https://msdn.microsoft.com/en-us/library/system.security.cryptography.ciphermode(v=vs.110).aspx

SEC0027 - Weak Algorithm: MD5

Insecure Code:

The following example shows the MD5 algorithm hashing a piece of data:

HashAlgorithm hash = new MD5CryptoServiceProvider();
byte[] bytes = hash.ComputeHash(input);

Secure Code:

Use SHA256Managed or SHA512Managed for hashing operations (note: this is not enough for storing passwords):

HashAlgorithm hash = new SHA512Managed();
byte[] bytes = hash.ComputeHash(input);

The MD5CryptoServiceProvider class uses the weak MD5 algorithm and is not an approved hashing algorithm.

Use the SHA256Managed (at least) preferably SHA512Managed for hashing operations.

NOTE: This alone is not sufficient for password hashing, which requires a unique salt and an adaptive hashing algorithm / iterations. See the references below for more information on password hashing in .NET.

References:

https://msdn.microsoft.com/en-us/library/system.security.cryptography.md5cryptoserviceprovider(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha512(v=vs.110).aspx https://blogs.dropbox.com/tech/2016/09/how-dropbox-securely-stores-your-passwords/

SEC0028 - Weak Algorithm: SHA1

Insecure Code:

The following example shows the SHA1 algorithm hashing a piece of data:

HashAlgorithm hash = new SHA1CryptoServiceProvider();
byte[] bytes = hash.ComputeHash(input);

Secure Code:

Use SHA256Managed or SHA512Managed for hashing operations (note: this is not enough for storing passwords):

HashAlgorithm hash = new SHA512Managed();
byte[] bytes = hash.ComputeHash(input);

The SHA1 algorithm has known collision weaknesses and should not be used for security operations in new applications.

Use the SHA256Managed (at least) preferably SHA512Managed for hashing operations.

NOTE: This alone is not sufficient for password hashing, which requires a unique salt and adaptive hashing algorithm. See this blog post for secure password hashing in .NET.

References:

https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha1managed(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha256(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.security.cryptography.sha512(v=vs.110).aspx https://blogs.dropbox.com/tech/2016/09/how-dropbox-securely-stores-your-passwords/

Insecure Deserialization

Similar to other platforms, .NET deserialization vulnerabilities occur when applications deserialize untrusted data. Without validation (e.g. HMAC signature validation), deserializing untrusted data can lead to application crashes, unauthorized access to resources, and remote code execution.

Special thanks to @JBW_1 for his contributions to these rules. Whitepaper reference coming soon.

SEC0029 - Deserialization: Binary Formatter

Insecure Code:

The following example shows the BinaryFormatter Deserialize method deserializing a byte array without HMAC signature validation.

public static T GetObject<T>(byte[] bytes) where T : new()
{
    using (MemoryStream stream = new MemoryStream())
    {
        stream.Write(bytes, 0, bytes.Length);

        BinaryFormatter formatter = new BinaryFormatter();
        return (T)formatter.Deserialize(stream);
    }
}

Secure Code:

Ensure that the application performs signature validation (e.g. HMAC) before deserializing the data.

COMING SOON. C# SNIPPET TO HMAC VALIDATE THE BYTE ARRAY BEFORE DESERIALIZATION

Deserializing untrusted data using the following BinaryFormatter methods can allow attackers to execute arbitrary code and perform denial of service attacks against the server:

Avoid deserializing untrusted data (e.g. request parameters, web service parameters, data from external services) using the above dangerous methods. In cases where deserialization is required, ensure that the application performs signature validation (e.g. HMAC) before deserializing the data.

References:

https://msdn.microsoft.com/en-us/library/b85344hz(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/unsafedeserialize(v=vs.110).aspx

https://msdn.microsoft.com/en-us/library/unsafedeserializemethodresponse(v=vs.110).aspx

SEC0030 - Deserialization: Newtonsoft JSON

Insecure Code:

The following example shows the Newtonsoft JSON serialization TypeNameHandling setting set to All.

public static T GetObject<T>(string json) where T : new()
{
    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.TypeNameHandling = TypeNameHandling.Auto;
    return JsonConvert.DeserializeObject<T>(json, settings);
}

Secure Code:

Explicitly set the TypeNameHandling setting to None (which is the default) to prevent JSON deserialization vulnerabilities.

public static T GetObject<T>(string json) where T : new()
{
    JsonSerializerSettings settings = new JsonSerializerSettings();
    settings.TypeNameHandling = TypeNameHandling.None;
    return JsonConvert.DeserializeObject<T>(json, settings);
}

The Newtonsoft JSON DeserializeObject method can allow attackers to execute arbitrary code and perform denial of service attacks if the TypeNameHandling setting is set to a value other than None.

References:

http://www.newtonsoft.com/json/help/html/T_Newtonsoft_Json_TypeNameHandling.htm

Injection

Injection rules run against the application source code and look for calls to insecure methods. The following Injection patterns are supported:

SEC0106 - SQL Injection: Dynamic LINQ Query

Insecure Code:

The following example shows dynamic SQL passed to the ExecuteQuery LINQ method.

using (DbDataContext context = new DbDataContext())
{
    string q = "SELECT Name from Items where ProductCode = " + model.ProductCode;
    name = context.ExecuteQuery<string>(q).SingleOrDefault().ToString();
}

Secure Code:

Call the overloaded ExecuteQuery method that accepts a list of parameters in the second argument.

using (DbDataContext context = new DbDataContext())
{
    string q = "SELECT Name from Items where ProductCode = {0}";
    name = context.ExecuteQuery<string>(q, model.ProductCode).SingleOrDefault().ToString();
}

Concatenating untrusted data into a dynamic SQL string and calling vulnerable LINQ methods can allow SQL Injection:

To ensure calls to vulnerable LINQ methods are parameterized, pass parameters into the statement using the method’s second argument: params object[] parameters.

References:

https://msdn.microsoft.com/en-us/library/bb361109(v=vs.110).aspx

SEC0107 - SQL Injection: ADO.NET

Insecure Code:

The following example shows a snippet concatenating a request parameter into a dynamic SQL statement. The statement is executed using the ExecuteScalar method.

SqlCommand cmd = new SqlCommand("select count(*) from Users where UserName = '" + model.UserName + "'", cn);
string result = cmd.ExecuteScalar().ToString();

Secure Code:

Parameterize the query using the standard ADO.NET placeholders and set the parameter value.

SqlCommand cmd = new SqlCommand("select count(*) from Users where UserName = @UserName", cn);
SqlParameter parm = new SqlParameter("@UserName", NVarChar);
parm.Value = model.UserName;
cmd.Parameters.Add(parm);
string result = cmd.ExecuteScalar().ToString();

The System.Data.SqlClient.SqlCommand class allows applications to communicate directly to a backend database without using an Object Relational Mapping (ORM) framework. There are several vulnerable methods in this class that allow dynamic SQL statements to be constructed and executed against the database:

Ensure that calls to these methods do not concatenate untrusted data into dynamic SQL statements. Use parameter placeholders or stored procedures to prevent SQL Injection attacks.

References:

https://msdn.microsoft.com/en-us/library/system.data.sqlclient.sqlcommand(v=vs.110).aspx

SEC0108 - SQL Injection: Dynamic EF Query

Insecure Code:

The following example shows dynamic SQL passed to the ExecuteSqlCommand Entity Database method.

using (DbDataContext context = new DbDataContext())
{
    string q = "DELETE FROM Items WHERE ProductCode = '" + model.ProductCode + "'";
    context.Database.ExecuteSqlCommand(q);
}

Secure Code:

Call the overloaded ExecuteSqlCommand method that accepts a list of parameters in the second argument.

using (DbDataContext context = new DbDataContext())
{
    string q = "DELETE FROM Items WHERE ProductCode = @productCode";
    context.Database.ExecuteSqlCommand(q, model.ProductCode);
}

Concatenating untrusted data into a dynamic SQL string and calling vulnerable Entity Framework (EF) methods can allow SQL Injection:

To ensure calls to vulnerable EF methods are parameterized, pass parameters into the statement using the method’s second argument: params object[] parameters.

References:

https://msdn.microsoft.com/en-us/library/system.data.entity.database(v=vs.113).aspx

SEC0114 - LDAP Injection

Insecure Code:

The following example shows untrusted data being concatenated into directory entry filter without escaping LDAP control characters.

DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://DC={0}, DC=COM/", model.Domain);
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = string.Format("(name={0})", model.UserName);
SearchResultCollection resultCollection = searcher.FindAll();

Secure Code:

Encode untrusted data passed to the DirectoryEntry.Path property with the Web Protection Library’s (aka AntiXSS) LdapDistinguishedNameEncode method. Similarly, encode untrusted data passed to the DirectorySearcher.Filter property with the LdapFilterEncode method.

DirectoryEntry entry = new DirectoryEntry(string.Format("LDAP://DC={0}, DC=COM/", Encoder.LdapDistinguishedNameEncode(model.Domain));
DirectorySearcher searcher = new DirectorySearcher(entry);
searcher.SearchScope = SearchScope.Subtree;
searcher.Filter = string.Format("(name={0})", Encoder.LdapFilterEncode(model.UserName));
SearchResultCollection resultCollection = searcher.FindAll();

LDAP Injection vulnerabilities occur when untrusted data is concatenated into a LDAP Path or Filter expression without properly escaping control characters. This can allow attackers to change the meaning of an LDAP query and gain access to resources for which they are not authorized.

Fixing the vulnerability requires untrusted data to be encoded using the Web Protection Library (aka AntiXSS) LDAP encoding methods:

Encoder.LdapDistinguishedNameEncode() Encoder.LdapFilterEncode()

References:

https://msdn.microsoft.com/en-us/library/system.directoryservices.directoryentry(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.directoryservices.directorysearcher(v=vs.110).aspx https://wpl.codeplex.com/

Password Management

Applications responsible for password management inherit a tremendous amount of risk and responsibility. User passwords must be created with sufficient length / complexity, stored securely, and protected from brute force and cracking attempts. The following password management rules are currently supported:

SEC0017 - Identity Weak Password Complexity

Insecure Code:

The following example shows the ApplicationUserManager class configuring the PasswordValidator with a weak password complexity policy. This configuration, which is the default policy generated by Visual Studio, sets a minimum password length of 6 characters.

// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
    RequiredLength = 6
};

Secure Code:

Update the PasswordValidator configuration to meet your organization’s password complexity requirements. The following example shows a required length of 12 characters, along with at least one digit, upper, lower, and special character.

// Configure validation logic for passwords
manager.PasswordValidator = new PasswordValidator
{
    RequiredLength = 12,
    RequireDigit = true,
    RequireLowercase = true,
    RequireNonLetterOrDigit = true,
    RequireUppercase = true
};

Weak passwords can allow attackers to easily guess user passwords using wordlist or brute force attacks. Enforcing a strict password complexity policy mitigates these attacks by significantly increasing the time to guess a user’s valid password.

Out of the box, Visual Studio’s template for ASP.NET Identity-based authentication requires only 6 characters. Increasing the minimum length from 6 to 12 characters will significantly increase the strength of the passwords stored by the application. Additionally, requiring all of the character types (upper, lower, numeric, and special) requires even more computational power to crack passwords.

References:

https://msdn.microsoft.com/en-us/library/microsoft.aspnet.identity.passwordvalidator(v=vs.108).aspx

SEC0018 - Identity Password Lockout Disabled

Insecure Code:

The following example shows the SignInManager.PasswordSignInAsync method passing false in the shouldLockout parameter. This disables the Identity password lockout mechanism.

public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    [...]
    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: false);
    [...]
};

Secure Code:

Change the shouldLockout parameter value to true.

public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    [...]
    var result = await SignInManager.PasswordSignInAsync(model.Email, model.Password, model.RememberMe, shouldLockout: true);
    [...]
};

Password lockout mechanisms help prevent continuous brute force attacks again user accounts by disabling an account after a number of invalid attempts.

By default, Visual Studio’s template for ASP.NET Identity-based authentication disables the account lockout feature. Enable the lockout feature by editing the login action and setting the shouldLockout parameter to true.

References:

https://msdn.microsoft.com/en-us/library/mt173779(v=vs.108).aspx

Validation

Weak validation can allow attackers to take advantage of the application and attack other users. The following validation rules are currently supported:

SEC0019 - Missing AntiForgery Token Attribute

Insecure Code:

The following example shows the Enter action performing a transaction without using the ValidateAntiForgeryToken attribute.

[HttpPost]
public ActionResult Enter(int id, ContestEntryModel model)
{
    if (ModelState.IsValid)
    {
        submitContestEntry(id, model);
    }
}

Secure Code:

By adding the ValidateAntiForgeryToken attribute, the application will validate the __RequestVerificationToken request parameter before entering the contest.

[HttpPost]
[ValidateAntiForgeryToken]
public ActionResult Enter(int id, ContestEntryModel model)
{
    if (ModelState.IsValid)
    {
        submitContestEntry(id, model);
    }
}

Cross Site Request Forgery attacks occur when a victim authenticates to a target web site and then visits a malicious web page. The malicious web page then sends a fake HTTP request (GET, POST, etc.) back to the target website. The victim’s valid authentication cookie from the target web site is automatically included in the malicious request, sent to the target web site, and processed as a valid transaction under the victim’s identity.

In ASP.NET MVC, the ValidateAntiForgeryToken attribute protects applications using authentication cookies from CSRF attacks. Actions with this attribute search the request parameters for the __RequestVerificationToken and validate the value prior to executing the request.

This rule searches for all actions decorated with HTTP verbs that typically modify data (POST, PUT, DELETE, and PATCH). Any identified actions that are missing the ValidateAntiForgeryToken attribute raise a diagnostic warning.

References:

https://msdn.microsoft.com/en-us/library/system.web.mvc.validateantiforgerytokenattribute(v=vs.118).aspx

SEC0022 - Model Request Validation Disabled

Insecure Configuration:

The following example shows the ProductFeedback model setting the AllowHtml attribute on the Feedback property.

public class ProductFeedbackModel
{
        [Display(Name = "Rating")]
        public int Rating { get; set; }

        [Display(Name = "Feedback")]
        [AllowHtml]
        public string Feedback { get; set; }
}

Secure Configuration:

The following example removes the AllowHtml attribute to enable request validation.

public class ProductFeedbackModel
{
        [Display(Name = "Rating")]
        public int Rating { get; set; }

        [Display(Name = "Feedback")]
        public string Feedback { get; set; }
}

Request validation performs blacklist input validation for XSS payloads found in form and URL request parameters. Request validation has known bypass issues and does not prevent all XSS attacks, but it does provide a strong countermeasure for most payloads targeting a HTML context.

Request validation is enabled by default during model binding to dynamic HTML request parameters, but can be disabled on individual model properties using the AllowHtml attribute. The following countermeasures can help validate data and filter XSS payloads:

References:

[1] https://msdn.microsoft.com/en-us/library/system.web.mvc.allowhtmlattribute(v=vs.118).aspx

[2] https://msdn.microsoft.com/en-us/library/system.componentmodel.dataannotations.validationattribute.aspx

[3] https://wpl.codeplex.com/ **

** Version 4.3.0 is the recommended HTML sanitizer library version

SEC0023 - Action Request Validation Disabled

Insecure Configuration:

The following example shows the Save action using the ValidateInput(false) attribute to disable request validation.

[HttpPost]
[ValidateInput(false)]
public ActionResult Save(int id, ProductFeedbackModel model)
{

}

Secure Configuration:

The following example removes the ValidateInput(false) attribute to enable request validation.

[HttpPost]
public ActionResult Save(int id, ProductFeedbackModel model)
{

}

Request validation performs blacklist input validation for XSS payloads found in form and URL request parameters. Request validation has known bypass issues and does not prevent all XSS attacks, but it does provide a strong countermeasure for most payloads targeting a HTML context.

Request validation is enabled by default during model binding to dynamic HTML request parameters, but can be disabled on controllers and actions properties using the ValidateInput(false) attribute. The following countermeasures can help validate data and filter XSS payloads:

References:

[1] https://msdn.microsoft.com/en-us/library/system.web.mvc.validateinputattribute.aspx

[2] https://wpl.codeplex.com/ **

** Version 4.3.0 is the recommended HTML sanitizer library version

SEC0109 - Unvalidated MVC Redirect

Insecure Code:

The following example shows the Controller Redirect method called using an unvalidated request parameter.

public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    [perform auth logic]

    return this.Redirect(model.ReturnUrl);
}

Secure Code:

Validate the return URL is a local path (not absolute) to ensure an attacker cannot redirect the user to a malicious external domain.

public async Task<ActionResult> Login(LoginViewModel model, string returnUrl)
{
    [perform auth logic]

    if (Url.IsLocalUrl(returnUrl))
    {
        return this.Redirect(model.ReturnUrl);
    }
    else
    {
        return RedirectToAction("Index", "Home");
    }
}

Passing unvalidated redirect locations to the MVC Controller.Redirect method can allow attackers to send users to malicious web sites. This can allow attackers to perform phishing attacks and distribute malware to victims.

References:

https://msdn.microsoft.com/en-us/library/system.web.mvc.controller.redirect(v=vs.118).aspx

SEC0110 - Unvalidated Web Forms Redirect

Insecure Code:

The following example shows the Response.Redirect method called using an unvalidated request parameter.

protected void LoginUser_LoggedIn(object sender, EventArgs e)
{
    if (Request.QueryString["ReturnUrl"] != null)
        Response.Redirect(Request.QueryString["ReturnUrl"]);
}

Secure Code:

Validate the return URL is a relative path (not absolute) to ensure an attacker cannot redirect the user to a malicious external domain.

protected void LoginUser_LoggedIn(object sender, EventArgs e)
{
    Uri targetUri = null;

    if (Uri.TryCreate(Request.QueryString["ReturnUrl"], UriKind.Relative, out targetUri))
    {
        Response.Redirect(targetUri.ToString());
    }
    else
    {
        Response.Redirect("~/default.aspx");
    }
}

Passing unvalidated redirect locations to the Response.Redirect method can allow attackers to send users to malicious web sites. This can allow attackers to perform phishing attacks and distribute malware to victims.

References:

https://msdn.microsoft.com/en-us/library/a8wa7sdt(v=vs.110).aspx

SEC0111 - Path Tampering: MVC File Path Result

Insecure Code:

The following example shows the FilePathResult action result using the fileName request parameter to construct the file path location.

[HttpPost]
public FileResult Download(string fileName)
{
    string filePath = ConfigurationManager.AppSettings["DownloadDirectory"].ToString();
    return new FilePathResult(filePath + fileName, "application/octet-stream");
}

Secure Code:

Avoid using untrusted values when constructing a file path. Instead, store file paths in a trusted location, such as a configuration file, and use a unique identifier to construct the file name.

[HttpPost]
public FileResult Download(Guid fileId)
{
    string filePath = ConfigurationManager.AppSettings["DownloadDirectory"].ToString();
    filePath = string.Format("{0}{1}.pdf", filePath, fileId.ToString());
    return new FilePathResult(filePath, "application/octet-stream");
}

Path traversal vulnerabilities occur when an application does not properly validate file paths for directory traversal (../) and other malicious characters. This can allow attackers to download, overwrite, or delete unauthorized files from the server. Ensure file paths are read from a trusted location, such as a static resource or configuration file. Do not send file paths in request parameters, which can be modified by an attacker.

The ASP.NET MVC FilePathResult action result is used to stream file content to the browser. Failing to validate the file path in FilePathResult actions can allow path tampering vulnerabilities.

References:

https://msdn.microsoft.com/en-us/library/system.web.mvc.filepathresult(v=vs.118).aspx

SEC0112 - Path Tampering: Unvalidated File Path

Insecure Code:

The following example shows the File.Delete method called using a dynamic parameter from a REST service to construct the file path location.

public HttpResponseMessage Delete(string file)
{
    string path = Path.Combine(ConfigurationManager.AppSettings["DownloadPath"], file);
    File.Delete(path);
    return Request.CreateResponse(HttpStatusCode.OK);
}

Secure Code:

Avoid using untrusted values when constructing a file path. Instead, store file paths in a trusted location, such as a configuration file, and use a unique identifier to construct the file name.

[HttpPost]
public HttpResponseMessage Delete(Guid fileId)
{
    string path = Path.Combine(ConfigurationManager.AppSettings["DownloadPath"], fileId.ToString());
    File.Delete(path);
    return Request.CreateResponse(HttpStatusCode.OK);
}

Path traversal vulnerabilities occur when an application does not properly validate file paths for directory traversal (../) and other malicious characters. This can allow attackers to download, overwrite, or delete unauthorized files from the server. Ensure file paths are read from a trusted location, such as a static resource or configuration file. Do not send file paths in request parameters, which can be modified by an attacker.

This rule covers several APIs that are commonly called with dynamic file path data. Any of the following method calls require strict validation on the files being consumed by the API. Ensure file paths are read from a trusted location, such as a static resource or configuration file. Do not send file paths in request parameters, which can be modified by an attacker to contain dangerous characters (../). The following vulnerable sinks are covered by SEC0112:

References:

https://msdn.microsoft.com/en-us/library/system.io.file(v=vs.110).aspx https://msdn.microsoft.com/en-us/library/system.io.filestream(v=vs.110).aspx

SEC0113 - Certificate Validation Disabled

Insecure Code:

The following example shows the ServicePointManager.ServerCertificateValidationCallbacke method being overridden to always return a true value.

using (var handler = new WebRequestHandler())
{
    handler.ServerCertificateValidationCallback += (sender, cert, chain, sslPolicyErrors) => true;

    using (var client = new HttpClient(handler))
    {
        var request = client.GetAsync(string.Format("{0}{1}", BASE_URL, endpoint)).ContinueWith((response) =>
            {
                var result = response.Result;
                var json = result.Content.ReadAsStringAsync();
                json.Wait();
                item = JsonConvert.DeserializeObject<T>(json.Result);
            }
        );
        request.Wait();
    }
}

Secure Code:

This one is too easy. Don’t override the frameworks certificate validation to always return true.

using (var handler = new WebRequestHandler())
{
    using (var client = new HttpClient(handler))
    {
        var request = client.GetAsync(string.Format("{0}{1}", BASE_URL, endpoint)).ContinueWith((response) =>
            {
                var result = response.Result;
                var json = result.Content.ReadAsStringAsync();
                json.Wait();
                item = JsonConvert.DeserializeObject<T>(json.Result);
            }
        );
        request.Wait();
    }
}

Disabling certificate validation is common in testing and development environments. Quite often, this is accidentally deployed to production, leaving the application vulnerable to man-in-the-middle attacks on insecure networks.

Do not override the ServicePointManager.ServerCertificateValidationCallback method to always return true. If the development team is using self-signed certificates, use certificate pinning to ensure the application will only communicate with the trusted server certificate.

References:

https://msdn.microsoft.com/en-us/library/system.net.servicepointmanager…

https://www.owasp.org/index.php/Certificate_and_Public_Key_Pinning

C#