Skip to content

Latest commit

 

History

History

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
 
 
 
 
 
 
 
 
 
 
 
 

README.md

1. Общее описание

Ниже приведён пример фаззинг-тестирования Java-приложения Keycloak — программного продукта с открытым исходным кодом, представляющего собой сервер идентификации и управления доступом. Для взаимодействия с Keycloak по умолчанию используется TCP-порт 8080.

2. Подготовка к фаззингу

Перед выполнением фаззинга необходимо подготовить:

  • фаззинг-цель (Keycloak);
  • сценарий работы Keycloak;
  • начальный корпус вх. данных.

2.1. Фаззинг-цель

  1. Установка зависимостей для запуска Keycloak на хосте.
$ sudo apt install -y openjdk-17-jdk
  1. Создание докер-образа keycloak-build для сборки Keycloak.
$ docker build -f docker/Dockerfile-build -t keycloak-build docker/
  1. Сборка Keycloak.
$ docker run --rm -v $PWD:$PWD -w $PWD -ti keycloak-build /bin/bash
$ git clone https://github.com/keycloak/keycloak.git
$ cd keycloak
$ git checkout 26.0.7
$ mvn -pl quarkus/dist -am -DskipTests clean install
$ exit
$ cp keycloak/quarkus/dist/target/keycloak-26.0.7.tar.gz docker
$ cd docker
$ tar xf keycloak-26.0.7.tar.gz
$ cd ..

2.2. Сценарий работы Keycloak

Keycloak запускается в JVM с помощью скрипта ./docker/keycloak-26.0.7/bin/kc.sh, который автоматически формирует и передает параметры Java. Чтобы вывести эти параметры, в скрипте запуска kc.sh была изменена последняя строка на следующую:

eval exec echo "'$JAVA'" $JAVA_RUN_OPTS

Далее необходимо запустить:

$ ./docker/keycloak-26.0.7/bin/kc.sh start-dev

Полученные JVM-параметры были добавлены в конфигурационный файл config.json. В этом файле необходимо заменить пути в полях -Dkc.home.dir и -Djboss.server.config.dir на актуальные.

2.3. Начальный корпус вх. данных

Начальные образцы входных данных (HTTP-запросы в директории in) для целей фаззинга Keycloak были получены путём запуска в режиме разработчика с возможностью просмотра трафика.

3. Фаззинг

Будет рассмотрено 2 режима фаззинга:

  • (тестовый) фаззинг на хосте в однопоточном режиме;
  • многопоточный фаззинг в докер-режиме.

Фаззинг выполняется с помощью Crusher, который реализует:

  • возможность фаззинга сетевых приложений;
  • инструментацию Java байт-кода;
  • возможность параллельного изолированного фаззинга в докер-контейнерах

3.1. Однопоточный фаззинг Keycloak (тестовый)

Скрипт fuzz-1.sh используется для проверки запуска фаззера в 1 поток:

$ ./fuzz-1.sh /path/to/crusher

где:

  • -i - директория с начальным корпусом входных данных;
  • -o - директория для результатов;
  • -t - таймаут на запуск приложения (в мс);
  • --auto-stop-target-server - автоматическое завершение процесса анализируемого сервера после того, как он закрывает сокет передачи данных;
  • -T NetworkTCP - передача входных данных по TCP;
  • --port 8080 - порт, использующийся для передачи пакетов;
  • --ip 127.0.0.1 - IP-адрес для подключения;
  • --delay - время ожидания (в мс) на установление соединения с сервером;
  • -I javajacoco - тип инструментации Java без форк-сервера;
  • -- ./keycloak-26.0.7/lib/quarkus-run.jar - путь к исполняемому JAR-файлу;
  • io.quarkus.bootstrap.runner.QuarkusEntryPoint - путь к основному классу, содержащему метод main() — точку входа в приложение;
  • --profile=dev - запуск в режиме разработчика (опция keycloak);
  • start-dev - аргумент запуска Keycloak в dev-режиме (как в скрипте kc.sh).

Примечание: при запуске фаззинг-тестирования в однопоточном режиме HTML-отчёт о покрытии не формируется.

В данном примере будет наблюдаться рост покрытия. В директории ./out/queue будут находиться файлы с входными данными, которые приводят к нормальному завершению и росту покрытия.

3.2. Многопоточный фаззинг Keycloak в докер-режиме

При многопоточном фаззинге во избежание конфликтов за TCP-порт 8080 запуски различных процессов Keycloak необходимо изолировать. Для этого воспользуемся докер-режимом крашера - см. "Фаззинг в докер-контейнерах" в документации (crusher/README.pdf).

Менеджер фаззеров (fuzz_manager) создаёт отдельный контейнер для каждого фазз-процесса, который, в свою очередь, запускает Keycloak.

3.2.1. Создание докер-образа для фаззинга

  1. Настройки лицензии.

Для правильной работы лицензии в докер-контейнерах необходимо в файле docker/license/hasplm.ini указать ip-адрес сервера с сетевым hasp-ключом (красной или черной флешкой) в следующей строке:

serveraddr = X.X.X.X

Если hasp-ключ подключен к машине, где производится запуск, то hasplm.ini не нужно использовать. В таком случае нужно внести соответствующие изменения и в Dockerfile.

  1. Сборка докер-образа keycloak-fuzz.
$ ./docker/docker_build.sh

3.2.2. Запуск фаззера

Запуск многопоточного фаззинга:

$ ./fuzz.sh /path/to/crusher/

где:

  • --wait-next-instance - временной интервал (мс) между запусками процессов fuzz и eat;
  • --tcp-recv-response - получение ответа от анализируемого TCP-сервера;
  • --docker - Docker-образ;
  • --java-jacoco-trace - формирование отчета об покрытии;
  • --no-affinity - отключение привязки процессов к свободным ядрам;
  • --max-file-size - максимальный размер файла в начальном корпусе входных данных.

Остальные опции см. выше.

Примечание: при запуске необходимо указывать полные пути.

3.2.3. Мониторинг фаззинга

Для просмотра UI фаззера в другом терминале выполните следующую команду:

sudo -E /path/to/crusher/bin_x86-64/ui -o out

где:

  • -o <path> - путь до out директории, которая хранит в себе результаты работы фаззера

См. также "Пользовательский интерфейс" в документации.

4. Возможные проблемы

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

Следует проверить следующие логи:

  • При однопоточном фаззинге:
out/log_fuzzer
  • При многопоточном фаззинге
out/FUZZ-IspFuzzerManager-*/log_fuzzer

При обнаружении таких ошибок следует увеличить значения соответствующих опций в скриптах (fuzz-1.sh и fuzz.sh) и повторно запустить тестирование.

5. Анализ результатов

5.1. Образцы вх. данных (инпуты).

Сохраняются в out/EAT_OUT в следующих поддиректориях (в зависимости от статуса завершения таргета):

  • queue/ - нормальное завершение;
  • crashes/ - аварийное завершение (в случае Java - необработанное исключение);
  • hangs/ - зависание (таргет продолжает работу после истечения отведённого таймаута).

Для каждого инпута также сохраняется набор отчётов - out/EAT_OUT/results/, в частности - отчёт о покрытии.

5.2. Отчёт о покрытии.

$ sudo chown -R $USER:$USER out/
$ firefox out/.tmp/JavaJacocoTrace/report/index.html

Отчет содержит информацию о покрытии по инструкциям и ветвлениям (branches) на уровне JVM.