Skip to main content
  1. Concetti/

HTTP in Detail

·6 mins
Alessio Barnini
Author
Alessio Barnini
Table of Contents

Cosa fa
#

Il protocollo HTTP definisce come client e server si scambiano richieste e risposte sul web — metodi, status code, header, cookie.


HTTP vs HTTPS
#

  HTTP  — HyperText Transfer Protocol
          Sviluppato da Tim Berners-Lee, 1989-1991
          Dati in chiaro → chiunque sulla rete può leggerli

  HTTPS — HTTP Secure
          Dati cifrati → nessuno può intercettare
          Verifica identità del server → non stai parlando con un impostore

  ┌─────────────────────────────────────────────────────────┐
  │  HTTP   porta 80   ← traffico leggibile da Wireshark   │
  │  HTTPS  porta 443  ← traffico cifrato (TLS)  └─────────────────────────────────────────────────────────┘

  Blue team: traffico HTTP su porta 80 in un log è sempre
  sospetto su sistemi moderni — potrebbe essere exfiltration
  o C2 che evita l'ispezione TLS.

Anatomia di un URL
#

  http://user:password@tryhackme.com:80/view-room?id=1#task3
   │         │              │         │     │       │    │
   │         │              │         │     │       │    └── Fragment
   │         │              │         │     │       └─────── Query String
   │         │              │         │     └─────────────── Path
   │         │              │         └───────────────────── Port
   │         │              └─────────────────────────────── Host / Domain
   │         └────────────────────────────────────────────── User:Password
   └──────────────────────────────────────────────────────── Scheme

  Scheme:       protocollo da usare (http, https, ftp)
  User:Pass:    autenticazione inline (raro, sconsigliato — password in chiaro nell'URL)
  Host:         dominio o IP del server
  Port:         80=HTTP, 443=HTTPS, qualsiasi 1-65535
  Path:         risorsa richiesta sul server
  Query String: parametri aggiuntivi (?id=1 → dammi il blog con id 1)
  Fragment:     ancora interna alla pagina (#task3 → scorri a task3)
                NON viene inviato al server, è solo lato browser

Struttura di una richiesta HTTP
#

  Richiesta minimale (funziona ma è scarna):

  GET / HTTP/1.1
  └─┘ └┘ └──────── versione protocollo
   │   └────────── path (/ = homepage)
   └────────────── metodo


  Richiesta completa:

  ┌─────────────────────────────────────────────────────┐
  │ GET / HTTP/1.1                                      │ ← riga di richiesta
  │ Host: tryhackme.com                                 │ ← quale sito voglio
  │ User-Agent: Mozilla/5.0 Firefox/87.0               │ ← chi sono
  │ Referer: https://tryhackme.com/                    │ ← da dove vengo
  │                                                     │ ← riga vuota = fine headers
  └─────────────────────────────────────────────────────┘

  La riga vuota finale è obbligatoria — dice al server
  "ho finito gli header, quello che segue è il body".
  Senza → il server aspetta per sempre.

Struttura di una risposta HTTP
#

  ┌─────────────────────────────────────────────────────┐
  │ HTTP/1.1 200 OK                                     │ ← versione + status code
  │ Server: nginx/1.15.8                                │ ← software server
  │ Date: Fri, 09 Apr 2021 13:34:03 GMT                 │ ← timestamp server
  │ Content-Type: text/html                             │ ← tipo di contenuto
  │ Content-Length: 98                                  │ ← byte del body
  │                                                     │ ← riga vuota = fine headers
  │ <html>                                              │
  │   <body>Welcome To TryHackMe.com</body>             │ ← body (contenuto)
  │ </html>                                             │
  └─────────────────────────────────────────────────────┘

  Content-Length è critico per la sicurezza:
  se il client riceve meno byte del dichiarato → dati mancanti
  se manipolato → HTTP Request Smuggling (vulnerabilità avanzata)

Metodi HTTP
#

  GET     → leggo una risorsa        "dammi la pagina /blog"
  POST    → creo una risorsa         "crea questo nuovo utente"
  PUT     → aggiorno una risorsa     "aggiorna l'email dell'utente 5"
  DELETE  → cancello una risorsa     "cancella la foto con id 3"

  ┌──────────┬────────────┬──────────────────────────────────┐
  │ Metodo   │ Body?      │ Uso tipico                       │
  ├──────────┼────────────┼──────────────────────────────────┤
  │ GET      │ no         │ leggere pagine, API read  │ POST     │ sì         │ login, form, creare risorse      │
  │ PUT      │ sì         │ aggiornare risorse esistenti     │
  │ DELETE   │ raramente  │ cancellare risorse               │
  └──────────┴────────────┴──────────────────────────────────┘

  Blue team: un DELETE o PUT inatteso nei log HTTP
  è sempre da investigare — potrebbe essere un attacco
  a un'API esposta senza autenticazione.

Status Codes
#

  1xx  Informational   → "continua, sto elaborando"   (raro)
  2xx  Success         → "tutto ok"
  3xx  Redirection     → "cerca altrove"
  4xx  Client Error    → "hai sbagliato tu"
  5xx  Server Error    → "ho sbagliato io"

Codici comuni:

CodeNomeSignificatoNote blue team
200OKTutto ok
201CreatedRisorsa creataRisposta normale a POST
301Moved PermanentlyRedirect permanenteAggiorna bookmark/SEO
302FoundRedirect temporaneoPotrebbe cambiare ancora
400Bad RequestRichiesta malformataParametro mancante o errato
401UnauthorisedNon autenticatoDevi fare login prima
403ForbiddenAutenticato ma non autorizzatoHai login ma non il permesso
404Not FoundRisorsa non esiste
405Method Not AllowedMetodo sbagliatoGET su endpoint che vuole POST
500Internal Server ErrorErrore generico serverSpesso rivela stack trace
503Service UnavailableServer sovraccarico o in manutenzione
  401 vs 403 — differenza importante:

  401 Unauthorised  → "Non so chi sei, fai login"
  403 Forbidden     → "So chi sei, ma non puoi entrare"

  Blue team: un flood di 401 nei log = brute force in corso
             un 403 su /admin = qualcuno sta cercando pannelli nascosti

Risorsa visiva: https://http.cat — ogni status code ha la foto di un gatto. Ridicolo e impossibile da dimenticare. (https://http.cat/404 → gatto che cerca qualcosa che non c'è)


Header HTTP
#

Request headers (client → server):

HeaderCosa faNota security
HostQuale sito vuoi (server può ospitare più domini)Virtual host enumeration
User-AgentBrowser e versioneFacilmente falsificabile — non fidarti per autenticazione
Content-LengthByte nel bodyManipolato → HTTP smuggling
Accept-EncodingCompressioni supportate (gzip, br)
CookieDati sessione inviati al serverSe rubato → session hijacking
RefererPagina da cui viene la richiestaFacilmente falsificabile

Response headers (server → client):

HeaderCosa faNota security
Set-CookieDice al browser di salvare un cookieDeve avere HttpOnly e Secure
Cache-ControlPer quanto tenere in cacheDati sensibili: no-store
Content-TypeTipo di dato restituitoMIME sniffing se mancante
Content-EncodingCompressione usata
ServerSoftware del server (nginx, Apache)Info disclosure — meglio oscurare
  Header di sicurezza che DOVRESTI vedere su ogni sito moderno:

  Strict-Transport-Security  → forza HTTPS
  X-Frame-Options            → blocca clickjacking
  Content-Security-Policy    → whitelist risorse caricate
  X-Content-Type-Options     → blocca MIME sniffing

  Se mancano → vulnerability nel tuo report di assessment.

Cookie e Sessioni#

HTTP è stateless — ogni richiesta è indipendente, il server non ricorda la precedente. I cookie risolvono questo problema.

  FLUSSO LOGIN CON COOKIE:

  1. GET / HTTP/1.1                         browser visita il sito
     Host: cookies.thm
     User-Agent: xxxx
     HTTP/1.1 200 OK                        server risponde con form
     Content-Type: text/html
     [HTML con form login]

  2. POST / HTTP/1.1                        utente invia credenziali
     Host: cookies.thm
     Content-Type: application/x-www-form-urlencoded
     Content-Length: 9
     [name=adam]
     HTTP/1.1 200 OK                        server imposta il cookie
     Set-Cookie: name=adam                  ← "salvati questo"
     Content-Type: text/html

  3. GET / HTTP/1.1                         richiesta successiva
     Host: cookies.thm
     Cookie: name=adam                      ← browser lo manda automaticamente
     HTTP/1.1 200 OK
     [<html>Welcome back adam</html>]       server riconosce l'utente
  Il cookie NON contiene la password in chiaro.
  Contiene un token opaco (es. session_id=a3f9b2c1d...)
  Il server fa il lookup del token nel proprio database.

  Cookie sicuro vs insicuro:

  Set-Cookie: session=abc123                          ← INSICURO
  Set-Cookie: session=abc123; HttpOnly; Secure        ← SICURO

  HttpOnly  → JavaScript non può leggere il cookie → blocca XSS
  Secure    → inviato solo su HTTPS → blocca intercettazione
  SameSite  → blocca CSRF (invio cross-site)

  Blue team: cookie senza HttpOnly = superficie di attacco XSS
             cookie senza Secure su HTTP = visibile in chiaro su Wireshark

Vedere i cookie nel browser#

  DevTools (F12) → tab Network → clicca su una richiesta
                                → tab Cookies
  
  Oppure: DevTools → tab Application → Storage → Cookies

Scenario Reale
#

Un analista SOC vede nei log del WAF un picco di richieste:

  192.168.1.45  POST /login HTTP/1.1  401  --
  192.168.1.45  POST /login HTTP/1.1  401  --
  192.168.1.45  POST /login HTTP/1.1  401  --
  ... (500 volte in 2 minuti)
  192.168.1.45  POST /login HTTP/1.1  200  --  ← login riuscito
  192.168.1.45  GET  /admin  HTTP/1.1  200  --  ← accesso admin

Sequenza: flood di 401 → un 200 → accesso a risorsa privilegiata. Questo è credential stuffing / brute force riuscito. Il cookie di sessione emesso dopo il 200 è ora in mano all'attaccante.

Collegato a
#

  • network — hub
  • tcp-udp — HTTP gira su TCP
  • http-wireshark — come appare HTTP in Wireshark (TCP segmentation, MSS)
  • ssl-tls — HTTPS = HTTP + TLS
  • ctf — hub

Related