]> Untitled Git - articles.git/blob
83617beef9c5e2906cc0cdc7bf84903a0a6ec424
[articles.git] /
1 ## PowerDNS
2
3 PowerDNS -- DNS сервер для массового обслуживания с хранением информации об обслуживаемых зонах в СУБД.
4 Когда-то в прошлой жизни я его использовал в проекте DNS-хостинга.
5 PowerDNS был выбран пример ПО с ярко выраженной поверхностью атаки: есть сетевое соединение обслуживающие анонимных пользователей посылающих серверу нетривиальные запросы.
6 (Надо отметить что в том DNS-хостиге мы прятали наш PowerDNS за более общепринятым bind9 работающем в режиме трансляции запросов)
7 Условия экзамена по обучающей программе предполагали использование Natch для обнаружение функций лежащих на поверхности атаки и подлежащих первоочередной обработки фаззингом.
8 Когда поверхность атаки ярко выраженная, это сделать проще всего.
9
10 ### План эксперимента   
11
12
13 Предполагается 
14 * выполнить сборку PowerDNS из исходников
15 * настроить тестовую DNS-зону
16 * запустить сервер в режиме авторитативного мастера,
17 * пометить данные приходящие на 53й порт по tcp и udp 
18 * отправить к серверу запросы по tcp и udp протоколу
19 * изучить как помеченные данные перемещались через иерархию вызова функций.
20
21 ### Сборка и установка
22
23 1. Получаем исходники последней версии PowerDNS:
24
25 ```
26 git clone https://github.com/PowerDNS/pdns.git
27 ```
28
29 В моем случае используется ветка master находящаяся на коммите d4ccf7673a от 9 апреля 2025г.
30
31 2. Устанавливаем зависимости необходимые для сборки проекта
32
33 ```
34 apt-get build-dep pdns-server
35 ```
36
37 3. Конфигурируем проект и запускаем сборку
38
39
40 ```
41 ./configure --with-modules="gpgsql"
42
43 make
44
45 sudo make install
46 ```
47
48 Если обратить внимание на финальный вывод скрипта `./configure` то можно заметить, что PowerDNS по умолчанию собирается с отладочной информацией (ключ `-g`) и никаких дополнительных действий для сборки с покрытием предпринимать не надо.
49
50 Сборка осуществляется с модулем `gpgsql` который позволяет хранить информацию о зонах и записях в СУБД PostgreSQL, мне с ней привычнее работать.
51
52 ### Настройка
53
54 #### 1. Устанавливаем PostgreSQL из пакетной системы Debian:
55
56 ```
57 sudo apt-get install postgresql
58 ```
59
60
61 #### 2. Создаем пользователя и базу данных для хранения данных PowerDNS
62
63 ```
64 sudo su postgres
65 createuser -P pdns_user
66 # Вводим пароль
67 createdb pdns -O pdns_user
68 ```
69
70 #### 3. Создание схемы базы данных
71
72 Копируем схему базы данных из [документации](https://doc.powerdns.com/authoritative/backends/generic-postgresql.html#default-schema) в буфер
73 (та же схема есть в исходниках по пути `modules/gpgsqlbackend/schema.pgsql.sql`)
74
75 Подключаемся консолью `psql` к базе `pdns` и переключаемся в пользователя `pdns_user`
76
77 ```
78 psql pdns
79 set role pdns_user;
80
81 ```
82
83 Вставляем из буфера обмена в консоль код схемы скопированный выше из документации, нажимаем Enter.
84
85 В консоли появится много строк начинающихся со слова `CREATE`.
86
87 Выходим из консоли `psql`, выходим из `shell`-консоли пользователя `postgres`
88
89 ```
90 exit
91 exit
92 ```
93
94 ####  4. Создание конфигурации PowerDNS
95
96 Копируем пример файла конфигурации в актуальный конфигурационный файл
97
98 ```
99 cp /usr/local/etc/pdns.conf-dist /usr/local/etc/pdns.conf
100 ```
101
102 Добавляем в файл `/usr/local/etc/pdns.conf` строки
103
104 ```
105 launch=gpgsql
106 gpgsql-host=127.0.0.1
107 gpgsql-user=pdns_user
108 gpgsql-password=[ваш пароль]
109 gpgsql-dbname=pdns
110 ```
111 В значение параметра `gpgsql-password` записываете пароль который вы указали при создании пользователя pdns.
112
113 ### Тестирование
114  
115 #### 1. Проверяем что вообще запускается
116
117 По неизвестной мне причине бинарник `pdns_server` в `/usr/local/bin` при `make install` не установился, но при наличии правильного конфигурационного в ожидаемом месте можно запускать бинарник прямо из директории сборки
118
119 ```
120 sudo pdns/pdns_server
121 ```
122
123 Если все было сделано правильно сервер запустится, сообщит что присоединился  к каким-то портам и перейдет в режим ожидания соединения. 
124 Если была допущена какая-то ошибка надо ее устранить и добиться того чтобы сервер запустился.
125 Сервер пока останавливаем нажав Ctrl+C
126
127 #### 2. Создаем тестовую зону.
128
129 В директории сборки в папке `/psql` есть утилита для управления зонами и записями PowerDNS. Используем ее для создания зоны.
130
131 ```
132 pdns/pdnsutil create-zone example.com
133 pdns/pdnsutil add-record example.com test A '8.8.8.8'
134 ```
135
136 Этими командами мы создаем A-запись, которая указывает, что доменное имя `test.example.com` привязана к IP-адресу `8.8.8.8`
137
138 Можно зайти обратно в `psql` и убедиться, что таблицах `domains` и `records` были созданы соответсвующие записи:
139
140 ```
141 select * from domains;
142 select * from records;
143 ```
144
145 #### 3. Локальное тестирование 
146
147 Запустим сервер как в п.1
148
149 ```
150 sudo pdns/pdns_server
151 ```
152
153 в соседней консоли еще раз зайдем на виртуалку и выполним команды
154
155 ```
156 dig @127.0.0.1 test.example.com
157
158 dig @127.0.0.1 test.example.com +tcp
159 ```
160
161 Эти команды выполнят запросы к нашему DNS-серверу по UDP и TCP протоколам. Правильный ответ должен содержать строку
162
163 ```
164 test.example.com.       3600    IN      A       8.8.8.8
165 ```
166
167 А так же в разделе `flags:` должен присутствовать флаг `aa`, говорящий что это ответ от сервера отвечающего за зону, а не ретранслированный.
168
169 #### 4. Пробрасывание 53 порта наружу
170
171 Теперь нам надо сделать так, чтобы порт по которому PowerDNS обслуживает клиентов, оказался доступен на host-машине.
172
173 Для этого в скрипт запуска виртуалки в опции настройки сети добавим параметры `hostfwd=udp::15353-:53,hostfwd=tcp::15353-:53`, в результате чего в теории 53 порт внутри виртуалки будет замэплен на порт 15353 хост машины и по TCP и по UDP.
174 Проделав это перезапустим виртуалку.
175
176 9. Тестирование извне виртуалки
177
178 Зайдя в виртуалку запускаем DNS-свервер как в п.1
179
180 ```
181 sudo pdns/pdns_server
182 ```
183
184 И на хост-машине делаем TCP и UDP DNS-запросы по порту 15353 локального интерфеса:
185  
186 ```
187 dig @127.0.0.1 -p15353 test.example.com +tcp
188 dig @127.0.0.1 -p15353 test.example.com
189 ```
190
191 Результат должен оказаться такой же как в п.3.
192
193
194 ### Запись трассы
195
196 На основании созданного образа виртуальной машины мы создаем два проекта natch для пометки данных по протоколу TCP и для пометки данных по протоколу UDP.
197 Процесс создания проектов в достаточной мере отражен в документации, обозначу лишь ключевые нюансы:
198
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` не указывать вовсе. 
202
203 Выяснить, читая конфиги на какой из внешних портов замэплен находящийся внутри виртуалки 53 порт. А потом все более или менее по инструкции:
204
205 * Включаем запись сценария `natch record`
206 * Логинимся в виртуалку, уже через графическое окно qemu
207 * Делаем первый снэпшот
208 * Запускаем сервер, как это делали при тестировании
209 * С хост машины отправляем запрос на TCP или UDP порт на который был замаплен 53 порт виртуалки (значение добывается из конфигов натча), так же как это делали при тестировании, номер порта только надо будет поменять.
210 * Получаем ответ
211 * Делаем второй снепшот
212 * Выходим.
213
214 Далее командой `natch replay` снимаем трассу между первым и вторым снепшотом и загружаем ее в snatch.
215
216 ### Анализ результатов.
217
218 Данные пришедшие в систему 53 TCP или UDP порта, были помечены, и при помощи программы визуализации snatch можно посмотреть как они распространялись по системе
219
220 #### Resources
221
222 Посмотрев на вкладку Resources мы можем следать вывод, что помеченные данные проходили через сам процесс pdns_server'а и через процесс ядра (имеют право) и через другие процессы не проходили
223
224 ![...](1. PowerDNS.imgs/resources_0.png)
225