Поиск открытых баз данных с помощью поисковиков

поиск незащищенных баз данных

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

Еще по теме: Как проверить сайт на уязвимости

В статье я покажу, как автоматизировать поиск незащищенных баз данных с помощью поисковиков.

Поиск открытых баз данных с помощью поисковиков

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

Вся информация предоставлена исключительно в ознакомительных целях. Ни автор, ни редакция сайта spy-soft.net не несут ответственности за любой возможный вред, причиненный материалами данной статьи.

Прог­рамми­ровать, прав­да, не придется, потому что некоторые такие как Францеска Эрера — это уже сде­лали до нас. Возь­мем, к при­меру интересный скрипт, который сам под­бира­ет 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 доменов. Работа­ет очень быс­тро.

По­иск доменов прог­раммой sublist3r
По­иск доменов прог­раммой sublist3r

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

По­иск под­доменов прог­раммой subbrute
По­иск под­доменов прог­раммой subbrute

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

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

Как защитить базы данных

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

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

Да­же во вре­мя раз­работ­ки (на тес­те и на stage) не сто­ит откры­вать дос­туп ко всем дан­ным в Firebase неав­торизо­ван­ным поль­зовате­лям, но есть воз­можность открыть их при авто­риза­ции:

service cloud.firestore {
  match /databases/{database}/documents {
    match /{document=**} {
      allow read, write: if request.auth != null;
    }
  }
}

Это пра­вило необ­ходимо, ког­да нес­коль­ким поль­зовате­лям нуж­но работать с одним кон­тентом.

Сле­дующее пра­вило дает дос­туп к дан­ным толь­ко вла­дель­цам этих дан­ных. Осталь­ные поль­зовате­ли не смо­гут их видеть или обра­баты­вать:

service cloud.firestore {
  match /databases/{database}/documents {
    // Allow only authenticated content owners access
    match /some_collection/{userId}/{documents=**} {
      allow read, write: if request.auth != null && request.auth.uid == userId
    }
  }
}

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

service cloud.firestore {
  match /databases/{database}/documents {
    // For attribute-based access control, Check a boolean `admin` attribute
    allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.admin == true;
    allow read: true;
    // Alterntatively, for role-based access, assign specific roles to users
    match /some_collection/{document} {
      allow read: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Reader"
      allow write: if get(/databases/$(database)/documents/users/$(request.auth.uid)).data.role == "Writer"
    }
  }
}

Бо­лее под­робные све­дения о бе­зопас­ности аутен­тифика­ции и кон­тро­ле дос­тупа мож­но най­ти в докумен­тации Firebase.

Заключение

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

В докумен­тации по безопас­ности Firebase при­веде­ны и сами пра­вила, и раз­ные спо­собы защитить дан­ные. Не сто­ит ими пре­неб­регать, перек­ладывая ответс­твен­ность на какие‑нибудь гей­ты или прок­си‑сер­веры. Адрес базы может быть обна­ружен.

Еще по теме: Что такое Google Dorks?

ВКонтакте
OK
Telegram
WhatsApp
Viber

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *