Sari la conținut

Vulnerabilitate Instagram: postări private expuse fără autentificare

Platformă afectată: Instagram

Zebrabyte

Expunerea postărilor private pe Instagram prin polaris_timeline_connection

Analiză tehnică completă a unei vulnerabilități server-side negate oficial

Platformă afectată: Instagram

Deținut de: Meta

Perioada descoperirii: Octombrie 2025

Durata disclosure-ului: 102 zile

Tip vulnerabilitate: Server-side authorization bypass

Impact: Acces neautorizat la conținut privat (imagini + descrieri)

Status final: Patch aplicat în tăcere, caz închis ca Not Applicable

1. Introducere

Acest articol documentează o vulnerabilitate reală, exploatabilă și demonstrată din infrastructura Instagram (mobile web), care a permis acces complet neautentificat la postări aparținând unor conturi setate ca private.

Deși problema a fost corectată în mod demonstrabil la scurt timp după raportare, Meta a refuzat recunoașterea existenței ei, susținând că nu a fost niciodată reproductibilă.

Articolul de față nu este o opinie, ci o reconstrucție tehnică și cronologică, bazată pe:

  • dovezi video cu hash criptografic,
  • scripturi PoC,
  • loguri de rețea,
  • commit-uri Git timestamp-ate,
  • corespondență oficială Meta.

2. Contextul descoperirii

Vulnerabilitatea a fost descoperită accidental, în timpul dezvoltării unui workflow automation tool pentru cereri HTTP.

Analizând răspunsuri HTML returnate de Instagram mobile web, am observat un comportament neobișnuit:

  • conținut media era returnat în HTML,
  • deși cererea era complet neautentificată,
  • iar profilul țintă era setat explicit ca private.

Inițial, ipotezele luate în calcul au fost:

  • cache CDN defectuos,
  • bleed de sesiune,
  • eroare locală de testare.

Toate au fost eliminate prin testare repetată și controlată.

3. Confirmarea vulnerabilității

Pentru a exclude orice posibilitate de eroare, testarea a fost repetată pe propriul meu cont privat:

  1. Contul a fost setat private
  2. A fost publicată o postare nouă
  3. S-a așteptat propagarea normală
  4. S-a trimis o cerere GET fără login, cookie, token sau sesiune

Rezultatul:

  • postarea privată era prezentă în răspuns,
  • imaginea se putea accesa direct din CDN,
  • descrierea (caption) era inclusă.

Acest pas este esențial: nu exista niciun vector de atac „extern”.

Serverul Instagram genera date private pentru utilizatori neautentificați.

4. Descriere tehnică detaliată

4.1 Endpoint-ul

Cererea:

  • nu include cookie-uri
  • nu include token-uri
  • nu include headere de autentificare

Singura condiție era utilizarea unor headere specifice mobile (User-Agent / Accept).

4.2 Răspunsul serverului

Serverul returna HTML care conținea JSON embeduit.

În structura acestui JSON apărea obiectul:

Cu următoarea structură relevantă:

4.3 De ce este critic

  • edges[] nu ar trebui populat pentru conturi private
  • popularea lui implică verificări de autorizare server-side
  • CDN-ul servește conținut valid, pentru că backend-ul l-a expus

Nu este un bug de frontend.

Nu este un bug de cache.

Este o eroare logică de autorizare în backend.

5. Proof of Concept (PoC)

A fost creat un script Python care:

  1. Trimite cererea neautentificată
  2. Extrage JSON-ul embeduit
  3. Parcurge polaris_timeline_connection.edges
  4. Obține display_url
  5. Accesează direct conținutul privat din CDN

Scriptul a fost:

  • rulat local
  • filmat
  • folosit pe conturi terțe doar cu acord explicit

6. Testare controlată

Testarea oficială a fost limitată strict la conturi cu permisiune.

Rezultate:

  • Total conturi testate: 7
  • Conturi vulnerabile: 2 (~28%)
  • Conturi neafectate: 5

Observații:

  • vulnerabilitatea era condițională
  • nu afecta toate conturile private
  • primele indicii sugerau o corelație cu vechimea contului
  • cauza exactă nu a fost determinată

Această natură condițională crește severitatea problemei, deoarece:

  • este greu de detectat,
  • este greu de confirmat ca rezolvată,
  • este ușor de negat.

7. Disclosure către Meta – cronologie completă

12 octombrie 2025

  • Raport inițial trimis către Meta Bug Bounty
  • Includea:
    • explicație tehnică
    • script PoC
    • demonstrație video

Răspuns Meta:

Caz închis ca „CDN caching issue”.

13–15 octombrie 2025

  • Raport nou, reformulat explicit ca server-side authorization bypass
  • Meta începe dialogul

Acțiuni:

  • Meta solicită test pe contul lor → nu vulnerabil
  • Meta solicită cont vulnerabil → furnizat cu acord
  • Vulnerabilitatea este demonstrată din nou
  • Sunt trimise:
    • video-uri
    • script
    • explicație a stării „trigger”

16 octombrie 2025

  • Vulnerabilitatea nu mai funcționează
  • Toate conturile anterior afectate returnează edges: []

Nu există:

  • notificare
  • confirmare
  • explicație

27 octombrie 2025

Meta răspunde oficial:

„We are unable to reproduce this issue.”

Cazul este închis ca Not Applicable.

8. Starea „trigger” – indiciu critic

În timpul exploatării, un indicator consistent era:

  • cont privat afișat cu 0 followers / 0 following
  • story ring prezent
  • timeline populat cu date reale

Această inconsecvență indică:

  • un state intern corupt
  • un flux de execuție unde verificările de autorizare sunt sărite

9. Ce NU a făcut Meta

  1. Nu a cerut loguri de debug Au fost oferite explicit (X-FB-Debug headers). Ignorate.
  2. Nu a analizat natura condițională Lista comparativă de conturi afectate a fost ignorată.
  3. Nu există Root Cause Analysis „Infrastructure changes” ≠ analiză de securitate.

Fără RCA, nu există garanția că:

  • problema nu reapare,
  • aceeași clasă de bug nu există în altă parte.

10. Dovezi și integritate

Au fost arhivate și versionate:

  • script PoC
  • capturi before / after
  • 4 video-uri cu timestamp + SHA256
  • arhivă completă de comunicare Meta
  • loguri de rețea
  • istoric Git public

Dovezile nu pot fi fabricate retroactiv.

11. Impact real

Instagram deservește peste 1 miliard de utilizatori.

Un bug care:

  • afectează doar unele conturi private,
  • nu lasă urme vizibile,
  • nu notifică utilizatorii,

este extrem de periculos.

Utilizatorii se bazează pe faptul că private înseamnă private.

12. De ce acest disclosure este public

  • standardul industriei: 90 zile
  • Meta a avut 102 zile
  • exploit-ul nu mai funcționează
  • nu a existat recunoaștere sau transparență

Scopul acestui articol:

  • documentare istorică
  • verificare independentă
  • responsabilitate publică

13. Concluzie

Întrebarea reală nu este:

„Mai funcționează azi?”

Ci:

Au fost expuse date private utilizatorilor neautorizați?

Pe baza dovezilor tehnice, cronologice și criptografice:

da, au fost.

Technical Details

For those who want to dig deeper:

Before

After