Je suis l'auteur d'une API JSON REST. Cette API REST est consommée par divers clients, tels que les clients HTML/JS, les clients .NET ( applications console) et Ruby clients. La sortie de l'API est au format JSON, donc elle est formatée selon les règles JSON et les caractères spéciaux nécessaires sont échappés.
Un chercheur en sécurité m'a signalé que <
et >
ne sont pas échappés dans la sortie, donc si un attaquant a fait une requête telle que HTTP POST https://my.api.example.com/blabla with le corps JSON {Value:"<Hello>"}
alors mon API affichera quelque chose comme {Response:"<Hello> is not a valid value"}
.
Le chercheur en sécurité a ensuite expliqué qu'un attaquant pourrait être en mesure de faire un script intersite réfléchi en utilisant ceci.
Mon API JSON renvoie toujours un Content-Type: application/json
header donc ma compréhension est que les clients modernes n'essaieront pas de l'interpréter comme HTML.
<
et >
sont des caractères valides dans mon API, je ne peux donc pas les filtrer. Une option serait de coder les caractères dans la sortie, mais les caractères de codage HTML dans une API JSON me semblent un peu étranges. Une troisième option serait de simplement supprimer la chaîne de la sortie et de dire à la place quelque chose comme "La valeur fournie n'était pas valide", mais cela réduirait un peu la convivialité.
Existe-t-il de bonnes pratiques communes pour gérer cela?
Pouvez-vous compter sur l'en-tête Content-Type? Non
Comme dit parfaitement dans la réponse à cette question security.stackexchange.com , nous ne pouvons pas compter sur les clients pour respecter les en-têtes de type de contenu en matière de sécurité.
Comment encoder JSON?
OWASP fournit des conseils pour exactement votre situation. Ils disent que si le contexte est HTML, alors vous encodez votre sortie pour ce contexte. Ils disent aussi:
Une alternative à l'échappement et à l'échappement de JSON directement en JavaScript consiste à normaliser le côté serveur JSON en convertissant "<" en "\ u003c" avant de le livrer au navigateur.
Dans une certaine mesure, c'est une question d'opinion, mais je ne pense pas qu'il y ait une vulnérabilité ici. Si un client reflète les données HTML de votre réponse JSON sans aucun nettoyage, il s'agit d'une vulnérabilité dans ce client et non dans votre API. Toute page Web doit traiter les réponses de l'API comme des données non fiables.
Vous avez raison de dire que le codage HTML de la réponse est une mauvaise idée. Pourquoi l'API devrait-elle faire des hypothèses sur ce qu'est un encodage approprié pour le client? Que se passe-t-il si vous souhaitez également utiliser l'API pour une application mobile où les données seront affichées dans un contexte non HTML? L'encodage HTML serait juste une mauvaise conception. Cela résoudrait un problème pour le client côté serveur.
Ce que je ferais à la place, c'est de documenter clairement que la sortie peut contenir des caractères spéciaux HTML et que le client devrait prendre les mesures appropriées.
Une chose, cependant: assurez-vous de répondre avec un en-tête sans reniflement. Sans cela, les navigateurs mimant le reniflement pourraient interpréter la réponse comme HTML ou JS, ce qui constituerait une véritable vulnérabilité.
Tout d'abord, les en-têtes ne sont pas strictement fiables. Et bien que cette vulnérabilité XSS potentielle ne soit peut-être pas un problème maintenant, vous ne pouvez pas savoir exactement comment votre API sera utilisée à l'avenir. Quelque part sur la route, quelqu'un pourrait utiliser des valeurs de réponse en HTML, ouvrant ainsi la possibilité de certains XSS.
Ce n'est peut-être pas votre problème en soi, vous devez toujours valider votre entrée et désinfecter votre sortie.
<>
serait des caractères valides dans votre entrée? `<>
chaque fois qu'une entrée ne correspond pas aux scénarios définis précédemment?Comme pour tout, OWASP a un excellent guide (appelé "cheat sheet") pour les développeurs Web sur la façon d'empêcher XSS ( en particulier en JSON ). Leur json-sanitizer
projet sur GitHub pourrait également être intéressant à vérifier.