Blog ·
De ce un scaner de vulnerabilități trebuie să trimită zero octeți
Linia dintre o verificare și un atac o dau octeții puși pe fir. Cum transformați promisiunea într-un număr pe care testele îl pot pica, cu măsurătorile.
De Provibr
Dacă administrați infrastructură pentru alți oameni, ajungeți la un moment dat să vreți să știți dacă portul 3306 de pe una dintre mașinile clienților dumneavoastră răspunde întregului internet. Este o întrebare rezonabilă, clientul ar vrea răspunsul, iar în clipa în care vă duceți să căutați ați devenit o parte care trimite trafic nesolicitat către o mașină aflată sub contractul altcuiva.
Ce separă asta de o intruziune nu este intenția dumneavoastră și nu este o bifă din condițiile dumneavoastră de utilizare. Este ce a plecat de fapt din soclu. Tot restul este o poveste despre ce a plecat din soclu.
Am construit recent o verificare de expunere în agentul nostru, cu o regulă care a început ca o propoziție într-un document de proiectare: nu trimiteți nicio interogare care modifică ceva, nicio încercare de autentificare, nicio dată de acces implicită, nicio sarcină utilă de exploatare, nicio recoltare largă de bannere. Iată cum a devenit acea propoziție ceva pe care un test îl poate pica și cât costă în octeți sondele rezultate.
O promisiune într-un comentariu este o promisiune cu termen de valabilitate
Problema propoziției de mai sus nu este că e greu de urmat. Este că e ușor de urmat vreo șase luni.
Cineva adaugă un EHLO la sonda SMTP, ca să poată detecta dacă se oferă STARTTLS, ceea ce este o informație cu adevărat utilă. Testele existente trec în continuare, pentru că ele afirmă lucruri despre ce a găsit sonda, nu despre ce a spus ea. Din acea zi programul trimite comenzi de protocol către mașinile clienților, iar documentul de proiectare încă spune că nu o face. Nimic nu a devenit roșu. Nimic nu va deveni vreodată.
Așa că l-am făcut un număr acolo unde un număr este cu putință. Fiecare soclu pe care îl deschide verificarea este învelit într-un flux care numără octeții scriși, iar totalul călătorește înapoi împreună cu rezultatul. Patru dintre cele șase feluri de sondă au în teste o cifră exactă afirmată: zero pentru cele două care nu trimit nimic, treizeci și doi pentru SSH, opt pentru PostgreSQL. Celelalte două nu pot, pentru că un client hello și un negotiate SMB variază în lungime în funcție de ce se oferă înăuntru; limita lor este în schimb o formă: un singur mesaj și nimic după el. Adăugarea unui EHLO la o sondă afirmată la zero este acum un test roșu cu un număr în el.
Două detalii ale acelui contor s-au dovedit importante.
El numără scrierile, nu citirile. Ce oferă cealaltă parte de bunăvoie nu este ceva provocat de noi; ce trimitem noi, da. Și este un contor comun, nu un câmp pe propriul nostru tip de flux, pentru că sonda TLS își predă soclul unei biblioteci care apoi scrie peste el propriile înregistrări de handshake. Fără un contor comun, singura sondă care folosește codul altcuiva ar fi exact sonda rămasă nenumărată, adică tocmai locul în care un buget de octeți este cel mai greu de urmărit.
Cât costă fiecare sondă
| Sondă | Ce trimitem | Ce se citește |
|---|---|---|
| Doar deschidere | nimic, afirmat la 0 octeți | nimic |
| Banner: FTP, Telnet, SMTP, MySQL | nimic, afirmat la 0 octeți | un salut mărginit |
| SSH | o linie de identificare, afirmată la 32 de octeți | linia de identificare a serverului, apoi lista lui de algoritmi dacă o oferă |
| TLS | un client hello, cu lungime variabilă | server hello și certificat |
| SMB | un negotiate, cu lungime variabilă | răspunsul la negotiate |
| PostgreSQL | cererea SSL, afirmată la 8 octeți | un octet |
Nimic nu urmează după deschidere. Niciun al doilea mesaj, niciun keepalive, nicio încheiere a unui handshake. Odată ce cealaltă parte a vorbit, soclul se închide.
SSH: treizeci și doi de octeți, și de ce nu poate merge mai departe
Protocolul SSH cere ca ambele capete să trimită întâi o linie de identificare. A noastră este o linie de treizeci și doi de octeți și este singurul lucru pe care îl scrie sonda. După aceea citește: linia de identificare a serverului și apoi, dacă serverul trimite unul nesolicitat, mesajul lui de schimb de chei, cu algoritmii oferiți în el.
Partea importantă este ce lipsește. Sonda nu trimite niciodată propriul ei mesaj de schimb de chei. Aceasta nu este o politică, este o margine structurală: fără el schimbul de chei nu poate continua, nu se stabilește niciodată o sesiune și, prin urmare, nu există nicio stare a protocolului în care s-ar putea trimite o cerere de autentificare. „Nicio încercare de autentificare” încetează să mai fie o regulă pe care trebuie să și-o amintească cineva.
Linia de identificare numește produsul, în loc să imite un client. Un administrator care își citește jurnalul de autentificare trebuie să poată vedea cine s-a conectat. Un șir neutru sau falsificat ar face ca o verificare legitimă să pară recunoaștere ostilă, ceea ce este un schimb prost pentru cele două secunde de obscuritate pe care le cumpără.
Există un cost și merită numit, pentru că apare ca o problemă de calitate a datelor, nu ca o eroare. Unele servere așteaptă mesajul de schimb de chei al clientului înainte să îl trimită pe al lor, iar protocolul permite oricare ordine. Când se întâmplă asta, sonda primește un șir de versiune și nicio listă de algoritmi. Acoperirea pentru acel port este atunci parțială și trebuie consemnată ca parțială. Dacă ar fi consemnată drept completă, cu o listă goală, motorul de reguli ar conchide că nu se oferă niciun algoritm învechit, ceea ce este cea mai proastă ieșire posibilă: un „sigur” încrezător derivat dintr-o absență de date.
Protocoalele care vorbesc primele și tentația de a răspunde
FTP, Telnet, SMTP și MySQL vă salută toate. Sonda pentru acestea nu trimite absolut nimic: se conectează, citește un număr mărginit de octeți, închide. Aceea nu este o recoltare de bannere, pentru că nu există niciun fel de a deschide un asemenea port fără a primi salutul, iar nu s-a cerut nimic.
Tentația EHLO este reală și am decis împotriva ei. Este cu adevărat valoros să știi dacă un server de mail oferă STARTTLS. Asta cere însă trimiterea unei comenzi de protocol, iar regula era despre faptele pe care cealaltă parte le cedează nesolicitat. Consecința este că o constatare SMTP ajunge la o severitate mai mică și la o încredere mai mică decât ar fi ajuns altfel. Acesta este prețul cinstit și trebuie să fie vizibil în constatare, nu combătut prin argumente.
PostgreSQL este cazul intermediar interesant. Opt octeți sunt întregul pachet de cerere SSL: o lungime și un număr magic, care este primul lucru pe care îl trimite orice client și care nu este o interogare, nu este o dată de acces și nu este o autentificare. Serverul răspunde cu un singur octet care spune dacă va vorbi TLS. Un octet de răspuns este de ajuns ca să deosebiți o bază de date care cere criptare de una care nu o cere, iar nu există nicio versiune a acestei verificări care să trimită mai puțin.
Un port deschis nu este o vulnerabilitate
Portul 445 care răspunde nu înseamnă că SMB1 este activat. Acelea sunt două fapte separate și au nevoie de două câmpuri separate.
Sonda noastră consemnează o stare pentru port, adică dacă este cineva acolo, și cel mult o singură probă, adică ce a spus acel cineva. Un negotiate care se întoarce fără un dialect vechi vă lasă cu un port deschis și nimic altceva, iar acela este un rezultat complet, nu unul parțial. Tentația de a contopi cele două într-o singură severitate este puternică, pentru că produce un tablou de bord mult mai palpitant.
Igiena probelor își are locul în același paragraf, pentru că un salut nu este un șir inofensiv. Bannerele FTP și SMTP poartă în practică numele de gazdă al clientului, uneori numele de gazdă al clientului lui și, ocazional, o cale pe disc. Stocarea lor brută înseamnă că tabelul dumneavoastră de constatări devine un loc în care se acumulează informații personale și structurale despre rețelele altor oameni, păstrate atâta timp cât se păstrează constatările, vizibile pentru oricine poate citi o constatare.
Așa că ce pleacă din sondă este un simbol de protocol normalizat, un fragment de versiune decupat după o regulă documentată, numărul de octeți citiți și un hash al octeților bruți. Hashul face două scanări comparabile fără ca cineva să păstreze textul. Ultima proprietate este cea care vă lipsește dacă o săriți: fără ea, „s-a schimbat asta față de luna trecută” cere tocmai lucrul pe care ați hotărât să nu îl păstrați.
Senzorul nu are opinii
Încă o separare, și este cea care face restul întreținibil.
Agentul măsoară. Nu rezolvă niciun nume de gazdă, nu ține nicio listă proprie de porturi și nu alege nicio țintă: adresa și porturile îi sunt scrise de platformă, care a verificat înainte de a le trimite că adresa este alocată în acest moment acelei organizații și acelui server. Fără ținte, agentul nu măsoară nimic.
Judecata se face pe platformă, dintr-un set de reguli care poate fi citit și versionat. Asta contează pentru că o constatare trăiește mai mult decât codul care a produs-o. Peste șase luni cineva va întreba de ce o scanare din septembrie a fost evaluată drept ridicată, iar singurul fel de a răspunde este să aveți regulile și măsurătorile ca lucruri separate, care se pot recupera individual. Dacă severitatea ar fi coaptă în senzor, răspunsul ar fi „pentru că acea versiune a agentului așa a crezut”, ceea ce nu este un răspuns.
Același raționament este motivul pentru care agentul se conectează spre exterior și nu ascultă niciodată și pentru care datele de autentificare rămân pe gazdă, în loc să călătorească spre noi. O componentă care nu face decât să raporteze ce a măsurat este o componentă a cărei rază de explozie o puteți descrie într-o propoziție.
Ce am scrie
- Transformați promisiunea într-un număr. Dacă regula dumneavoastră este despre ce trimiteți, numărați ce trimiteți și afirmați lucruri despre număr. Un comentariu nu poate pica.
- Preferați marginile structurale. Netrimiterea unui mesaj de schimb de chei înseamnă că autentificarea este inaccesibilă, ceea ce este mai tare decât o regulă care spune să nu vă autentificați.
- Lăsați o sondă să fie parțială. Datele lipsă trebuie să fie vizibile ca lipsă, pentru că alternativa este un negativ încrezător pe care nimeni nu îl poate audita.
- Țineți „deschis” și „vulnerabil” în câmpuri diferite și puneți motorul de reguli să le combine undeva unde puteți citi.
- Nu stocați bannere brute. Normalizați, faceți hash și păstrați hashul pentru comparație.
- Puneți opinia pe platformă, ca o judecată de trimestrul trecut să fie în continuare explicabilă în acest trimestru.
Ca să fie limpede în privința propriului nostru produs: acesta este un singur detector, se află în spatele unui comutator la nivel de organizație care este acum oprit și nu este ceva ce puteți cumpăra astăzi. Măsurătorile de mai sus vin din implementare și din testele ei, nu de pe o pagină de marketing.
Construit pentru Provibr, unde agentul rulează în rețeaua proprie a clientului. Partea de verificare a aceleiași proiectări, dovada că un nume de gazdă îi aparține celui care întreabă, se află în cum dovediți că dețineți un nume de gazdă.