Voilà un petit retour d'expérience sur les audits d'applications 3-tiers.

Pour commencer, mettons nous d'accord sur les termes.

  • Architecture 2-tiers:

Un client dialogue avec un serveur. Dans la plupart des cas, il s'agit d’un client lourd qui se connecte à une base de données.

  • Architecture 3-tiers:

Un client parle à un serveur qui parle à un autre serveur. Dans la vraie vie il s'agit d'un client qui dialogue avec un serveur applicatif qui lui même dialogue avec une base de données.

Voilà pour une terminologie approximative!

Pour la plupart des informaticiens, les vulnérabilités d'une application en architecture deux tiers sont assez évidentes.

Voici par exemple quelques problèmes rencontrés fréquemment sur du 2-tiers:

  • Les secrets sont souvent stockés côté client dans un fichier de configuration, dans un script ou codés en dur dans le binaire ou en mémoire.
  • Le client via son IHM, se connecte directement à la base de données pour envoyer des actions. Il est facile d'intercepter et de modifier les requêtes SQL envoyées à la base avec des outils comme EchoMirage.
  • L'utilisateur utilise un compte de base de données pour lancer l'application. Il est alors possible de se connecter directement à la base avec son client SQL. Cela pourrait ne poser aucun problème (ou presque ^^) s'il était facile pour les DBAs ou aux équipes de support de gérer finement la ségrégation verticale/horizontale de centaines ou de milliers utilisateurs directement en base. Les utilisateurs ont donc accès à l'ensemble des données contenus dans la base aussi bien en lecture qu'en écriture... Génial.
  • L'application utilise un unique compte de base pour tous les clients. Ainsi au lancement de l'application, le client se connecte à la base avec un compte générique pour vérifier les identifiants applicatifs stockés en base. Il est possible de faire du SQL tampering pendant l'authentification applicative et d'accéder à la base pour récupérer tous les comptes applicatifs, ou pour valider son authentification.
  • La plupart des permissions applicatives sont gérées côté client, Eureka et les fenêtres se dégrisent ;-)

Voilà, une fois que l'on a réalisé tout ça, et qu'on a pardonné aux architectes des années Mitnick d'avoir déguisé un client SQL en une application de Trading (par exemple), on peut envisager le passage aux architectures 3-tiers pour les futures applications.

On utilise alors le tiers applicatif supplémentaire pour contrôler les accès clients aux données, et on y gère aussi les secrets d'accès à la base. Tout est parfait.

Le billet aurait même pu s'arrêter là, (ou même n'avoir jamais existé), mais cela voudrait dire que TOUS les développeurs et architectes de profession savent pourquoi ils sont passés d'une architecture 2-tiers à du 3-tiers... (10 minutes d'auto flagellation pour tous ceux qui ont cru cela possible).

En effet, la sécurité n'est encore bien souvent qu'un mirage dans l'esprit des développeurs, et cela est d'autant plus frappant (déprimant) lorsqu'on s'aperçoit que certaines applications 3-tiers ne sont pas plus sécurisées que des 2-tiers voire réimplémentent les mêmes vulnérabilités.

Pour appuyer mes dires (et pour se marrer un peu aussi =)), notre "consultant proxy" Melvin Kitnick nous a préparé une petite séléction de vulnérabilités qu'il a croisé dans des applications 3-tiers ces dernières années (tous secteurs confondus):

Les classiques du 3-tiers:

1. Les identifiants de base de données sont inutiles MAIS disponibles côté client. On les retrouve dans un fichier de configuration, dans le binaire ou dans la mémoire après le lancement du client (Si si je vous assure c'est vrai et relativement fréquent).

2. Les contrôles des permissions sont effectués uniquement côté client (à la mode 2-tiers) et non sur le tiers serveur applicatif. En bref, un attaquant peut accéder à des fonctionnalités ne correspondant pas à son profil utilisateur, par exemple en modifiant le client, ou plus simplement, en d'interceptant et en modifiant les données échangées avec le serveur.

Il est souvent possible de modifier son profil à la réception ou bien de modifier des actions à l'envoi, Enfin, il est parfois possible en utilisant un utilitaire de kiddies de réactiver les boutons de fonctionnalités auxquelles votre profil utilisateur n'a pas accès. (Oui aussi sur du 3-tiers ;-))

Les moins classiques mais croisés plusieurs fois:

3. Dans la même famille que la précédente, le mot de passe est vérifié côté client. Chez nous, le client est roi, et c'est lui qui décide si son mot de passe est bon. Par la même occasion il est alors possible de récupérer les hashs et mots de passe de n'importe quel utilisateur.

4. Il n'est pas rare que certaines applications soient très mal packagées. Le client lourd distribué aux utilisateurs contient les classes compilées et les fichiers de configuration du serveur... et donc les secrets qu'il embarque.

Le cas particulier

5. Une équipe de développeurs pleine de bon sens se dit Tain', les gars, c’est trop la honte d'avoir une appli 2-tiers ! Même mes enfants se foutent de ma gueule, leur prof d'électrotechnique leur a dit que ça n'existait plus le 2-tiers. Allez on fait péter les technos applicatives et on passe en 3-tiers.

Héhé, c'est super bien comme initiative, mais ça prend du temps de refaire une application... des mois voire des années. Et pendant ce temps, l'application est un chantier digne du désamiantage des Twin Towers ou de Jussieu… Pendant ce chantier, certaines fonctionnalités sont donc en 2-tiers (accès direct à la base) et d'autres en trois tiers...

Le résultat est une application "best of both worlds", pwnable en 2 minutes malgré l'archi 3-tiers. Tant qu'il restera une fonctionnalité ayant un comportement 2-tiers, on ne profitera pas de l'avantage sécurité de l'archi 3-tiers. Logique non? Ben pas pour tout le monde...

La palme

6. Le client envoie des requêtes SQL au serveur applicatif, qui les exécutent sans modification sur le serveur de base de données. 1 minute de silence (profitez en pour pwner la base)...

Conclusion

Que penser de ça ? Comment en arrive t-on là, en ayant pris la bonne décision d'archi dès le début ? S’agit-il d'un simple manque de formation, de fainéantise, de temps, ou d'un désintéressement pour la sécurité ?

La réponse est sûrement un mélange de tout ça. Sans oublier l'effet marketing du 3-tiers à la mode dans le bancaire, qui fait croire que le simple choix de cette architecture sécurise l'application... c'est comme croire qu'un site Web est sécurisé grâce au SSL. C'est bien mais c'est pas suffisant ...

Enfin bref, je ne suis pas là pour tirer sur l'ambulance, mais juste pour rappeler qu'un des buts d'une archi 3-tiers et d'éviter ces désagrément:

  • Le client n'accède pas directement à la base, il envoie ses demandes d'accès aux données au serveur applicatif, qui se chargera après autorisation, d'effectuer les accès base nécessaires.
  • Le serveur applicatif vérifie toujours les permissions des clients avant d'exécuter leurs actions.
  • Le serveur applicatif filtre les données envoyées par le client avant de les réutiliser.
  • Le client n'embarque pas de secrets compromettant pour l'application (mot de passe de base, clefs, "intelligence" applicative).

C'est très synthétique et vulgarisé, mais s’il y a des développeurs qui lisent ce billet, demandez-vous si vous respectez les 4 derniers points. Si celà n'est pas le cas, vous savez ce qu'il vous reste à faire (ou pas, comme dirait Hurukan :-) ).

Si oui, "BRAVO !" vous méritez une augmentation et vous pouvez maintenant penser à chiffrer les flux entre vos tiers. (Mouhahaha) ;) .