Partager via


Infrastructure de sécurité : gestion des exceptions | Atténuation des risques

Produit/Service Article
WCF
API Web
Application Web

WCF - Ne pas inclure le nœud serviceDebug dans le fichier de configuration

Intitulé Détails
Composant WCF
Phase SDL Build
Technologies applicables Générique, NET Framework 3
Attributs N/A
Informations de référence MSDN, Fortify Kingdom
Étapes Des services Windows Communication Framework (WCF) peuvent être configurés pour exposer des informations de débogage. Les informations de débogage ne doivent pas être utilisées dans les environnements de production. La balise <serviceDebug> définit si la fonctionnalité d’informations de débogage est activée pour un service WCF. Si l’attribut includeExceptionDetailInFaults est défini sur true, les informations sur les exceptions de l’application sont renvoyées aux clients. Les personnes malveillantes peuvent exploiter les informations supplémentaires qu’elles obtiennent de la sortie de débogage pour lancer des attaques ciblées sur l’infrastructure, la base de données ou d’autres ressources utilisées par l’application.

Exemple

Le fichier de configuration suivant inclut la balise <serviceDebug> :

<configuration> 
<system.serviceModel> 
<behaviors> 
<serviceBehaviors> 
<behavior name=""MyServiceBehavior""> 
<serviceDebug includeExceptionDetailInFaults=""True"" httpHelpPageEnabled=""True""/> 
... 

Désactivez les informations de débogage dans le service. Ceci peut être effectué en supprimant la balise <serviceDebug> du fichier de configuration de votre application.

WCF - Ne pas inclure le nœud serviceMetadata dans le fichier de configuration

Intitulé Détails
Composant WCF
Phase SDL Build
Technologies applicables Générique
Attributs Générique, NET Framework 3
Informations de référence MSDN, Fortify Kingdom
Étapes L’exposition publique des informations sur un service peut fournir aux personnes malveillantes une piste précieuse sur la manière dont elles peuvent exploiter le service. La balise <serviceMetadata> active la fonctionnalité de publication de métadonnées. Les métadonnées de service peuvent contenir des informations sensibles qui ne doivent pas être accessibles publiquement. Au minimum, autorisez uniquement les utilisateurs approuvés à accéder aux métadonnées et vérifiez que les informations inutiles ne sont pas exposées. Mieux encore, désactivez complètement la possibilité de publier des métadonnées. Une configuration WCF sûre ne contiendra pas la balise <serviceMetadata>.

Vérifier que la gestion des exceptions correcte est effectuée dans l’API web ASP.NET

Intitulé Détails
Composant API Web
Phase SDL Build
Technologies applicables MVC 5, MVC 6
Attributs N/A
Informations de référence Gestion des exceptions dans l’API web ASP.NET, Validation de modèle dans l’API web ASP.NET
Étapes Par défaut, la plupart des exceptions non interceptées dans l’API web ASP.NET sont converties en réponse HTTP avec le code d’état500, Internal Server Error

Exemple

Pour contrôler le code d’état renvoyé par l’API, HttpResponseException peut être utilisé comme indiqué ci-dessous :

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        throw new HttpResponseException(HttpStatusCode.NotFound);
    }
    return item;
}

Exemple

Pour contrôler davantage la réponse d’exception, la classe HttpResponseMessage peut être utilisée comme indiqué ci-dessous :

public Product GetProduct(int id)
{
    Product item = repository.Get(id);
    if (item == null)
    {
        var resp = new HttpResponseMessage(HttpStatusCode.NotFound)
        {
            Content = new StringContent(string.Format("No product with ID = {0}", id)),
            ReasonPhrase = "Product ID Not Found"
        }
        throw new HttpResponseException(resp);
    }
    return item;
}

Pour intercepter les exceptions non prises en charge qui ne sont pas du type HttpResponseException, des filtres d’exception peuvent être utilisés. Les filtres d’exception implémentent l’interface System.Web.Http.Filters.IExceptionFilter. La méthode la plus simple pour écrire un filtre d’exception consiste à le dériver de la classe System.Web.Http.Filters.ExceptionFilterAttribute et à remplacer la méthode OnException.

Exemple

Voici un filtre qui convertit des NotImplementedException exceptions en code d’état HTTP 501, Not Implemented :

namespace ProductStore.Filters
{
    using System;
    using System.Net;
    using System.Net.Http;
    using System.Web.Http.Filters;

    public class NotImplExceptionFilterAttribute : ExceptionFilterAttribute 
    {
        public override void OnException(HttpActionExecutedContext context)
        {
            if (context.Exception is NotImplementedException)
            {
                context.Response = new HttpResponseMessage(HttpStatusCode.NotImplemented);
            }
        }
    }
}

Plusieurs méthodes pour enregistrer un filtre d’exception d’API web sont possibles :

  • Par action
  • Par contrôleur
  • Globalement

Exemple

Pour appliquer le filtre à une action spécifique, ajoutez le filtre en tant qu’attribut à l’action :

public class ProductsController : ApiController
{
    [NotImplExceptionFilter]
    public Contact GetContact(int id)
    {
        throw new NotImplementedException("This method is not implemented");
    }
}

Exemple

Pour appliquer le filtre à toutes les actions sur un controller, ajoutez le filtre en tant qu’attribut à la classe controller :

[NotImplExceptionFilter]
public class ProductsController : ApiController
{
    // ...
}

Exemple

Pour appliquer le filtre globalement à tous les contrôleurs d’API web, ajoutez une instance du filtre à la collection GlobalConfiguration.Configuration.Filters. Les filtres d’exception de cette collection s’appliquent à n’importe quelle action de contrôleur d’API web.

GlobalConfiguration.Configuration.Filters.Add(
    new ProductStore.NotImplExceptionFilterAttribute());

Exemple

Pour valider un modèle, l’état du modèle peut être transmis à la méthode CreateErrorResponse comme indiqué ci-dessous :

public HttpResponseMessage PostProduct(Product item)
{
    if (!ModelState.IsValid)
    {
        return Request.CreateErrorResponse(HttpStatusCode.BadRequest, ModelState);
    }
    // Implementation not shown...
}

Vérifiez les liens dans la section Références pour plus d’informations sur la gestion exceptionnelle et la validation de modèle dans l’API web ASP.NET

Ne pas exposer les détails de sécurité dans les messages d’erreur

Intitulé Détails
Composant Application Web
Phase SDL Build
Technologies applicables Générique
Attributs N/A
Informations de référence N/A
Étapes

Des messages d’erreur génériques sont fournis directement à l’utilisateur sans inclure de données d’application sensibles. Voici quelques exemples de données sensibles :

  • Noms de serveur
  • Chaînes de connexion
  • Noms d’utilisateur
  • Mots de passe
  • Procédures SQL
  • Détail des échecs SQL dynamiques
  • Arborescence des appels de procédure et lignes de code
  • Variables stockées dans la mémoire
  • Emplacements de lecteur et de dossier
  • Points d’installation d’application
  • Paramètres de configuration d’hôte
  • Autres détails de l’application internes

L’interception de toutes les erreurs dans une application, la fourniture de messages d’erreur génériques, ainsi que l’activation des messages d’erreur personnalisés dans IIS permettent d’éviter la divulgation d’informations. La base de données SQL Server et la gestion des exceptions .NET, entre autres architectures de gestion des erreurs, sont particulièrement détaillées et extrêmement utiles à un utilisateur malveillant profilant votre application. N’affichez pas directement le contenu d’une classe dérivée de la classe d’exceptions .NET et vérifiez que vous disposez de la gestion des exceptions appropriée afin qu’une exception inattendue ne soit pas présentée directement par inadvertance à l’utilisateur.

  • Fournissez des messages d’erreur génériques directement à l’utilisateur qui résument les détails spécifiques trouvés directement dans le message d’exception/d’erreur
  • Ne présentez pas le contenu d’une classe d’exceptions .NET directement à l’utilisateur
  • Interceptez tous les messages d’erreur et, le cas échéant, informez l’utilisateur à l’aide d’un message d’erreur générique envoyé au client de l’application
  • N’exposez pas le contenu de la classe d’exceptions directement à l’utilisateur, et plus particulièrement la valeur renvoyée par .ToString(), ou les valeurs des propriétés Message ou StackTrace. Journalisez ces informations de manière sécurisée et présentez un message plus inoffensif à l’utilisateur

Implémenter la page de gestion des erreurs par défaut

Intitulé Détails
Composant Application Web
Phase SDL Build
Technologies applicables Générique
Attributs N/A
Informations de référence Modifier la boîte de dialogue des paramètres des pages d’erreur ASP.NET
Étapes

Lorsqu’une application ASP.NET échoue et provoque une erreur serveur interne HTTP/1.x 500, ou que la configuration d’une fonctionnalité (comme le filtrage des demandes) empêche l’affichage d’une page, un message d’erreur est généré. Les administrateurs peuvent choisir si l’application doit afficher ou non un message convivial pour le client, un message d’erreur détaillé au client ou un message d’erreur détaillé à l’hôte local uniquement. La balise <customErrors> dans le fichier web.config comporte trois modes :

  • On : spécifie que les erreurs personnalisées sont activées. Si aucun attribut defaultRedirect n’est spécifié, les utilisateurs voient une erreur générique. Les erreurs personnalisées sont présentées aux clients distants et à l’hôte local
  • Off : spécifie que les erreurs personnalisées sont désactivées. Les erreurs ASP.NET détaillées sont présentées aux clients distants et à l’hôte local
  • RemoteOnly : spécifie que les erreurs personnalisées sont visibles uniquement pour les clients distants, et que les erreurs ASP.NET sont visibles pour l’hôte local. Il s'agit de la valeur par défaut

Ouvrez le fichier web.config pour l’application/le site et vérifiez que la balise est définie sur <customErrors mode="RemoteOnly" /> ou <customErrors mode="On" />.

Définir la méthode de déploiement sur Vente au détail dans IIS

Intitulé Détails
Composant Application Web
Phase SDL Déploiement
Technologies applicables Générique
Attributs N/A
Informations de référence Élément de déploiement (schéma des paramètres ASP.NET)
Étapes

Le commutateur <deployment retail> est conçu pour être utilisé par les serveurs IIS de production. Ce commutateur est utilisé pour permettre aux applications de s’exécuter avec les meilleurs niveaux de performances et le moins de fuites d’informations de sécurité possibles en désactivant la capacité de l’application à générer la sortie de trace sur une page, en désactivant la capacité à afficher des messages d’erreur détaillés pour les utilisateurs finaux et en désactivant le commutateur de débogage.

Les commutateurs et les options destinés aux développeurs, comme le suivi et le débogage des échecs de demande, sont généralement activés pendant le développement actif. Il est recommandé de définir la méthode de déploiement de n’importe quel serveur de production sur Vente au détail. Ouvrez le fichier machine.config et vérifiez que <deployment retail="true" /> est toujours défini sur true.

Les exceptions doivent échouer en toute sécurité

Intitulé Détails
Composant Application Web
Phase SDL Build
Technologies applicables Générique
Attributs N/A
Informations de référence Échec en toute sécurité
Étapes L’application doit échouer en toute sécurité. Toute méthode renvoyant une valeur booléenne, en fonction de la décision prise, doit comporter un bloc d’exception créé avec soin. Il existe un grand nombre d’erreurs logiques dues à des problèmes de sécurité lorsque le bloc d’exception n’est pas écrit correctement.

Exemple

        public static bool ValidateDomain(string pathToValidate, Uri currentUrl)
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(pathToValidate))
                {
                    var domain = RetrieveDomain(currentUrl);
                    var replyPath = new Uri(pathToValidate);
                    var replyDomain = RetrieveDomain(replyPath);

                    if (string.Compare(domain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
                    {
                        //// Adding additional check to enable CMS urls if they are not hosted on same domain.
                        if (!string.IsNullOrWhiteSpace(Utilities.CmsBase))
                        {
                            var cmsDomain = RetrieveDomain(new Uri(Utilities.Base.Trim()));
                            if (string.Compare(cmDomain, replyDomain, StringComparison.OrdinalIgnoreCase) != 0)
                            {
                                return false;
                            }
                            else
                            {
                                return true;
                            }
                        }

                        return false;
                    }
                }

                return true;
            }
            catch (UriFormatException ex)
            {
                LogHelper.LogException("Utilities:ValidateDomain", ex);
                return true;
            }
        }

La méthode ci-dessus renvoie toujours la valeur True si une exception se produit. Si l’utilisateur final fournit une URL incorrecte acceptée par le navigateur mais pas par le constructeur Uri(), une exception est levée et la victime est dirigée vers l’URL valide mais mal formée.