Введение:
Думаю многие сталкивались с проблемой, когда нужно было сделать базовый анализ какого либо вебсайта, но ПК/Ноутбук рядом не находились, но был смартфон.
В таких случаях есть несколько решений, например кто-то имеет SSH доступ к основной машине, кто-то VNC. Конечно, это даст вам весь функционал (почти) и должно решить проблему, но когда в руках смартфон, то только мазохисты будут возражать заявлению о том, что печатать и управлять курсором с телефона совсем неудобно.
Главной проблемой остается управление, нужно что-то удобное, почему бы нам не взять телеграм ботов? Они ограничены в функционале, но гораздо более удобные, в них есть список комманд на которые достаточно нажать, а не печатать полностью, да и сам интерфейс более юзер-френдли.
В качестве библиотеки для бота я возьму telebot, т.к считаю ее самой простой и функциональной.
Мы реализуем поддержку:
1. Подготовка почвы.
2. Создание модулей и подключение модулей.
2.1 Censys
2.2 Scaner
2.3 WAF
2.4 SearchSploit
3. Тесты
Подготовка почвы:
Перед работой нам понадобится установить telebot, прописываем:
Далее, request и bs4 для работы с Censys и Exploit-DB.
Мы также будем использовать wafw00f для создания детекта WAF.
В телеграме начнем беседу с @BotFather, создадим нового бота с помощью команды /newbot, можно ввести произвольные парметры, после завершения мы получим так называемый токен, он нам пригодится в дальнейшем. Создадим Auxiliator.py, это будет основной файл где и будет сам бот. Импортируем нужный нам telebot:
Теперь, нам нужен токен бота, это уникальный адрес вашего бота, вы должны были получить его при создании:
Используя команды, мы чаще всего будем так-же вводить цель, это будет аргументом и нам его нужно извлечь, напишем функцию:
Теперь, определимся с командами с помощью которых мы будем управлять ботом:
Поиск информации в Censys по IP:
Поиск информации в Censys по домену:
Сканер портов:
Тест на WAF:
SearchSploit:
Создание модулей:
Создадим модуль для поиска информации в Censys:
Сначала разберемся с функцией, целью которой будет поиск информации в Censys по IP:
Создадим лист infos, где будем хранить всю нарытую информацию.
Зададим переменную header, чтобы Censys не выявил, что мы бот:
Теперь нам нужно сделать запрос к сайту, все ссылки Censys имеют вид:
Теперь, нам нужно использовать response.content, именно в нем содержатся данные которые нам передает Censys при обработке запроса:
Здесь, мы используем BeautifulSoup для преобразования данных в другой формат и сохраняет в переменной soup.
Изучив страницу через F12, мы поймем, что нужные нам данные касательно IP хранятся в "content", в BeautifulSoup есть возможность поиска по id, используем его:
Это еще не все, дальше нам нужно найти порты и протокол которые засек Censys, сделаем это с помощью поиска по классу:
Теперь нам нужно пройтись по каждому порту и сделать несколько преобразований, немного отформатировать строки и получить нормальные данные:
Далее, снова переопределяем переменную soup и ищем content:
Теперь мы попытаемся найти гораздо более интересную инфу, такую как:
Информация об ОС, информация о сети, информация о роутинге.
Ну и конечно же, сервисы на портах и их версия:
И снова проходимся по каждому порту и ищем сервисы:
Возвращаем нашу переменную:
Идем дальше, иногда сайт скрывает свой IP, через тот же WAF.
Предположим что мы с помощью будущей команды для WAF определили наличие CloudFlare, как нарыть инфу на сайт в таком случае?
К счастью, в Censys есть поиск и он поддерживает поиск по доменам, реализуем этот поиск в функции.
Мы будем хранить все найденные айпи в переменной
Как и в прошлый раз зададим headers:
Но того мало, нам так-же нужно задать доп. параметры для поиска
Теперь делаем запрос к серверу вместе со всеми параметрами и headers:
Теперь, нам нужно начинать парсинг, аналогично с предыдущей функцией используем response.text
Финальный штрих:
Это нужно, чтобы при импорте файла не выполнились все функции, а просто вызывались только нужные.
В корневой директории проекта создаем папку modules, добавляем туда файл censys.py, в котором будут две только что написанные функции.
Далее, нам нужно создать пустой __init__.py, чтобы Python знал, что это папка с модулями
Теперь мы можем использовать эти функции в нашем проекте.
Заходим в Auxiliator.py, импортируем Censys в начале файла:
Переходим к функции
В ней, нам нужно извлечь аргумент, то что идет после команды, в нашем случае это IP адрес.
Используем функцию extract_arg(arg), которую написали в начале статьи:
Далее:
Тоже самое с searchbydomain:
Наши первые две команды готовы!
Scaner:
Создание сканера будет легче, чем парсинг Censys. Я уже выпускал статью о создании сканера и в этой сделаю все кратко.
Создадим в папке modules scaner.py:
Чтобы сканер был достаточно быстрым, мы реализуем многопоточность с помощью следуещего модуля:
Далее, для подключения к портам мы будем использовать socket:
Все будет происходить в функции portscan:
Внутри этой функции будет находится функция для проверки одного порта:
В конце portscan() прописываем:
Теперь мы можем использовать эту функцию в нашем проекте.
Заходим в Auxiliator.py, импортируем наш модуль:
import modules.scanner as scanner
В начале статьи мы создали заготовку:
Добавляем сюда:
Детекторы WAF:
Существует замечательная утилита для выявления фаерволла на питоне, wafw00f.
К сожалению, по умолчанию ее нельзя использовать как модуль, но если подредактировать исходный код с гитхаба, то возможно все:
wafw00f/main.py at master · EnableSecurity/wafw00f, это оригинальный файл который выводит результаты сканирования на WAF.
А это, RollerScanner/wafmeow.py at main · MajorRaccoon/RollerScanner, отредактированный мной main.py, для работы с моим сканером, в нем лишь нужно заменить print на return:
В функции def wafsearch(target, scheme) я уберу все случаи использования цветного текста, заменю print на return и получу:
Полученный файл сохраню как wafmeow.py в моей папке modules. Теперь можно использовать его в нашем проекте. Возвращаемся в Auxiliator.py:
Импортируем наш модифицированный модуль:
В начале статьи у нас была заготовка:
Сюда добавляем:
Далее, модулю нужно понять какая схема используется, а значит она должна быть в аргументе:
Мы реализовали еще одну команду и у нас осталась только реализация searchsploit.
SearchSploit:
На главной странице exploit-db есть встроенная возможность поиска по базе:
Мы воспользуемся этим и через F12 найдем запрос к серверу:
Копируем как curl, заметим, что ответ к нам приходит в виде JSON.
С помощью
Получаем полностью рабочий код, который мы добавим в функцию.
Получаем:
В headers мы задаем параметры, чтобы нас не заблокировала защита от ботов, если она конечно есть. В params стоят параметры поиска, сам текст поиска содержится в search[value]. В последней строке мы отправляем запрос на сервер с нашими параметрами.
Мы получим неупорядоченный JSON, поэтому нам понадобится библиотека json:
Теперь начнем сортировку, в data будут содержаться нужные нам элементами, поэтому для каждого из них мы будем
Модуль готов к работе с ботом. Заходим в Auxiliator.py, используем нашу заготовку из начала статьи:
Под конец, во все команды я добавил исключения, чтобы бот не крашнулся при опечатке.
Тесты:
Предположим, у нас есть сайт artscp.com и телеграм бот. Сначала посмотрим есть ли у сайта защита фаерволла:
Нам приходит ответ:
Значит смысла в сканировании сейчас нету, попробуем найти настоящий IP:
Получаем:
95.216.162.249
130.193.62.38
Первый принадлежит app.artscp.com, второй artscp.com. Сканируем 130.193.62.38:
/scan 130.193.62.38
Спустя ~8 секунд получаю список:
Теперь хочется узнать поподробнее о том что стоит на портах:
Получаю достаточное кол-во инфы:
Попробуем найти эксплоиты для openssh 7.6:
Из ответа получаем следующие подходящие по версии эксплоиты:
Они могут быть полезны при дальнейшем изучении и эксплуатации машины, когда мы наконец-то доберемся до основной рабочей станции.
Весь код можно найти здесь
Думаю многие сталкивались с проблемой, когда нужно было сделать базовый анализ какого либо вебсайта, но ПК/Ноутбук рядом не находились, но был смартфон.
В таких случаях есть несколько решений, например кто-то имеет SSH доступ к основной машине, кто-то VNC. Конечно, это даст вам весь функционал (почти) и должно решить проблему, но когда в руках смартфон, то только мазохисты будут возражать заявлению о том, что печатать и управлять курсором с телефона совсем неудобно.
Главной проблемой остается управление, нужно что-то удобное, почему бы нам не взять телеграм ботов? Они ограничены в функционале, но гораздо более удобные, в них есть список комманд на которые достаточно нажать, а не печатать полностью, да и сам интерфейс более юзер-френдли.
В качестве библиотеки для бота я возьму telebot, т.к считаю ее самой простой и функциональной.
Мы реализуем поддержку:
- Censys
- Самописного сканера портов
- Детектора WAF
- SearchSploit
1. Подготовка почвы.
2. Создание модулей и подключение модулей.
2.1 Censys
2.2 Scaner
2.3 WAF
2.4 SearchSploit
3. Тесты
Подготовка почвы:
Перед работой нам понадобится установить telebot, прописываем:
Python:
pip3 install pytelegrambotapi
Python:
pip3 install requests
pip3 install bs4
Мы также будем использовать wafw00f для создания детекта WAF.
Python:
pip3 install wafw00f
В телеграме начнем беседу с @BotFather, создадим нового бота с помощью команды /newbot, можно ввести произвольные парметры, после завершения мы получим так называемый токен, он нам пригодится в дальнейшем. Создадим Auxiliator.py, это будет основной файл где и будет сам бот. Импортируем нужный нам telebot:
Python:
import telebot
Теперь, нам нужен токен бота, это уникальный адрес вашего бота, вы должны были получить его при создании:
Python:
bot = telebot.TeleBot("ВАШ_ТОКЕН")
Используя команды, мы чаще всего будем так-же вводить цель, это будет аргументом и нам его нужно извлечь, напишем функцию:
Python:
def extract_arg(arg):
return arg.split()[1:]
Теперь, определимся с командами с помощью которых мы будем управлять ботом:
Поиск информации в Censys по IP:
Python:
@bot.message_handler(commands=['searchbyip'])
def searchbyip(message):
Поиск информации в Censys по домену:
Python:
@bot.message_handler(commands=['searchbydomain'])
def searchbydomain(message):
Сканер портов:
Python:
@bot.message_handler(commands=['scan'])
def scan(message):
Тест на WAF:
Python:
@bot.message_handler(commands=['waf'])
def waf(message):
SearchSploit:
Python:
@bot.message_handler(commands=['searchsploit'])
def searchsploit(message):
Создание модулей:
Создадим модуль для поиска информации в Censys:
Python:
import requests #Библиотека для создания запроса
import re #Библиотека для форматирования
from bs4 import BeautifulSoup #Библиотека для парсинга
Сначала разберемся с функцией, целью которой будет поиск информации в Censys по IP:
Python:
def SearchByIp(target):
Создадим лист infos, где будем хранить всю нарытую информацию.
Python:
infos=[]
Зададим переменную header, чтобы Censys не выявил, что мы бот:
Python:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0',
'Accept': 'text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Connection': 'keep-alive',
'Upgrade-Insecure-Requests': '1',
'Sec-Fetch-Dest': 'document',
'Sec-Fetch-Mode': 'navigate',
'Sec-Fetch-Site': 'none',
'Sec-Fetch-User': '?1',
'Cache-Control': 'max-age=0',
'TE': 'trailers',
}
Теперь нам нужно сделать запрос к сайту, все ссылки Censys имеют вид:
Ссылка скрыта от гостей
{ЦЕЛЬ}, делаем запрос вместе с header и получаем ответ:
Python:
response = requests.get(f'''https://search.censys.io/hosts/{target}''', headers=headers)
Теперь, нам нужно использовать response.content, именно в нем содержатся данные которые нам передает Censys при обработке запроса:
Python:
soup = BeautifulSoup(response.content, "html.parser")
Изучив страницу через F12, мы поймем, что нужные нам данные касательно IP хранятся в "content", в BeautifulSoup есть возможность поиска по id, используем его:
Python:
results = soup.find(id="content").
Это еще не все, дальше нам нужно найти порты и протокол которые засек Censys, сделаем это с помощью поиска по классу:
Python:
ports = results.find_all("div", class_="protocol-details")
Теперь нам нужно пройтись по каждому порту и сделать несколько преобразований, немного отформатировать строки и получить нормальные данные:
Python:
for port in ports:
soup = BeautifulSoup(str(port), features="lxml") #Преобразуем наш результат в объект BeautifulSoup
results = soup.h2 #Оставляем только h2
results = str(results.text) #Преобразуем в строку
results = results.replace(" ", "") #Удаляем пробелы
results = results.split('\n') #Разбиваем на строки
infos.append("Protocol:"+" "+results[1].split("/")[1]+" "+"is on port:"+" "+results[1].split("/")[0]) #Добавляем в лист infos протокол и порт
Далее, снова переопределяем переменную soup и ищем content:
Python:
soup = BeautifulSoup(response.content, "html.parser")
results = soup.find(id="content")
Теперь мы попытаемся найти гораздо более интересную инфу, такую как:
Информация об ОС, информация о сети, информация о роутинге.
Ну и конечно же, сервисы на портах и их версия:
Python:
try:
dl_data = results.find('dt', string='OS').find_next_siblings('dd') #Ищем все данные о ОС
infos.append("OS:"+dl_data[0].string.replace("\n", "")) #Добавляем в лист
except:
infos.append("OS Can't be specified!") #Если не нашли данные о ОС, выводим в лист ошибку
try:
dl_data = results.find('dt', string='Network').find_next_siblings('dd') #Ищем все данные о сети
infos.append("Network:"+dl_data[0].text.replace(" ", "").replace("\n", "")) #Добавляем в лист
except:
infos.append("Network Can't be specified!") #Если не нашли данные о сети, выводим в лист ошибку
try:
dl_data = results.find('dt', string='Routing').find_next_siblings('dd') #Ищем все данные о роутинге
infos.append("Routing:"+dl_data[0].text.replace(" ", "").replace("\n", "")) #Добавляем в лист
except:
infos.append("Routing Can't be specified!") #Если не нашли данные о роутинге, выводим в лист ошибку
Python:
for portservice in ports:
portlist=(portservice.find_next_siblings("div", class_="host-section")) #Ищемсоседние элементы
port=re.sub('\n\n', '\n', portlist[0].text) #Удаляем пустые строки
port=re.sub(' +', ' ', port) #Удаляем пробелы
port=port.split("\n") #Разбиваем на строки
infos.append(portservice.text.split("\n")[2].replace(" ", "")+":") #Добавляем в лист название порта
for el in port: #Проходимся по каждой строке
if el!='' and el!=' ' and "\r" not in el and "\n" not in el: #Если строка не пустая и не содержит пробелов и не содержит переносов строк
if(el.startswith(" ")==True): #Если строка начинается с пробела
infos.append(el.replace(" ", "-", 1)) #Удаляем пробел и добавляем в лист
if(el.startswith(" ")==False): #Если строка не начинается с пробела
infos.append(el+":") #Добавляем в лист
elif(el!=' '): #Если строка не пустая
infos.append(el) #Добавляем в лист
Возвращаем нашу переменную:
Python:
return(infos)
Предположим что мы с помощью будущей команды для WAF определили наличие CloudFlare, как нарыть инфу на сайт в таком случае?
К счастью, в Censys есть поиск и он поддерживает поиск по доменам, реализуем этот поиск в функции.
Python:
def SearchByDomain(target):
Мы будем хранить все найденные айпи в переменной
Python:
Мы будем хранить все найденные айпи в переменной addr=[]
Код:
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:92.0) Gecko/20100101 Firefox/92.0',
'Accept': '*/*',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'X-Requested-With': 'XMLHttpRequest',
'Connection': 'keep-alive',
'Referer': 'https://search.censys.io/search?resource=hosts&q=randomfgnya.com',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'Cache-Control': 'max-age=0',
}
Но того мало, нам так-же нужно задать доп. параметры для поиска
Код:
params = (
('resource', 'hosts'),
('q', f''' services.tls.certificates.leaf_data.names: {target}''')
)
Теперь делаем запрос к серверу вместе со всеми параметрами и headers:
Python:
response = requests.get('https://search.censys.io/_search', headers=headers, params=params) #Запрос к серверу
Теперь, нам нужно начинать парсинг, аналогично с предыдущей функцией используем response.text
Python:
soup = BeautifulSoup(response.text, "html.parser") #Парсим ответ
results=soup.text.replace("\n", "") #Удаляем переносы строк
results=re.sub(' +', ' ', results) #Удаляем пробелы
results=results.split(" ") #Разбиваем по пробелам
for result in results: #Проходимся по каждому элементу
preresult=str(result).replace("\n", "") #Удаляем переносы строк
preresult=preresult.replace(" ", "") #Удаляем пробелы
resultis=(preresult.split("\n")) #Разбиваем по переносам строк
if(any(c.isalpha() for c in resultis[0])==False and ")" not in resultis[0] and resultis[0]!=""): #Если элемент не содержит буквы и не содержит закрывающую скобку и не пустой
addr.append(resultis[0]) #Добавляем в лист
return(addr) #Возвращаем нашу переменную
Python:
if __name__ == "__main__":
SearchByDomain(target)
SearchByIp(target)
Это нужно, чтобы при импорте файла не выполнились все функции, а просто вызывались только нужные.
В корневой директории проекта создаем папку modules, добавляем туда файл censys.py, в котором будут две только что написанные функции.
Далее, нам нужно создать пустой __init__.py, чтобы Python знал, что это папка с модулями
Теперь мы можем использовать эти функции в нашем проекте.
Заходим в Auxiliator.py, импортируем Censys в начале файла:
Python:
import modules.censys as censys
Переходим к функции
Python:
Переходим к функции def searchbyip(message):
В ней, нам нужно извлечь аргумент, то что идет после команды, в нашем случае это IP адрес.
Используем функцию extract_arg(arg), которую написали в начале статьи:
Python:
IP=extract_arg(message.text)[0]
Далее:
Python:
info="\n".join(censys.SearchByIp(IP))
bot.send_message(message.chat.id, info)
Тоже самое с searchbydomain:
Python:
domain=extract_arg(message.text)[0]
info="\n".join(censys.SearchByDomain(domain))
bot.send_message(message.chat.id, info)
Наши первые две команды готовы!
Scaner:
Создание сканера будет легче, чем парсинг Censys. Я уже выпускал статью о создании сканера и в этой сделаю все кратко.
Создадим в папке modules scaner.py:
Чтобы сканер был достаточно быстрым, мы реализуем многопоточность с помощью следуещего модуля:
Python:
from concurrent.futures import ThreadPoolExecutor
Далее, для подключения к портам мы будем использовать socket:
Python:
import socket
Все будет происходить в функции portscan:
Python:
def portscan(host):
ports=list(range(1, 65535)) #Создаем список портов
portsopened=[] #Создаем пустой список для открытых портов
Внутри этой функции будет находится функция для проверки одного порта:
Python:
def scanner(port):
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) #Создаем сокет
s.settimeout(0.5) #Устанавливаем таймаут для сокета
try:
con = s.connect((host, port)) #Пытаемся подключиться к порту
portsopened.append(port) #Если подключились, добавляем порт в список открытых
con.close() #Если подключились, закрываем сокет
except:
pass #Если не подключились, просто пропускаем
В конце portscan() прописываем:
Python:
with ThreadPoolExecutor(max_workers=5000) as pool:
pool.map(scanner, ports)
return portsopened
Теперь мы можем использовать эту функцию в нашем проекте.
Заходим в Auxiliator.py, импортируем наш модуль:
import modules.scanner as scanner
В начале статьи мы создали заготовку:
Python:
@bot.message_handler(commands=['scan'])
def scan(message):
Добавляем сюда:
Python:
target=extract_arg(message.text)[0] #Извлекаем аргумент
bot.send_message(message.chat.id, "Scanning Started!") #Информируем о начале сканирования
openedports=scanner.portscan(target) #Сканируем порты и получаем открытые
info="\n".join(str(port) for port in openedports) #Преобразуем в строку
bot.send_message(message.chat.id, "Opened Ports\n"+info) #Отправляем информацию об открытых портах
Детекторы WAF:
Существует замечательная утилита для выявления фаерволла на питоне, wafw00f.
К сожалению, по умолчанию ее нельзя использовать как модуль, но если подредактировать исходный код с гитхаба, то возможно все:
wafw00f/main.py at master · EnableSecurity/wafw00f, это оригинальный файл который выводит результаты сканирования на WAF.
А это, RollerScanner/wafmeow.py at main · MajorRaccoon/RollerScanner, отредактированный мной main.py, для работы с моим сканером, в нем лишь нужно заменить print на return:
В функции def wafsearch(target, scheme) я уберу все случаи использования цветного текста, заменю print на return и получу:
Python:
res='The site %s%s%s is behind %s%s%s WAF.'
req='Number of requests: %s'
target=scheme+target
results = []
attacker = WAFW00F(target)
waf = attacker.identwaf(True)
if len(waf) > 0:
for i in waf:
results.append(buildResultRecord(target, i))
return(res % (B, target, E, C, (E+' and/or '+C).join(waf), E))
return(req % attacker.requestnumber)
Полученный файл сохраню как wafmeow.py в моей папке modules. Теперь можно использовать его в нашем проекте. Возвращаемся в Auxiliator.py:
Импортируем наш модифицированный модуль:
Python:
undefined
В начале статьи у нас была заготовка:
Python:
@bot.message_handler(commands=['waf'])
def waf(message):
Сюда добавляем:
Python:
target=extract_arg(message.text)[0] #Извлекаем аргумент
Далее, модулю нужно понять какая схема используется, а значит она должна быть в аргументе:
Python:
if("https" in target): #Если в аргументе есть https
firewall=wafmeow.wafsearch(target.replace("https://", ""), "https://") #То используем https и получаем ответ
bot.send_message(message.chat.id, firewall) #Отправляем ответ
if("http" in target): #Если в аргументе есть http
firewall=wafmeow.wafsearch(target.replace("http://", ""), "http://") #То используем http и получаем ответ
bot.send_message(message.chat.id, firewall) #Отправляем ответ
else:
bot.send_message(message.chat.id, "No scheme is provided, use either http or https!") #Если нет схемы, то отправляем сообщение об этом
Мы реализовали еще одну команду и у нас осталась только реализация searchsploit.
SearchSploit:
На главной странице exploit-db есть встроенная возможность поиска по базе:
Ссылка скрыта от гостей
Мы воспользуемся этим и через F12 найдем запрос к серверу:
Копируем как curl, заметим, что ответ к нам приходит в виде JSON.
С помощью
Ссылка скрыта от гостей
мы можем конвертировать curl в python.Получаем полностью рабочий код, который мы добавим в функцию.
Получаем:
Python:
def searchsploit(query):
results={}
headers = {
'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:93.0) Gecko/20100101 Firefox/93.0',
'Accept': 'application/json, text/javascript, */*; q=0.01',
'Accept-Language': 'ru-RU,ru;q=0.8,en-US;q=0.5,en;q=0.3',
'Referer': 'https://www.exploit-db.com/',
'X-Requested-With': 'XMLHttpRequest',
'Connection': 'keep-alive',
'Sec-Fetch-Dest': 'empty',
'Sec-Fetch-Mode': 'cors',
'Sec-Fetch-Site': 'same-origin',
'TE': 'trailers',
}
params = (
('draw', '1'),
('columns[0][data]', 'date_published'),
('columns[0][name]', 'date_published'),
('columns[0][searchable]', 'true'),
('columns[0][orderable]', 'true'),
('columns[0][search][value]', ''),
('columns[0][search][regex]', 'false'),
('columns[1][data]', 'download'),
('columns[1][name]', 'download'),
('columns[1][searchable]', 'false'),
('columns[1][orderable]', 'false'),
('columns[1][search][value]', ''),
('columns[1][search][regex]', 'false'),
('columns[2][data]', 'application_md5'),
('columns[2][name]', 'application_md5'),
('columns[2][searchable]', 'true'),
('columns[2][orderable]', 'false'),
('columns[2][search][value]', ''),
('columns[2][search][regex]', 'false'),
('columns[3][data]', 'verified'),
('columns[3][name]', 'verified'),
('columns[3][searchable]', 'true'),
('columns[3][orderable]', 'false'),
('columns[3][search][value]', ''),
('columns[3][search][regex]', 'false'),
('columns[4][data]', 'description'),
('columns[4][name]', 'description'),
('columns[4][searchable]', 'true'),
('columns[4][orderable]', 'false'),
('columns[4][search][value]', ''),
('columns[4][search][regex]', 'false'),
('columns[5][data]', 'type_id'),
('columns[5][name]', 'type_id'),
('columns[5][searchable]', 'true'),
('columns[5][orderable]', 'false'),
('columns[5][search][value]', ''),
('columns[5][search][regex]', 'false'),
('columns[6][data]', 'platform_id'),
('columns[6][name]', 'platform_id'),
('columns[6][searchable]', 'true'),
('columns[6][orderable]', 'false'),
('columns[6][search][value]', ''),
('columns[6][search][regex]', 'false'),
('columns[7][data]', 'author_id'),
('columns[7][name]', 'author_id'),
('columns[7][searchable]', 'false'),
('columns[7][orderable]', 'false'),
('columns[7][search][value]', ''),
('columns[7][search][regex]', 'false'),
('columns[8][data]', 'code'),
('columns[8][name]', 'code.code'),
('columns[8][searchable]', 'true'),
('columns[8][orderable]', 'true'),
('columns[8][search][value]', ''),
('columns[8][search][regex]', 'false'),
('columns[9][data]', 'id'),
('columns[9][name]', 'id'),
('columns[9][searchable]', 'false'),
('columns[9][orderable]', 'true'),
('columns[9][search][value]', ''),
('columns[9][search][regex]', 'false'),
('order[0][column]', '9'),
('order[0][dir]', 'desc'),
('start', '0'),
('length', '15'),
('search[value]', query),
('search[regex]', 'false'),
('author', ''),
('port', ''),
('type', ''),
('tag', ''),
('platform', ''),
('_', '1636022484613'),
)
response = requests.get('https://www.exploit-db.com/', headers=headers, params=params)
В headers мы задаем параметры, чтобы нас не заблокировала защита от ботов, если она конечно есть. В params стоят параметры поиска, сам текст поиска содержится в search[value]. В последней строке мы отправляем запрос на сервер с нашими параметрами.
Мы получим неупорядоченный JSON, поэтому нам понадобится библиотека json:
Python:
import json.
Теперь начнем сортировку, в data будут содержаться нужные нам элементами, поэтому для каждого из них мы будем
Python:
for element in data["data"]:
index=data["data"].index(element)
results["https://www.exploit-db.com/exploits/"+data["data"][index]["id"]] = data["data"][index]["description"][1]
return(results)
Модуль готов к работе с ботом. Заходим в Auxiliator.py, используем нашу заготовку из начала статьи:
Python:
@bot.message_handler(commands=['searchsploit'])
def searchsploit(message):
query=extract_arg(message.text)[0] #Получаем запрос для поиска
info=exploitsearch.searchsploit(query) #Ищем эксплоиты, получаем словарь
for exploit in info: #Для каждой ссылки на эксплоит
bot.send_message(message.chat.id, exploit+": "+info[exploit]) #Отправляем ссылку на эксплоит вместе с названием
Под конец, во все команды я добавил исключения, чтобы бот не крашнулся при опечатке.
Python:
try:
Код, код, код
except:
bot.send_message(message.chat.id, "Error!")
Тесты:
Предположим, у нас есть сайт artscp.com и телеграм бот. Сначала посмотрим есть ли у сайта защита фаерволла:
Код:
/waf https://artscp.com
Нам приходит ответ:
Код:
The site https://artscp.com is behind Cloudflare (Cloudflare Inc.) WAF.
Значит смысла в сканировании сейчас нету, попробуем найти настоящий IP:
Получаем:
95.216.162.249
130.193.62.38
Первый принадлежит app.artscp.com, второй artscp.com. Сканируем 130.193.62.38:
/scan 130.193.62.38
Спустя ~8 секунд получаю список:
Код:
Opened Ports
22
80
443
Теперь хочется узнать поподробнее о том что стоит на портах:
Код:
/searchbyip 130.193.62.38
Получаю достаточное кол-во инфы:
Код:
Protocol: SSH is on port: 22
Protocol: HTTP is on port: 80
Protocol: HTTP is on port: 443
OS:Ubuntu Linux 18.04
Network:YANDEXCLOUD(RU)
Routing:130.193.62.0/24 via AS200350
22/SSH:
Software:
-linux
CPE:
-cpe:2.3:o:*:linux:*:*:*:*:*:*:*:*
Ubuntu Linux:
Version:
-18.04
CPE:
-cpe:2.3:o:canonical:ubuntu_linux:18.04:*:*:*:*:*:*:*
OpenBSD OpenSSH:
Version:
-7.6
CPE:
-cpe:2.3:a:openbsd:openssh:7.6:p1:*:*:*:*:*:*
80/HTTP:
Software:
-nginx
CPE:
-cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*
443/HTTP:
Software:
-nginx
CPE:
-cpe:2.3:a:nginx:nginx:*:*:*:*:*:*:*:*
Попробуем найти эксплоиты для openssh 7.6:
Код:
/searchsploit openssh 7
Из ответа получаем следующие подходящие по версии эксплоиты:
Ссылка скрыта от гостей
Ссылка скрыта от гостей
Они могут быть полезны при дальнейшем изучении и эксплуатации машины, когда мы наконец-то доберемся до основной рабочей станции.
Весь код можно найти здесь
Последнее редактирование: