API8:2019 Injection
Facteurs de menace / Vecteurs d'attaque | Faille de sécurité | Impact |
---|---|---|
Spécifique API : Exploitabilité 3 | Prévalence 2 : Détectabilité 3 | Technique 3 : Spécifique à l'organisation |
Les attaquants vont envoyer à l'API des données malveillantes via tout vecteur d'injection disponible (ex : entrée directe, paramètres, services intégrés, etc), en espérant qu'elles soient envoyés à un interpréteur. | Les failles par injection sont très courantes et souvent trouvées dans des requêtes SQL, LDAP, ou NoSQL, des commandes systèmes (OS), des parsers XML et des ORM. Ces failles sont faciles à trouver lors de la revue du code source. Les attaquants peuvent utiliser des scanners et des fuzzers. | L'injection peut aboutir à des divulgations d'informations et des pertes de données. Elle peut aussi aboutir à un déni de service, ou à une prise de contrôle complète de l'hôte. |
L'API est-elle vulnérable ?
L'API est vulnérables à l'injection si :
- Les données fournies par le client ne sont pas validées, filtrées et épurées par l'API.
- Les données fournies par le client sont directement utilisées ou concaténées dans des requêtes SQL / NoSQL / LDAP, des commandes de système d'exploitation, des parsers XML ou des mappages objet-relationnel (ORM) / mappages objet-document (ODM).
- Les données en provenance de systèmes externes (ex : systèmes intégrés) ne sont pas validées, filtrées et épurées par l'API.
Exemples de scénarios d'attaque
Scénario #1
Le firmware d'un appareil de contrôle parental dispose d'un point d'accès
/api/CONFIG/restore
qui prend en entrée un appId devant être envoyé comme
paramètre multiparties. Avec un décompilateur, un attaquant découvre que
l'appId est passé directement dans un appel système sans aucune épuration :
snprintf(cmd, 128, "%srestore_backup.sh /tmp/postfile.bin %s %d",
"/mnt/shares/usr/bin/scripts/", appid, 66);
system(cmd);
La commande suivante permet à l'attaquant d'arrêter tout appareil équipé de ce même firmware vulnérable :
$ curl -k "https://${deviceIP}:4567/api/CONFIG/restore" -F 'appid=$(/etc/pod/power_down.sh)'
Scénario #2
Nous avons une application dotée de fonctionnalités CRUD basiques pour les
opérations de réservation. Un attaquant a réussi à découvrir qu'une injection
NoSQL pourrait être possible via le paramètre bookingId
de la chaine de
requête pour la suppression d'une réservation. Voici à quoi ressemble cette
requête : DELETE /api/bookings?bookingId=678
.
L'API serveur utilise la fonction suivante pour traiter les requêtes de suppression :
router.delete('/bookings', async function (req, res, next) {
try {
const deletedBooking = await Bookings.findOneAndRemove({'_id' : req.query.bookingId});
res.status(200);
} catch (err) {
res.status(400).json({error: 'Unexpected error occured while processing a request'});
}
});
L'attaquant a intercepté la requête et a remplacé le paramètre bookingId
de
la chaine de requête comme indiqué ci-dessous. Dans le cas présent, l'attaquant
a réussi à supprimer la réservation d'un autre utilisateur :
DELETE /api/bookings?bookingId[$ne]=678
Comment s'en prémunir
Prévenir les injections requiert de séparer les données des commandes et des requêtes.
- Effectuez la validation des données avec une bibliothèque unique, digne de confiance et activement maintenue.
- Validez, filtrez et épurez toutes les données fournies par le client, ou les autres données en provenance de systèmes intégrés.
- Les caractères spéciaux doivent être échappés en utilisant la syntaxe spécifique à l'interpréteur cible.
- Préférez une API sûre qui fournit une interface paramétrée.
- Limitez toujours le nombre d'enregistrements retournés pour éviter les divulgations de masse en cas d'injection.
- Validez les données entrantes avec suffisamment de filtres pour accepter uniquement les valeurs valides pour chaque paramètre d'entrée.
- Définissez des types de données et des schémas stricts pour tous les paramètres de chaines.