Utilisation d'un caractère slash dans les URL Spring

1. Introduction

Lorsque nous développons des services Web, nous pouvons avoir besoin de gérer des chemins d'URL complexes ou inattendus pouvant contenir des barres obliques . En conséquence, nous pouvons rencontrer des problèmes avec les serveurs Web ou les frameworks que nous utilisons.

Spring en particulier peut être un peu délicat à cet égard en raison des configurations par défaut qu'il fournit.

Dans ce didacticiel, nous montrerons quelques solutions et recommandations courantes pour gérer les URL avec des barres obliques dans Spring . Nous verrons également pourquoi nous ne devrions pas utiliser certains hacks courants pour contourner ces problèmes. Continuez à lire pour en savoir plus!

2. Analyser la demande manuellement

Dans nos services Web, nous devons parfois mapper toutes les demandes sous un certain chemin vers le même point de terminaison. Pour aggraver les choses, nous ne savons peut-être pas à quoi ressemblera le reste du chemin. Nous pourrions également avoir besoin de recevoir ce chemin en tant que paramètre pour pouvoir l'utiliser par la suite.

Disons que nous pouvons recevoir des requêtes avec n'importe quel chemin sous / mypaths :

//localhost:8080/mypaths/any/custom/path

Et supposons que nous voulions stocker tous ces chemins différents dans une base de données pour savoir quelles demandes nous recevons.

La première solution qui nous viendra probablement à l'esprit est de capturer la partie dynamique du chemin dans une PathVariable :

@GetMapping("mypaths/{anything}") public String pathVariable(@PathVariable("anything") String anything) { return anything; }

Malheureusement, nous découvrons bientôt que cela renvoie un 404 si la variable PathVariable contient une barre oblique . Le caractère barre oblique est le délimiteur de chemin d'accès standard URI, et tout ce qui va après compte comme un nouveau niveau dans la hiérarchie des chemins. Comme prévu, Spring suit cette norme.

Nous pouvons facilement résoudre ce problème en créant une solution de secours pour toutes les requêtes sous un certain chemin en utilisant le caractère générique ** :

@GetMapping("all/**") public String allDirectories(HttpServletRequest request) { return request.getRequestURI() .split(request.getContextPath() + "/all/")[1]; }

Ensuite, nous devons analyser l'URI nous-mêmes afin d'obtenir la partie du chemin qui nous intéresse.

Cette solution est très pratique lorsque vous travaillez avec des paramètres de type URL , mais comme nous le verrons dans la section suivante, elle ne suffit pas pour certains autres cas.

3. Utiliser les paramètres de requête

Contrairement à notre exemple précédent, il existe d'autres cas où nous ne mappons pas seulement différents chemins, mais recevons n'importe quelle chaîne en tant que paramètre dans l'URL.

Imaginons que dans notre exemple précédent, nous effectuons une requête avec un paramètre de chemin contenant des barres obliques consécutives :

//localhost:8080/all///myurl.com

Au début, on pouvait penser que cela devrait marcher, mais on se rend vite compte que notre contrôleur renvoie http: /myurl.com. Cela se produit parce que Spring Security normalise les URL et remplace toute double barre oblique par une seule .

Spring normalise également d'autres séquences dans les URL, telles que les traversées de chemins. Il prend ces précautions pour empêcher les URL malveillantes de contourner les contraintes de sécurité définies , comme expliqué dans la documentation officielle de Spring Security.

Dans ces cas, il est fortement recommandé d'utiliser à la place des paramètres de requête:

@GetMapping("all") public String queryParameter(@RequestParam("param") String param) { return param; }

De cette façon, nous pouvons recevoir n'importe quel paramètre String sans ces restrictions de sécurité, et notre service Web sera plus robuste et sécurisé.

4. Évitez les solutions de contournement

Les solutions que nous avons présentées peuvent impliquer des changements dans la conception de nos mappages. Cela pourrait nous inciter à utiliser des solutions de contournement courantes pour faire fonctionner nos points de terminaison d'origine lors de la réception de barres obliques dans les URL.

La solution de contournement la plus courante consiste probablement à encoder les barres obliques dans les paramètres de chemin. Cependant, certaines vulnérabilités de sécurité ont été signalées dans le passé et la plupart des serveurs Web et d'applications y ont réagi en interdisant les barres obliques codées par défaut . Il est toujours possible de modifier ce comportement en modifiant simplement le paramètre correspondant, comme dans Tomcat.

D'autres comme Apache Server sont allés un peu plus loin et ont introduit une option permettant d'autoriser les barres obliques codées sans les décoder afin qu'elles ne soient pas interprétées comme des délimiteurs de chemin. Dans tous les cas, cela n'est pas recommandé et peut présenter des risques de sécurité potentiels.

D'autre part, les frameworks Web prennent également quelques précautions. Comme nous l'avons vu précédemment, Spring ajoute des mécanismes de protection contre les conteneurs de servlet moins stricts . Donc, si nous autorisons les barres obliques codées sur notre serveur, nous devons toujours les autoriser dans Spring.

Enfin, il existe d'autres types de solutions de contournement telles que la modification de la normalisation d'URI que Spring fournit par défaut. Comme auparavant, nous devons être très prudents si nous modifions ces valeurs par défaut.

5. Conclusion

Dans ce court article, nous avons montré quelques solutions pour gérer les barres obliques dans les URL au printemps. Nous avons également introduit des problèmes de sécurité qui peuvent survenir si nous modifions les configurations par défaut des serveurs ou des frameworks comme Spring.

En règle générale, les paramètres de requête sont généralement la meilleure solution pour gérer les barres obliques dans les URL.

Comme toujours, le code source complet des exemples est disponible à l'adresse over sur GitHub.