Привет! Ни для кого не секрет, что качественные вордлисты - это ключ к эффективному фаззингу и, как следствие, большему покрытию скоупа и хорошим файндингам во время пентеста и баг-баунти. Однако вордлисты в общем доступе далеко не всегда дадут достаточное покрытие, какими бы большими они ни были. У веб-приложения может быть свой специфический нейминг путей и параметров. Некоторые ручки могут находиться на внескоуповых доменах и дублироваться на скоуповых, иногда даже с измененной функциональностью. Часть параметров и вовсе не удастся найти без ручного анализа JavaScript-кода приложения.

Здесь в игру вступают кастомные вордлисты, закрывающие все вышеперечисленные нюансы. Благодаря ним можно значительно эффективнее проводить фаззинг путей веб-приложения, а также брутить параметры его запросов.

Эта статья - первая из цикла про кастомные словари, рассказывающая про сбор базового вордлиста без особых усилий. В следующей статье я расскажу про создание более комплексного кастомного вордлиста, требующего больших затрат по времени.

А мне точно это нужно?

Не важно, баунти-хантер вы или пентестер, большее покрытие таргета - это хорошо, ведь всегда есть шанс наткнуться на забытые разработчиками параметры и пути. Даже один новый найденный ассет может дать вам преимущество перед другими исследователями.

Если у вас широкий скоуп с большим количеством поддоменов, шансы найти такие ассеты куда больше, чем на пентесте небольшой компании с парой поддоменов. Но даже в этом случае, если есть время, не стоит пренебрегать созданием кастомных вордлистов. Как-то раз во время пентеста небольшой компании благодаря кастомному вордлисту мне удалось обнаружить XSS в скрытом параметре на платёжной странице.

Отдельно стоит упомянуть, что кастомные словари неплохо себя показывают на регулярных пентестах (Penetration Testing as a Service) и в баг-баунти на больших программах с регулярно обновляющейся кодовой базой. Формируя кастомный вордлист на основе текущего состояния системы, вы делаете его ключом к скрытой поверхности атаки в будущем. Например, вы перехватили JSON-ответы API аутентифицированного пользователя и получили слова, которые невозможно найти в веб-архивах, сфокусированных в основном на сохранении статики. Эти уникальные слова в данный момент могут не участвовать в активной логике приложения, но с большой вероятностью могут появиться в следующих итерациях разработки приложения во время вашего следующего тестирования.

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

Лично я при пентесте составляю вордлист во второй половине работы, уже после того, как сделал базовый рекон и посмотрел основной функционал. После чего выборочно использую словарь, руководствуясь своей хакерской интуицией. Иногда не делаю кастомный вордлист вообще, если требуется проверить много бизнес-логики.

Базовый кастомный вордлист

Ниже написал процесс сбора базового кастомного вордлиста на примере тестового приложения.

1. Ручной краулинг с прокси

Все начинается с того, чтобы вручную посетить таргеты с включенным прокси и собрать достаточное количество запросов. В своей работе я использую Firefox с расширением FoxyProxy, направляющим запросы в Burp Suite.

Сохраненные в Burp Suite запросы и ответы нам понадобятся к концу этой главы, чтобы распарсить их через расширение и собрать вордлист.

Автоматизированные краулеры смогут прокликать все статичные страницы, однако они плохо справляются с динамическим функционалом, поэтому без ручного этапа никуда. Зарегистрируйтесь в личном кабинете, поменяйте пароль, отправьте сообщение в поддержку, оплатите подписку и т.д. - сделайте все возможные действия, доступные через UI.

Так вы получите больше запросов к API и соответствующих ответов сервера.

2. Автоматизированный краулинг

Как я упоминал выше, посещением всех статичных страниц займется автоматика. Я использую краулер Katana - он достаточно быстрый, и в нем есть удобный динамический анализ ссылок в JavaScript-файлах.

Не забудьте передать краулеру сессионную Cookie, если на таргете имеется функционал, закрытый за авторизацией. Запросы краулера аналогично проксируйте в Burp Suite.

Также для перестраховки от блокировки WAF-ом советую менять User-Agent на стандартный агент браузера.

Пример команды (можете заменить параметр глубины кроулинга -depth по вашему желанию, то же самое с рейт-лимитами в параметре -rl):

katana -u https://example.com (-list urls.txt) -depth 5 -js-crawl -jsluice -known-files all -proxy http://127.0.0.1:8080 -rl 100 -o katana-example-com.out -v -H 'User-Agent: xxx' -H 'Cookie: xxx=xxx'

3. Фаззинг со стандартными вордлистами

Также важно пофаззить пути веб-приложения общедоступными вордлистами, чтобы найти скрытые ручки и, самое главное, сохранить ответы на них. Содержимое ответов на открытой кастомной админ-панели может содержать достаточно много слов для нашего вордлиста, а JS-файлы на странице входа - еще больше.

Для фаззинга я использую инструмент ffuf и вордлисты fuzz.txt, content discovery all.txt. Второй достаточно большой, его советую оставлять запущенным на ночь на VPS в tmux.

Валидные страницы можно сразу отправлять в Burp через параметры -r -replay-proxy http://127.0.0.1:8080 (-r — следовать редиректам, -replay-proxy — направлять в прокси Burp Suite только те запросы, которые прошли фильтрацию). Это позволяет за один проход и собрать результаты фаззинга и запроксировать валидные эндпоинты в Burp.

Если нужно отфильтровать другой код ответа, меняйте 403 в -fc на соответствующий (можно перечислять через запятую, например -fc 403,404).

Пример команды:

ffuf -c -w fuzz.txt -u https://example.com/FUZZ -rate 80 -t 5 -fc 403 -H "User-Agent: Mozilla Firefox" -r -replay-proxy http://127.0.0.1:8080 -o ffuf/<url>-fuzz.out

4. Собираем URL из архивов через gau

gau - инструмент, позволяющий собрать сохраненные URL домена на различных сайтах-архивах вроде webarchive.org. То есть, по сути, осуществить быстрый автоматизированный OSINT - найти URL, которые в приложении уже нигде не фигурируют, но остались в истории Интернета. Не игнорируйте этот шаг - очень много файндингов идёт именно отсюда.

Пример команды:

cat <subdomains.txt> | gau --blacklist ttf,woff,svg,png,jpg --fc 404 --o gau.out --verbose

На практике аргумент blacklist не всегда работает корректно, поэтому советую инверсивно грепать статику из вывода gau:

cat gau.out | grep -vE '\.ttf|\.woff|\.svg|\.png|\.jpg'

Полученные URL прогоняем через тот же ffuf, чтобы запроксировать их в Burp, как во втором шаге.

Так как мое тестовое приложение локальное и не оставило следов в сети, для примеров, связанных с OSINT, буду использовать сайт www.spacex.com:

5. Парсим JavaScript-файлы через xnLinkFinder

xnLinkFinder - инструмент для краулинга и поиска URL в JavaScript-файлах. Примечателен тем, что умеет проверять относительные пути, а также собирать отдельный вордлист параметров, который мы потом совместим с нашим основным кастомным словарем.

Инструмент нужен для увеличения покрытия - он находит ручки, скрытые в JS-файлах.

Хотя инструмент и позиционируется как краулер, я не вижу смысла делать краулинг повторно после того, как мы сделали его через Katana. Поэтому рекомендую использовать xnLinkFinder как парсер для JavaScript-файлов.

Сохраните запросы-ответы из Burp, выделив все URL в таргете - ПКМ - Save selected items - base64-encode requests and responses.

Пример команды (-sp - домен со схемой для подстановки перед относительными URL, -sf - фильтр по одному или нескольким доменам в XML-файле Burp Suite, если их несколько):

xnLinkFinder -i <urls.xml> -sp https://example.com -sf example.com -o xnlinkfinder.out -op xnlinkfinder-params.out -d 3

В результате вы получите список найденных URL и вордлист с параметрами.

Полученные URL также нужно спроксировать в Burp Suite через ffuf.

6. Формируем кастомный вордлист через GAP

GAP - расширение для Burp от автора xnLinkFinder. Именно ради него мы проксировали все запросы в Burp на предыдущих этапах. Оно парсит все URL в таргете и составляет на их основе кастомный вордлист. Скачать его можете из BApp Store.

Для более полного покрытия советую перед запуском расширения включить следующие опции:

  • Include URL path words? (в Parameters mode и в Words mode)

  • JSON params (в Request и Response Parameters)

  • Cookie names

  • Name and Id attributes of HTML input fields

  • Include potential params?

  • Params from links found

  • Selected target(s)

Также укажите директорию в поле Auto save output directory и нажмите Save options.

Для запуска: ПКМ по домену в Target - Extensions - GAP.

В результате получаются два вордлиста (Params, Words) и список URL (Links).

В завершение совмещаем вордлисты GAP-а с вордлистом параметров xnLinkFinder, удаляем дубли и получаем кастомный вордлист!

cat xnlinkfinder-deiteriypay-params.out http-deiteriypay.local/deiteriypay.local_20260414_155944_params.txt http-deiteriypay.local/deiteriypay.local_20260414_155944_words.txt | sort -u > wordlist-final.txt

Использование вордлистов на практическом примере

  1. Param Miner

Param Miner - расширение для Burp Suite от небезызвестного Джеймса Кеттла.

Для начала его нужно настроить в одноименной вкладке сверху, указав ему наш вордлист и поставив галочку use custom wordlist. Также я использую некоторые другие опции, которые вы можете видеть на скриншоте.

Запустить расширение очень просто - ПКМ по запросу - Extensions - Param Miner - Guess …

Советую для каждого запроса выбирать логичные варианты: Guess query params для GET-запросов, body params для POST/PUT/PATCH-запросов. Guess cookies/headers советую сканить лишь один раз, логика с большой вероятностью будет повторяться на всем таргете (но, естественно, смотрите по ситуации).

Если хотите побольше узнать про другие опции Param Miner’а, можете почитать об этом в нашей статье.

После завершения сканирования видим новый Issue о том, что найден скрытый параметр internal_receipt_id на ручке deiteriypay.local:8090/checkout:

Параметр internal_receipt_id был зашит в файл app.js и был успешно извлечён расширением GAP.

Благодаря этому legacy-параметру на тестовом стенде удалось найти XSS:

2. ffuf

Кастомный вордлист не ограничивается брутом параметров. Он может быть использован и для фаззинга путей. Однако пути зачастую куда капризнее к неймингу, и на реальном таргете словарь с параметрами требует доработки, чтобы использоваться для фаззинга путей.

Я не знаю ни одного инструмента, который умел бы анализировать нейминг путей и генерировать на его основе потенциальные URL. Нечто похожее реализовано в kiterunner - фаззере API, однако его функционал рекурсивного фаззинга ограничен встроенными вордлистами. Возможно, в этой задаче могут хорошо помочь нейросети. Если знаете подходящие инструменты для работы с кастомными словарями - делитесь в комментариях!

Поэтому для грамотного покрытия таргета стоит уделить хотя бы немного времени ручному анализу нейминга URL и редактуре вордлиста с параметрами. Но, конечно, можно и просто закинуть вордлист с параметрами на фаззинг как https://example.com/FUZZ.

На тестовом стенде, прочитав вордлист Links от GAP, можно увидеть, что в нейминге часто используется разделение нескольких слов через - и префиксы типа deiteriy-, deit-. Также мы знаем, что API расположен на /api/v1/.

На основании этих данных сделаем мутации вордлиста с параметрами, добавив к словам, начинающимся со строчной буквы, префиксы, а также соединив эти слова через дефисы. Сканировать будем URL http://deiteriypay.local:8090/api/v1/FUZZ. Пример баш-скрипта для очистки и мутаций словаря будет приведен ниже.

Мутации вордлиста стоит проводить на как можно более чистом и маленьком вордлисте, чтобы он не раздулся в размерах. Более подробно про очистку вордлистов я расскажу в следующей части статьи. А пока что приведу пример мутации вордлиста для тестового стенда.

Я заметил, что в вордлисте много повторяющихся слов с заглавной буквы. Решил почистить вордлист, убрав слова с заглавной буквы и слова короче 3 символов, и сделать конкатенацию слов с дефисами и префиксами. Я написал баш-скрипт, но можно удобнее это делать через Python. В помощь с написанием простых скриптов рекомендую использовать ИИ.

#!/usr/bin/env bash
set -euo pipefail

INPUT="${1:-wordlist-final.txt}"
OUTPUT="${2:-paths-mutated.txt}"
PREFIXES="deiteriy deit"

if [[ ! -f "$INPUT" ]]; then
    exit 1
fi

ATOMS=$(mktemp)

# Очистка и подготовка "атомов"
sed 's/[-_]/\n/g' "$INPUT" | \
    grep -v '[A-Z]' | \
    awk 'length >= 3' | \
    grep -vxE "$(echo $PREFIXES | tr ' ' '|')" | \
    sort -u > "$ATOMS"

# Генерация мутаций
awk -v prefixes="$PREFIXES" '
BEGIN { np = split(prefixes, px, " ") }
      { a[NR] = $0; n = NR }
END   {
    for (i = 1; i <= n; i++) {
        print a[i]
        for (p = 1; p <= np; p++)
            print px[p] "-" a[i]
    }
    for (i = 1; i <= n; i++) {
        for (j = 1; j <= n; j++) {
            if (i == j) continue
            combo = a[i] "-" a[j]
            print combo
            for (p = 1; p <= np; p++)
                print px[p] "-" combo
        }
    }
}' "$ATOMS" | sort -u > "$OUTPUT"

rm -f "$ATOMS"

Вордлист получился внушительным, именно поэтому выше я упоминал, что для мутаций стоит работать с максимально очищенным вариантом словаря.

Фаззинг API тестового стенда и результаты:

Выводы

Кастомные вордлисты могут помочь более широко покрыть таргет, а также найти скрытый функционал, недоступный при использовании стандартных вордлистов. Однако создание вордлистов - процесс не полностью автоматический и требует времени. Важно грамотно его распределять, воспринимая кастомные вордлисты как дополнение к OSINT.

В итоге общий флоу создания кастомного вордлиста получается таким:

Делитесь в комментариях мнениями насчет статьи, своими подходами к составлению и использованию вордлистов, а также инструментами, которые для этого применяете.

Увидимся в следующей части! В ней я расскажу про более продвинутое составление кастомных вордлистов с добавлением во флоу OSINT, а также про утилиты и подходы к очистке словарей. Ещё затрону инструменты, которые помогают собрать вордлист без GAP - например, если вы используете Caido вместо Burp.

Комментарии (4)


  1. OlegZH
    30.04.2026 10:52

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

    "Вы это прекратите!" (с) Стругацкие, "Понедельник начинается в субботу".

    Зачем всё это? Это с порога отбивает читать дальше, даже, если дальше идёт описание какой-нибудь дельной вещи.

    Даже не знаю, что делать. Одно из двух: либо напроситься в Хабр в качестве редактора, который должен (вместо какой-нибудь модельки))) править чужие статьи для их всяческого улучшения, или писать собственные статьи на те же темы с воспроизведением тех же результатов (но и предложением собственных), но своими словами. Лучше, наверное, второе. ;-)


    1. gotch
      30.04.2026 10:52

      Так у меня не у одного пошла кровь из глаз?
      Извиняюсь, ничего что я по-русски?

      Кастомные
      вордлист
      фаззинг
      скоуп
      файндинг
      пентест
      баг-баунти
      нейминг
      внескоуповых
      брутить
      таргет
      ассет
      флоу
      рекон
      эндпоинты


  1. dimas846
    30.04.2026 10:52

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

    Ни для кого не секрет, что качественные списки слов и входных данных для перебора (wordlists) — это ключ к эффективному тестированию программ путём подачи большого количества случайных или специально подготовленных данных (fuzzing) и, как следствие, к большему охвату проверяемой области системы (scope coverage) и обнаружению полезных уязвимостей или проблем безопасности (findings) во время тестирования на проникновение (penetration testing, pentest) и в программах поиска уязвимостей за вознаграждение (bug bounty).


  1. Gutt
    30.04.2026 10:52

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

    Не могу не экспрессировать свой диповый эгримент с этим трули эстонишинговым стейтментом!