Lignes directrices

Authentification et autorisation

Le sujet de l'authentification (AuthN) et de l'autorisation (AuthZ) est extrêmement important en raison de la fréquence des vulnérabilités impliquant l'un ou l'autre de ces éléments. Comme elles semblent revenir si régulièrement, cela signifie généralement qu'il y a un peu d'incertitude sur ce qu'elles sont ou même sur ce qui les provoque. 

Pour rappel, chaque trimestre couvre les points suivants :

  • Authentification : Qui est l'utilisateur ? 
  • Autorisation : A quoi l'utilisateur doit-il avoir accès ? 

Nous les examinerons séparément ci-dessous.

Authentification (échecs d'identification et d'authentification)

Une mauvaise authentification peut couvrir une grande variété de vulnérabilités, telles que

  • L'absence d'authentification sur une page/un point de terminaison spécifique
  • Absence de protection contre les attaques par force brute (Credentials stuffing)
  • Processus de récupération des comptes/mots de passe non sécurisés
  • La génération, la validation, l'expiration, la transmission ou le stockage des jetons d'authentification ne sont pas sécurisés.
  • Validation incorrecte ou manquante du fait que l'utilisateur s'est authentifié avec 2FA (le cas échéant)

Le premier point de la liste (absence d'authentification) est de loin le problème le plus courant observé dans la nature. Souvent, un développeur doit explicitement annoter/configurer le niveau d'authentification requis par une page ou un point de terminaison, et cette étape peut facilement être omise. 

Une bonne pratique consiste à s'assurer qu'un système est fermé en cas d'échec, plutôt qu'ouvert en cas d'échec. Ainsi, plutôt que d'annoter chaque point d'accès avec l'information qu'il nécessite une session utilisateur authentifiée, la valeur par défaut devrait être que tous les itinéraires nécessitent une session utilisateur authentifiée, à moins qu'elle n'ait été spécifiquement surchargée. Cela permet de réduire considérablement les risques d'erreur.

Autorisation (contrôle d'accès interrompu)

Les problèmes d'autorisation peuvent se présenter sous différentes formes très courantes :

  • Références directes non sécurisées (IDOR)
  • Contrôle d'accès au niveau de la fonction manquant (AuthZ manquant)
  • Augmentation des privilèges (horizontale ou verticale)

Références à l'objet direct incertaines

Les objets ont tendance à avoir des identifiants uniques (ID) qui sont utilisés comme clé pour les référencer. Lorsqu'un utilisateur envoie une demande pour consulter une commande, un compte ou quelque chose de similaire, cette demande contient généralement cet identifiant. Une "référence directe d'objet non sécurisée" se produit lorsque l'application ne parvient pas à valider si l'utilisateur (ou l'absence d'utilisateur) devrait être en mesure d'accéder à cet objet spécifique.

Absence de contrôle d'accès au niveau de la fonction 

Une autre vulnérabilité très courante est l'absence de contrôles d'autorisation pour une page ou un point final (par opposition à un objet). 

En fonction du cadre utilisé, il est courant que les développeurs doivent soit vérifier l'autorisation dans le gestionnaire, soit annoter le point final et spécifier les exigences requises pour appeler le point final. 

Malheureusement, ces étapes supplémentaires sont également très faciles à oublier, ce qui explique souvent comment certaines vulnérabilités en matière d'autorisation finissent par se produire.

Recommandations

Fermé par défaut au lieu d'ouvert

Dans le cas de l'authentification et de l'autorisation, il est important de choisir par défaut le mode fermé plutôt que le mode ouvert. 

En fonction de votre langage/cadre de travail, une bonne pratique consiste à s'assurer que la valeur par défaut de tous les chemins d'accès à votre application nécessite une session authentifiée avec les rôles ou les autorisations les plus élevés possibles. Cela oblige le développeur à passer outre les exigences de l'itinéraire. 

cs

// Ensure the default behaviour is to authenticate requests, and check if they are admin
[Authenticate]
[Authorize("Admin")]
public class SecureController : Controller
{

}

public class MyController : SecureController
{

    // Overrides the Authorize attribute inherited to allow any user to access the page
    [Authorize("User")]
    public Page ShowUserProfile() {
        
    }   

    // Can only be accessed by an Admin user
    public Page ShowAdminPage() { 

   }

    // Overrides the Authenticate and Authorize attribute to allow ME
    [AllowAnonymous]
    public Page ShowLoginPage() {
       
    } 

}

Renforcer les contrôles d'autorisation dans les services

Lorsque vous accédez à des données, il est extrêmement important de veiller à ce que tous les accès aux données appliquent les contrôles d'accès et d'autorisation pertinents de manière uniforme. Cela se fait généralement par l'utilisation d'un service de domaine.

Autres exemples

Vous trouverez ci-dessous une courte série d'exemples qui illustrent bien la différence entre une authentification et une autorisation sûres et non sûres. 

C# - peu sûr

Authentification manquante

public class AdminController : Controller
{

    // INSECURE: Does not check whether the user is logged in before showing an Admin page
    public Page ShowAdminPage() {

    }

}

Autorisation manquante

[Authenticate]
public class AdminController : Controller
{

    // INSECURE: Does not check the Authorization of the user before showing an Admin page public Page ShowAdminPage() {

    }

}

C# - sécurisé

[Authenticate]
[Authorize("Admin")]
public class AdminController : Controller
{

    // SECURE: Both checks that the user is logged in, and has the Admin role
    public Page ShowAdminPage() {

    }

}