Hacking
March 4, 2022

Ищем открытые базы данных сайтов

Рассказываю о том, как найти массу всего интересного в открытом доступе.

Всем салют, дорогие друзья!

Об­лачная база дан­ных — шту­ка удоб­ная: счи­тай, вся работа по деп­лою и нас­трой­ке сер­вера за тебя уже сде­лана, оста­лось толь­ко поль­зовать­ся! Адми­нов это рас­слаб­ляет нас­толь­ко, что такие базы час­то оста­ются незащи­щен­ными и ищут­ся с помощью поис­ковиков. Один нюанс — этим поис­ковиком не может быть Google!


Введение

Firebase — это облачная плат­форма, которую раз­работа­ла ком­пания Envolve в 2011 году. Изна­чаль­но это была база дан­ных для при­ложе­ний‑чатов, но поз­же ее полюби­ли раз­работ­чики мно­гополь­зователь­ских онлай­новых игр. Это под­вигло осно­вате­лей раз­делить Firebase на две час­ти: модуль чата и модуль игро­вого фрей­мвор­ка.

Два года спус­тя, в 2014 году, Google при­обре­ла Firebase и про­дол­жила раз­вивать. Прог­рам­мные интерфей­сы для этой базы дан­ных есть для мно­жес­тва плат­форм и язы­ков прог­рамми­рова­ния.

С тех­ничес­кой точ­ки зре­ния Firebase — кру­тая и удоб­ная шту­ка. Кажет­ся, что ничего док­ручивать и допили­вать здесь не нуж­но. Но безопас­ная нас­трой­ка облачной базе таки нуж­на, и мно­гие вла­дель­цы об этом забыва­ют, черес­чур рас­сла­бив­шись. Нас­толь­ко, что забыва­ют о прос­тей­шей вещи — аутен­тифика­ции.


Ищем открытые базы данных

По­луча­ется, что в интерне­те мас­са не зак­рытых паролем баз дан­ных, а это лег­кая добыча для нас, хакеров. Толь­ко вот взять и нагуг­лить их не получит­ся, потому что в Google решили, что эту проб­лему мож­но решить, прос­то исклю­чив эти базы из поис­ковой выдачи. Лов­ко! Но край­не ненадеж­но.

Нич­то не меша­ет нам вос­поль­зовать­ся дру­гим поис­ковиком — нап­ример, Bing или DuckDuckGo. Они выда­ют уже нам­ного боль­ше полез­ной информа­ции.

Что мож­но сде­лать даль­ше, пос­ле того как най­дены домены с уяз­вимыми базами? Откры­ваем любую ссыл­ку — нап­ример, https://hacker-news.firebaseio.com/v0/topstories.json. Информа­ция о ней бес­полез­на, но если убрать из ссыл­ки наз­вание таб­лицы topstories и оста­вить толь­ко .json, то мож­но про­верить, защище­на база или нет. В этом слу­чае резуль­тат выг­лядит вот так:

{
  "error" : "Permission denied"
}

Все вер­но, лич­но я бы знат­но уди­вил­ся, если бы вла­дель­цы это­го сай­та допус­тили нас­толь­ко вопи­ющую оплошность. Но некото­рые ее таки допус­кают. Минут десять перебо­ра ссы­лок, и поиск увен­чает­ся успе­хом.

Я нашел что‑то более инте­рес­ное — учет­ки с хешами паролей. Выб­рать их из фай­ла нес­ложно прос­тым скрип­том на Python или ути­литой jq.

При помощи HashID опре­деля­ем тип хешей (это был MD5) и загоня­ем в hashcat. Если нет дос­таточ­но мощ­ного железа, мож­но вос­поль­зовать­ся онлай­новым сер­висом — тул­за FindMyHash авто­мати­чес­ки их под­бира­ет.

Все эти ути­литы пре­дус­танов­лены в Kali Linux.

Ждем десять минут, и перед нами логины и пароли в откры­том виде.


Автоматизируем

Си­деть, менять поис­ковики и переби­рать все URL вруч­ную очень нуд­но. Слиш­ком час­то видишь «error : Permission denied». Зна­чит, пора авто­мати­зиро­вать! Прог­рамми­ровать, прав­да, не пот­ребу­ется, потому что это уже сде­лали до нас. Возь­мем, к при­меру, скрипт за авторс­твом Фран­цеска Эрре­ры.

Скрипт сам под­бира­ет URL и ищет уяз­вимые базы дан­ных.

Ка­чаем его и уста­нав­лива­ем зависи­мос­ти:

git clone https://github.com/Turr0n/firebase.git
cd firebase
pip install -r requirements.txt

И запус­каем:

python3 firebase.py -p 4 -c 150 –dnsdumpster

Клю­чи:

  • p — ука­зыва­ет количес­тво потоков (по умол­чанию 1, мак­симум 4);
  • dnsdumpster — генери­рует URL самос­тоятель­но;
  • с — какое количес­тво доменов генери­ровать.

Да, скрипт уме­ет генери­ровать ссыл­ки самос­тоятель­но. Точ­нее, дела­ет это не сам, а обра­щает­ся за помощью к ути­лите DNSdumpster.

По резуль­тату вид­но, что из най­ден­ных баз:

  • 37 урлов «битые» или боль­ше не сущес­тву­ют;
  • 171 база име­ет аутен­тифика­цию при обра­щении к дан­ным и защище­на;
  • од­на база с подоз­рени­ем на уяз­вимость;
  • 25 баз не защище­ны или уяз­вимы.

Мож­но скор­мить скрип­ту и свой спи­сок. В нем дол­жны быть толь­ко под­домены треть­его уров­ня. Нап­ример, ты дела­ешь вот такой вход­ной спи­сок:

xxx
yyy
zzz

Тог­да скрипт про­верит вот эти URL:

https://xxx.firebaseio.com
https://yyy.firebaseio.com
https://zzz.firebaseio.com

В поисках поддоменов

Что­бы получить наибо­лее эффектив­ный спи­сок, мож­но вос­поль­зовать­ся скрип­том sublist3r, который исполь­зует раз­ные тех­ники поис­ка и OSINT, что­бы подоб­рать наибо­лее прав­доподоб­ные вари­анты.

За­пус­каем:

python3 sublist3r.py -d firebaseio.com

И на выходе получа­ем око­ло 650 доменов. Работа­ет очень быс­тро.

Еще одна ути­лита для генера­ции доменов — subbrute. Она выдала мне в рай­оне 100 под­доменов, но работа­ла 30–40 минут.

Censys-subdomain-finder, на который я воз­лагал боль­шие надеж­ды, выдал все­го семь доменов. К сло­ву, и сам сер­вис выдал нем­ного — 25 урлов.

Все перечис­ленные ути­литы не вхо­дят в сос­тав дис­три­бути­ва Kali Linux, их приш­лось качать отдель­но.

Из онлай­новых сер­висов мож­но вос­поль­зовать­ся nmmapper, DNSdumpster, Pentest-Tools.

Ес­ли все еще мало, мож­но задей­ство­вать зна­ния о том, что нас­трой­ки интегра­ции про­исхо­дят в фай­ле google-services.json, и поис­кать в гите зап­росом site:github.com google-services.json. Этот вари­ант идет враз­рез со сло­вом «авто­мати­зация», зато мож­но докопать­ся до уни­каль­ных баз.


Ковыряем и дописываем скрипт

Те­перь мы воору­жены доб­ротным набором урлов и зна­ем, что какие‑то из них могут быть уяз­вимы. Даже можем запус­тить скрипт и про­верить количес­тво невер­но нас­тро­енных баз из нашего спис­ка. Но цель в таких слу­чаях — не соб­рать ста­тис­тику, а получить уяз­вимые цели. Поэто­му откро­ем код скрип­та и слег­ка поп­равим.

Пос­мотри вот на этот кусок кода:

urls = set()
with open(args_.list, 'r') as f:
[urls.add('https://{}.firebaseio.com/.json'.format(line.rstrip())) for line in f]

Из него понят­но, как фор­миру­ется пол­ный адрес. А в кон­це фор­миру­ется отчет:

print('404 DBs: {}'.format(l['-2']))
print('Secure DBs: {}'.format(l['-1']))
print('Possible vulnerable DBs: {}'.format(l['0']))
print('Vulnerable DBs: {}'.format(l['1']))

Ку­сок кода с про­вер­кой я при­водить не буду. Там нет ничего любопыт­ного, мне нуж­но было най­ти само прис­воение. И вот оно:

with open(args_.fn, 'w') as f:
json.dump(loot, f)
l = {'1':0, '0':0, '-1':0, '-2':0}
for result in loot:
l[str(result['status'])] += 1

Вот в этом мес­те я соз­даю свой мас­сив по ста­тусу 1. Так как я еще не понимаю, чем его запол­нять, записы­ваю все под­ряд. Получи­лось при­мер­но сле­дующее:

l = {'1':0, '0':0, '-1':0, '-2':0}
Vulnerable = []
for result in loot:
l[str(result['status'])] += 1
if str(result['status']) == '1':
Vulnerable.append(result)

И в кон­це добав­ляю вывод резуль­тата в кон­соль:

print('404 DBs: {}'.format(l['-2']))
print('Secure DBs: {}'.format(l['-1']))
print('Possible vulnerable DBs: {}'.format(l['0']))
print('Vulnerable DBs: {}'.format(l['1']))
print(Vulnerable)

Пос­ле запус­ка вижу такую кар­тину.

Мне высыпа­лось все, что хра­нилось в базах. Зато теперь я знаю, что записы­вать в Vulnerable. Пра­вим код, как надо:

l = {'1':0, '0':0, '-1':0, '-2':0}
Vulnerable = []
for result in loot:
l[str(result['status'])] += 1
if str(result['status']) == '1':
Vulnerable.append(result['url'])
...
print('404 DBs: {}'.format(l['-2']))
print('Secure DBs: {}'.format(l['-1']))
print('Possible vulnerable DBs: {}'.format(l['0']))
print('Vulnerable DBs: {}'.format(l['1']))
print(Vulnerable)

На этот раз при запус­ке видим то, что было нуж­но, — спи­сок уяз­вимых баз.

Осо­бен­но меня заин­тересо­вала вот эта ссыл­ка: https://covid-19-tracker-e76ca.firebaseio.com/.json. В Малай­зии так спе­шили отсле­живать переме­щения боль­ных ковидом, что не пос­тавили пароль на базу дан­ных с их коор­дината­ми...

Итак, мы рас­смот­рели, как про­исхо­дит утеч­ка дан­ных, разоб­рались с поис­ком уяз­вимых URL и научи­лись авто­мати­зиро­вать про­цесс.

На сегодня это все. Надеюсь, что данная информация будет вам полезна!


👉Да, хочу!ᅠ