3 PowerDNS -- DNS сервер для массового обслуживания с хранением информации об обслуживаемых зонах в СУБД.
4 Когда-то в прошлой жизни я его использовал в проекте DNS-хостинга.
5 PowerDNS был выбран пример ПО с ярко выраженной поверхностью атаки: есть сетевое соединение обслуживающие анонимных пользователей посылающих серверу нетривиальные запросы.
6 (Надо отметить что в том DNS-хостиге мы прятали наш PowerDNS за более общепринятым bind9 работающем в режиме трансляции запросов)
7 Условия экзамена по обучающей программе предполагали использование Natch для обнаружение функций лежащих на поверхности атаки и подлежащих первоочередной обработки фаззингом.
8 Когда поверхность атаки ярко выраженная, это сделать проще всего.
14 * выполнить сборку PowerDNS из исходников
15 * настроить тестовую DNS-зону
16 * запустить сервер в режиме авторитативного мастера,
17 * пометить данные приходящие на 53й порт по tcp и udp
18 * отправить к серверу запросы по tcp и udp протоколу
19 * изучить как помеченные данные перемещались через иерархию вызова функций.
21 ### Сборка и установка
23 1. Получаем исходники последней версии PowerDNS:
26 git clone https://github.com/PowerDNS/pdns.git
29 В моем случае используется ветка master находящаяся на коммите d4ccf7673a от 9 апреля 2025г.
31 2. Устанавливаем зависимости необходимые для сборки проекта
34 apt-get build-dep pdns-server
37 3. Конфигурируем проект и запускаем сборку
41 ./configure --with-modules="gpgsql"
48 Если обратить внимание на финальный вывод скрипта `./configure` то можно заметить, что PowerDNS по умолчанию собирается с отладочной информацией (ключ `-g`) и никаких дополнительных действий для сборки с покрытием предпринимать не надо.
50 Сборка осуществляется с модулем `gpgsql` который позволяет хранить информацию о зонах и записях в СУБД PostgreSQL, мне с ней привычнее работать.
54 #### 1. Устанавливаем PostgreSQL из пакетной системы Debian:
57 sudo apt-get install postgresql
61 #### 2. Создаем пользователя и базу данных для хранения данных PowerDNS
65 createuser -P pdns_user
67 createdb pdns -O pdns_user
70 #### 3. Создание схемы базы данных
72 Копируем схему базы данных из [документации](https://doc.powerdns.com/authoritative/backends/generic-postgresql.html#default-schema) в буфер
73 (та же схема есть в исходниках по пути `modules/gpgsqlbackend/schema.pgsql.sql`)
75 Подключаемся консолью `psql` к базе `pdns` и переключаемся в пользователя `pdns_user`
83 Вставляем из буфера обмена в консоль код схемы скопированный выше из документации, нажимаем Enter.
85 В консоли появится много строк начинающихся со слова `CREATE`.
87 Выходим из консоли `psql`, выходим из `shell`-консоли пользователя `postgres`
94 #### 4. Создание конфигурации PowerDNS
96 Копируем пример файла конфигурации в актуальный конфигурационный файл
99 cp /usr/local/etc/pdns.conf-dist /usr/local/etc/pdns.conf
102 Добавляем в файл `/usr/local/etc/pdns.conf` строки
106 gpgsql-host=127.0.0.1
107 gpgsql-user=pdns_user
108 gpgsql-password=[ваш пароль]
111 В значение параметра `gpgsql-password` записываете пароль который вы указали при создании пользователя pdns.
115 #### 1. Проверяем что вообще запускается
117 По неизвестной мне причине бинарник `pdns_server` в `/usr/local/bin` при `make install` не установился, но при наличии правильного конфигурационного в ожидаемом месте можно запускать бинарник прямо из директории сборки
120 sudo pdns/pdns_server
123 Если все было сделано правильно сервер запустится, сообщит что присоединился к каким-то портам и перейдет в режим ожидания соединения.
124 Если была допущена какая-то ошибка надо ее устранить и добиться того чтобы сервер запустился.
125 Сервер пока останавливаем нажав Ctrl+C
127 #### 2. Создаем тестовую зону.
129 В директории сборки в папке `/psql` есть утилита для управления зонами и записями PowerDNS. Используем ее для создания зоны.
132 pdns/pdnsutil create-zone example.com
133 pdns/pdnsutil add-record example.com test A '8.8.8.8'
136 Этими командами мы создаем A-запись, которая указывает, что доменное имя `test.example.com` привязана к IP-адресу `8.8.8.8`
138 Можно зайти обратно в `psql` и убедиться, что таблицах `domains` и `records` были созданы соответсвующие записи:
141 select * from domains;
142 select * from records;
145 #### 3. Локальное тестирование
147 Запустим сервер как в п.1
150 sudo pdns/pdns_server
153 в соседней консоли еще раз зайдем на виртуалку и выполним команды
156 dig @127.0.0.1 test.example.com
158 dig @127.0.0.1 test.example.com +tcp
161 Эти команды выполнят запросы к нашему DNS-серверу по UDP и TCP протоколам. Правильный ответ должен содержать строку
164 test.example.com. 3600 IN A 8.8.8.8
167 А так же в разделе `flags:` должен присутствовать флаг `aa`, говорящий что это ответ от сервера отвечающего за зону, а не ретранслированный.
169 #### 4. Пробрасывание 53 порта наружу
171 Теперь нам надо сделать так, чтобы порт по которому PowerDNS обслуживает клиентов, оказался доступен на host-машине.
173 Для этого в скрипт запуска виртуалки в опции настройки сети добавим параметры `hostfwd=udp::15353-:53,hostfwd=tcp::15353-:53`, в результате чего в теории 53 порт внутри виртуалки будет замэплен на порт 15353 хост машины и по TCP и по UDP.
174 Проделав это перезапустим виртуалку.
176 9. Тестирование извне виртуалки
178 Зайдя в виртуалку запускаем DNS-свервер как в п.1
181 sudo pdns/pdns_server
184 И на хост-машине делаем TCP и UDP DNS-запросы по порту 15353 локального интерфеса:
187 dig @127.0.0.1 -p15353 test.example.com +tcp
188 dig @127.0.0.1 -p15353 test.example.com
191 Результат должен оказаться такой же как в п.3.
196 На основании созданного образа виртуальной машины мы создаем два проекта natch для пометки данных по протоколу TCP и для пометки данных по протоколу UDP.
197 Процесс создания проектов в достаточной мере отражен в документации, обозначу лишь ключевые нюансы:
199 * Создаем два отдельных проекта, один для перехвата TCP, другой для перехвата UDP
200 * Для случая TCP в консольном диалоге запрашиваем проброс наружу 53го порта, в `tainted.cfg` в разделе `[Ports]` указываем `ip_protocol=6`, `dst=53`, `rc=53`, и все должно заработать
201 * Для случая UDP, после создания проекта, необходимо руками во всех конфигах заменить `hostfwd=tcp` на `hostfwd=udp`, в `tainted.cfg` в разделе `[Ports]` указать `ip_protocol=17`, а `src` и `dst` не указывать вовсе.
203 Выяснить, читая конфиги на какой из внешних портов замэплен находящийся внутри виртуалки 53 порт. А потом все более или менее по инструкции:
205 * Включаем запись сценария `natch record`
206 * Логинимся в виртуалку, уже через графическое окно qemu
207 * Делаем первый снэпшот
208 * Запускаем сервер, как это делали при тестировании
209 * С хост машины отправляем запрос на TCP или UDP порт на который был замаплен 53 порт виртуалки (значение добывается из конфигов натча), так же как это делали при тестировании, номер порта только надо будет поменять.
211 * Делаем второй снепшот
214 Далее командой `natch replay` снимаем трассу между первым и вторым снепшотом и загружаем ее в snatch.
216 ### Анализ результатов.
218 Данные пришедшие в систему 53 TCP или UDP порта, были помечены, и при помощи программы визуализации snatch можно посмотреть как они распространялись по системе
222 Посмотрев на вкладку Resources мы можем следать вывод, что помеченные данные проходили через сам процесс pdns_server'а и через процесс ядра (имеют право) и через другие процессы не проходили
224 