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

Поиск и сбор сервисов (ip, port)

ChekistOV

CD-диск
Пользователь
Регистрация
08.09.2024
Сообщения
12
Реакции
12
Привет, бандиты!

Статья (если ее так можно назвать), будет полезна для тех, кто только начинает.

Позавчера k0priz написал статью, в которой доступным языком расписана эксплуатация CVE-2024-3400.
Для многих новичков остается непонятным, где и как им получить таргеты...
Я не смог пройти мимо и не дать, хотя бы какое-то направление, куда смотреть.


Поисковики
Одни из самых распространенных:
Но мое внимание упало на LeakIx.

О главном

Допустим нам нужен сервис GlobalProtect, и чем больше у нас будет ip тем лучше.
Столкнувшись с тем что API дает возможность выкачать только 500 страниц, мы можем исправлять запрос к поисковику, тем самым сужать область поиска.

Пример:
port:80 - 500 страниц, затем port:443, еще +500 страниц, и того у нас уже 1000 страниц...
Потом еще и страны туда...

Чтобы сократить Ваше время, немного был подредактирован найденyый скрипт на GitHub, который дает возможность получать ip, удобным для нас образом.


Python:
#!/usr/bin/python3

import sys
import json
import time
import requests
import argparse
from rich.console import Console


# Парсер аргументов командной строки
parser = argparse.ArgumentParser(description="LeakIX API Query Tool")
parser.add_argument(
    "-s", "--scope",
    choices=["service", "leak"],
    help="Тип данных для запроса: 'service' (службы) или 'leak' (утечки).",
    type=str,
    required=True
)
parser.add_argument(
    "-p", "--pages",
    help="Количество страниц для запроса. По умолчанию: 2.",
    default=2,
    type=int
)
parser.add_argument(
    "-q", "--query",
    help="Поисковый запрос. Например, 'http.title:\"Admin Panel\"'.",
    default="",
    type=str
)
parser.add_argument(
    "-o", "--output",
    help="Файл для сохранения результатов. Например, 'results.txt'.",
    type=str
)
parser.add_argument(
    "-f", "--filter",
    choices=["ip", "protocol", "port", "all"],
    help="Фильтр для вывода результатов: 'ip' (только IP), 'protocol' (только протокол), 'port' (только порт), 'all' (все данные).",
    type=str,
    default="all"
)
parser.add_argument(
    "--api-keys",
    help="Путь к файлу с API-ключами (один ключ на строку). Например, '/path/to/api_keys.txt'.",
    type=str,
    required=True
)

args = parser.parse_args()

console = Console()


def print_banner():
    """Вывод баннера при запуске."""
    banner = """
    [bold cyan]LeakIX API Query Tool[/]
    [bold yellow]CHEKISTOV[/]
    [bold green]Инструмент для автоматизированного поиска данных в LeakIX.[/]
    """
    console.print(banner)


def check_output(result):
    """Сохранение результатов в файл."""
    if args.output and len(result) != 0:
        with open(args.output, "w") as f:
            result = list(dict.fromkeys(result))  # Удаление дубликатов
            for line in result:
                f.write(f"{line}\n")
        console.print(
            f"\n[bold green][+] Результаты успешно записаны в файл {args.output} ({len(result)} строк)\n"
        )
    sys.exit(0)


def load_api_keys(api_keys_file):
    """Загрузка API-ключей из файла."""
    try:
        with open(api_keys_file, "r") as f:
            api_keys = [line.strip() for line in f if line.strip()]
        if not api_keys:
            console.print("[bold red][X] В файле не найдено ни одного валидного API-ключа.")
            sys.exit(1)
        return api_keys
    except FileNotFoundError:
        console.print(f"[bold red][X] Файл с API-ключами не найден: {api_keys_file}")
        sys.exit(1)


def write_to_file(target):
    """Запись результата в файл."""
    if args.output:
        with open(args.output, "a") as f:
            f.write(f"{target}\n")


def main():
    # Вывод баннера
    print_banner()

    # Загрузка API-ключей
    api_keys = load_api_keys(args.api_keys)
    current_key_index = 0

    result = list()

    for page in range(0, args.pages):
        while True:
            api_key = api_keys[current_key_index]
            headers = {
                "api-key": f"{api_key}",
                "Accept": "application/json",
            }

            params = {
                "page": f"{page}",
                "q": f"{args.query}",
                "scope": f"{args.scope}",
            }

            console.print(f"[bold yellow][-] Отправка запроса: {params}")

            response = requests.get(
                "https://leakix.net/search", params=params, headers=headers
            )

            if response.text == "null":
                console.print(
                    "[bold yellow][!] Нет доступных результатов (проверьте ваш запрос или область поиска)"
                )
                break

            elif response.text == '{"Error":"Page limit"}':
                console.print(
                    f"[bold red][X] Лимит страниц исчерпан для API-ключа {api_key}. Переключение на следующий ключ..."
                )
                current_key_index = (current_key_index + 1) % len(api_keys)
                continue

            else:
                console.print(f"[bold green] Запрос страницы {page + 1} : \n")
                data = json.loads(response.text)

                try:
                    for json_data in data:
                        protocol = f"{json_data['protocol']}://"
                        protocol = (
                            protocol
                            if protocol == "http://" or protocol == "https://"
                            else ""
                        )
                        ip = json_data["ip"]
                        port = json_data["port"]

                        if args.filter == "ip":
                            target = ip
                        elif args.filter == "protocol":
                            target = protocol
                        elif args.filter == "port":
                            target = str(port)
                        else:
                            target = f"{protocol}{ip}:{port}"

                        if target not in result:
                            result.append(target)
                            console.print(f"[bold blue][+] {target}")
                            write_to_file(target)

                except Exception as e:
                    console.print(f"[bold red][X] Ошибка при обработке данных: {e}")
                    break

            break

        console.print("\n")
        time.sleep(1.9)  # Задержка для предотвращения превышения лимита запросов

    console.print(f"[bold green][+] Сбор данных завершен. Все результаты записаны в файл {args.output}.\n")
    check_output(result)


if __name__ == "__main__":
    main()


1745573684797.png


В целом, у меня на этом все.
Вдруг возникли трудности, всегда готов подсказать!
Если у кого-то есть идеи, по модернизации или улучшению процессов получений таргетов, буду очень рад услышать!



1745573846285.png
 
Спасибо за мануал и код.

Единственое query надо чутка по-другому задавать. Если делать как на скрине : -q "Global-Protect +country:\"France\"" то будет возвращать всю Францию (а если как в статье порт, то вернет все 443 и не важно есть там Global-Protect или нет).

Чтобы все таки искало только где есть/был Global-Protect , то запрос надо делать как-то так: python3 leakix.py -s service -q "+\"Global-Protect\" +country:\"France\"" ... (не забыв экранировать кавычки и поставить +(плюс) в начале).

В web версии тоже самое:

Global-Protect +country:"France"
12350.png


+"Global-Protect" +country:"France"
23151.png

по крайней мере у меня это так работает
 


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