HTTP

Le protocole HTTP est utilisé par les navigateurs web pour obtenir des documents hébergés par les serveurs.
Le navigateur se connecte en TCP à un serveur, sur le port 80 par défaut.
La requête minimale contient une commande (ici GET), une URL (/hello.txt), une ligne vide.

GET /hello.txt

La réponse contient directement le fichier.

Hello world
$ printf 'GET /hello.txt \n\r\n' | nc localhost 8001

La version 1.1 du protocole HTTP est optimisée pour transférer des pages HTML complexes, et permet de négocier la langue et les formats d'encodages.
La requête minimale contient une commande (GET), une url (/hello.txt), la version (HTTP/1.1), le champ Host, une ligne vide.

GET /hello.txt HTTP/1.1
Host: 10.10.10.11 80

La réponse contient une entête composée de nombreux champs (server, date,...), la longueur du contenu (13), et le contenu sous forme de texte.

HTTP/1.0 200 OK
Server: SimpleHTTP/0.6 Python/2.7.15+
Date: Thu, 26 Dec 2019 17:06:12 GMT
Content-type: text/html; charset=UTF-8
Content-Length: 13

Hello world

Les headers de la réponse sont des mines d'information sur le serveur, sa version...
Ici un serveur Apache en version 0.8.4 qui éxécute des scripts avec un interpréteur php en version 7.3.13.

HTTP/1.1 200 OK
Server: Apache/0.8.4
Content-Type: text/html; charset=UTF-8
Transfer-Encoding: chunked
Connection: keep-alive
X-Powered-By: PHP/7.3.13
$ printf 'GET / HTTP/1.1\r\nHost: localhost 8001\r\n\r\n' | nc localhost 8001

Code de réponse HTTP

    1xx informational response – the request was received, continuing process
    2xx successful – the request was successfully received, understood, and accepted
        200 OK
    3xx redirection – further action needs to be taken in order to complete the request
        301 Moved Permanently => Redirection
        304 Not Modified
    4xx client error – the request contains bad syntax or cannot be fulfilled
        400 Bad request
        401 Unauthorized
        403 Forbidden
        404 Not found
    5xx server error – the server failed to fulfil an apparently valid request
        500 Internal Server Error
        502 Bad Gateway - The server was acting as a gateway or proxy and received an invalid response from the upstream server
        503 Service Unavailable - The server cannot handle the request (because it is overloaded or down for maintenance)
        504 Gateway Timeout - The server was acting as a gateway or proxy and did not receive a timely response from the upstream server.
    https://en.wikipedia.org/wiki/List_of_HTTP_status_codes

Télécharger un fichier :

$ wget http://localhost:8001/

Afficher le contenu de la réponse :

$ curl http://localhost:8001/

Afficher les headers, la requête et le contenu de la réponse :

$ curl -v http://localhost:8001/

Les headers HTTP sont standardisés et sont riches en information.

  • Host: Précise le site web destinataire de la requète.
  • Referer: Adresse de la page web qui a généré la requète.
  • User-Agent: Navigateur utilisé pour se connecter.

Il est possible d'ajouter des headers personnels, tel 'X-MyHeader: value'

GET / HTTP/1.1
Host: localhost:8001
User-Agent: curl/7.58.0
Accept: */*
X-MyHeader: value

Pour ajouter un header avec curl : -H 'header: valeur'

$ curl -H 'X-MyHeader: value' http://localhost:8001

Le header des requêtes contient un champ User-Agent.
Il est utilisé par les navigateurs pour s'identifier et donner des information sur leur version.
Le serveur peut adapter la page à un vieux navigateur Internet Explorer ou un Firefox dernier cris.

Curl v7.68.0 utilise 'curl/7.68.0' comme User-Agent. Il est possible de définir la valeur du User-Agent avec l'option -A.

curl -A 'MyAgent' http://localhost:8001

L'URI permet de précider une ressource, et d'ajouter des paramètres.
Le premier paramètre est identifié par un ?, les suivants par un &.
Si les paramètres contiennent des ? ou des &, ils sont encodés sous la forme %3F et %26. On parle de Percent (%) encoding.
https://fr.wikipedia.org/wiki/Percent-encoding

Exemple:

$ curl 'http://localhost:8001/register.php?name=jean&lastname=bon&age=42&admin=true'

Le shell unix utilisant le & pour lancer des taches en arrière plan, il est impératif de mettre l'URL entre '.

HTTP dispose d'une fonctionnalité d'authentification basique. Il est possible ajouter un champ contenant un identifiant et un mot de passe en clair.
Ces informations sont mise sous la forme login:password, puis encodées en base64, et ajoutées dans l'entête de la requête:
Authorization: Basic bG9naW46cGFzc3dvcmQ=

Exemple:

GET /hello.txt HTTP/1.1
Host: localhost:8001
Authorization: Basic bG9naW46cGFzc3dvcmQ=
User-Agent: curl/7.58.0
Accept: */*

Pour envoyer une requête avec des informations d'authentification avec curl:

$ curl -u login:password http://localhost:8001/hello.txt

Pour encoder un login:password dans le terminal

$ printf 'login:password' | base64
bG9naW46cGFzc3dvcmQ=

Pour décoder du base64 dans le terminal

$ printf 'bG9naW46cGFzc3dvcmQ=' | base64 -d
login:password

Pour tester une liste de mots de passe:

for i in `cat rockyou.txt`; do printf \n$i:; curl  -u admin:$i http://12.10.1.11/training-http-auth-simple.php; done

Quand une page web comporte un formulaire, elle peut envoyer le contenu des champs avec la méthode GET dans les paramètres de l'URL, ou avec la méthode POST dans le corps de la requète.

Les valeurs en paramètres du GET apparaissent dans les logs, et sont limités en longueur.
Les valeurs en paramètres du POST n'apparaissent pas dans les logs, et ne sont pas limités en longueur. Il est ainsi possible d'uploader de gros fichiers.
Ces paramètres sont encodés avec le format 'Percent encoding'.
Exemple:

POST /login.php HTTP/1.1
Host: 10.10.1.11
Content-Type: application/x-www-form-urlencoded
Content-Length: 24

login=James&password=007

Poster un formulaire avec curl:

$ curl -X POST -F 'username=admin' -F 'password=megapassword'  http://localhost:8001/

Les formulaires sont des objets HTML de base, définis par les balises <form> et </form>
<input name='xxx'>: Nom des champs de type texte.
<form action='xxx': URL a laquelle sera envoyé le formulaire. Si le champ est vide, le formulaire est envoyé à la URL.
Exemple:

<form action="/action_page.php"> 
  First name: <input type="text" name="firstname" value="Mickey">
  Last name:  <input type="text" name="lastname" value="Mouse">
  <input type="submit" value="Submit"> 
</form> 

Poster un formulaire avec curl:

$ curl -X POST -F 'firstname=Mickey' -F 'lastname=Mouse'  http://12.10.1.11/action_page.php

Les pages web comportant des formulaires utilisent généralement la commande POST, mais elles peuvent aussi utiliser une commande GET.
Dans ce cas, la valeur des paramètres sont directement passés comme argument dans la requète.
Ne pas oublier de mettre l'url entre 'cotes'
Exemple:

$ curl 'http://localhost:8001/register.php?name=jean&lastname=bon&age=42&admin=true'

Dans les formulaires élaborés, les données sont validées en Java Script avant d'être envoyées, au bon format au serveur.
JavaScript utilise nativement le format JSON pour envoyer des structures de données structurées.
Exemple: {key1:value1, key2:value2}.
Dans ce cas, l'entête Content-Type précise le type de données: Content-Type: application/json

Exemple:

POST / HTTP/1.1
Host: localhost:8001
User-Agent: curl/7.58.0
Accept: */*
Content-Type: application/json
Content-Length: 34

{"key1":"value1", "key2":"value2"}

Curl :

$ curl --header "Content-Type: application/json" -X POST --data  '{"key1":"value1", "key2":"value2"}' http://10.10.1.11/

Les formulaires sont généralement utilisés pour s'enregister, se connecter ou d'uploader des fichiers.
Des contrôles sur les fichiers uploadés peuvent être fait en javascript sur le client, ou sur le serveur.
On vérifie souvent la taille, le nom, l'extension du fichier, et parfois son header.
Un chapitre entier du guide est dédié à l'upload de nos shells.

Un champ de type Fichier est caractérisé par le code HTML

<input type=file name=fileToUpload>:

Commande curl

curl -X POST -F 'fileToUpload=@./picture.jpg' http://10.10.1.11/upload

Les cookies servent à stocker des valeurs sur le navigateur qui seront reutilisées entre deux sessions.
Ils peuvent contenir des choix de langue, couleurs, et parfois d'authentification...

Lire les cookies envoyés par le serveur et les stocker dans un cookie jar.

$ curl  -c cookies.txt http://10.10.1.11/cookies.php

Envoyer un cookie sauvegardé, et sauver la nouvelle valeur

$ curl -b cookies.txt -c cookies.txt http://10.10.1.11/cookies.php

Envoyer un cookie manuellement

$ curl -b 'code=1447' http://10.10.1.11/cookies.php