Gray Hat C#, OpenVAS, Программирование

#38 Gray Hat C#. Руководство для хакера по созданию и автоматизации инструментов безопасности. Класс OpenVASSession.

Здравствуйте, дорогие друзья.

Мы будем использовать класс OpenVASSession для связи с OpenVAS. В листинге ниже показаны конструктор и свойства, с которых начинается класс OpenVASSession.

The constructor and properties for the OpenVASSession class

Конструктор OpenVASSession принимает до четырех аргументов: имя пользователя и пароль для аутентификации в OpenVAS (по умолчанию в виртуальном устройстве это admin:admin); хост, к которому необходимо подключиться; и, опционально, порт для подключения на хосте, по умолчанию 9390 [1].
Мы передаем аргумент хоста в IPAddress.Parse() [2] и присваиваем результат свойству ServerIPAddress. Затем мы присваиваем значение переменной порта свойству ServerPort и передаем имя пользователя и пароль методу Authenticate(), если аутентификация прошла успешно (как описано в следующем разделе). Свойства ServerIPAddress и ServerPort назначаются в конструкторе и используются во всем классе.
Свойство Stream использует get [3], чтобы проверить, имеет ли значение частная переменная-член _stream значение null. Если это так, он вызывает GetStream(), который устанавливает [4] _stream с подключением к серверу OpenVAS, а затем возвращает переменную _stream.


Аутентификация на сервере OpenVAS

Чтобы попытаться пройти аутентификацию на сервере OpenVAS, мы отправляем XML-документ с именем пользователя и паролем в OpenVAS, а затем читаем ответ, как показано в листинге ниже. Если аутентификация прошла успешно, мы сможем вызвать команды с более высоким уровнем привилегий, чтобы указать цель для сканирования, получить отчет и т. д.

The OpenVASSession constructor’s Authenticate() method

Метод Authenticate() [1] начинается с принятия двух аргументов: имени пользователя и пароля для аутентификации с помощью OpenVAS. Мы создаем новую XML-команду аутентификации и используем имя пользователя [2] и пароль [3], предоставленные для учетных данных; затем мы отправляем запрос на аутентификацию с помощью ExecuteCommand() [4] и сохраняем ответ, чтобы мы могли убедиться, что аутентификация прошла успешно, и получить токен аутентификации.
Если атрибут status [5] корневого XML-элемента, возвращенный сервером, равен 200, аутентификация прошла успешно. Мы присваиваем методу свойства «Имя пользователя», «Пароль» и любые аргументы, а затем возвращаем ответ аутентификации.


Создание метода для выполнения команд OpenVAS

В листинге ниже показан метод ExecuteCommand(), который принимает произвольную команду OpenVAS, отправляет ее в OpenVAS и затем возвращает результат.

The ExecuteCommand() method for OpenVAS

Для выполнения команд с помощью протокола управления OpenVAS мы используем сокет TCP для отправки XML на сервер и получения XML в ответ.
Метод ExecuteCommand() принимает только один аргумент: отправляемый XML-документ. Мы вызываем ToString() для XML-документа, сохраняем результат, а затем используем метод Write() [1] свойства Stream, чтобы записать XML в поток.


Чтение сообщения сервера


Мы используем метод ReadMessage(), показанный в листинге ниже, для чтения сообщения, возвращаемого сервером.

The ReadMessage() method for OpenVAS

Этот метод считывает документ XML из потока TCP по частям и возвращает документ (или значение NULL) вызывающей стороне. После передачи sslStream [1] в метод мы объявляем MemoryStream [2], который позволяет нам динамически хранить данные, получаемые с сервера. Затем мы объявляем целое число для хранения количества прочитанных байтов и используем цикл do/ while [3], чтобы создать 2048-байтовый буфер для чтения данных. Затем мы вызываем Read() [4] в SslStream, чтобы заполнить буфер количеством байтов, прочитанных из потока, а затем копируем данные, поступающие из OpenVAS, в MemoryStream с помощью Write(), поэтому позже мы сможем проанализировать данные в XML.
Если сервер возвращает меньше данных, чем может содержать буфер, нам нужно проверить, прочитали ли мы действительный XML-документ с сервера. Для этого мы используем GetString() в блоке try/catch [5], чтобы преобразовать байты, хранящиеся в MemoryStream, в анализируемую строку и попытаться проанализировать XML, поскольку синтаксический анализ выдаст исключение, если XML недействителен. Если исключение не выброшено, мы возвращаем XML-документ. Если генерируется исключение, мы знаем, что не закончили чтение потока, поэтому вызываем continue [6], чтобы прочитать больше данных. Если мы закончим чтение байтов из потока и еще не вернули действительный XML-документ, мы возвращаем ноль. Это своего рода защита на случай, если связь с OpenVAS потеряется посередине и мы не сможем прочитать весь ответ API. Возврат значения null позволяет нам позже проверить, действителен ли ответ от OpenVAS, поскольку значение null будет возвращено только в том случае, если мы не сможем прочитать полный ответ XML.

Настройка потока TCP для отправки и получения команд


В листинге ниже показан метод GetStream(), который впервые появляется в листинге выше. Он устанавливает фактическое TCP-соединение с сервером OpenVAS, которое мы будем использовать для отправки и получения команд.

The OpenVASSession constructor’s GetStream() method

GetStream() настраивает поток TCP для использования в остальной части класса, при взаимодействии с OpenVAS. Для этого мы создаем экземпляр нового TcpClient [1] на сервере, передавая свойства ServerIPAddress и ServerPort в TcpClient, если поток недействителен. Мы оборачиваем поток в SslStream [2], который не будет проверять сертификаты SSL, поскольку сертификаты SSL являются самоподписанными и выдадут ошибку; затем мы выполняем SSL-квитирование, вызвав AuthenticateAsClient() [3]. Поток TCP на сервер OpenVAS теперь может использоваться остальными методами, когда мы начинаем отправлять команды и получать ответы.


Проверка сертификата и сбор мусора

В листинге ниже показаны методы, используемые для проверки сертификатов SSL (поскольку SSL-сертификаты, которые OpenVAS использует по умолчанию, являются самоподписанными) и очистки нашего сеанса после его завершения.

The ValidateServerCertificate() and Dispose() methods
The ValidateServerCertificate() and Dispose() methods

Возвращать true [1], как правило, является плохой практикой, но поскольку в нашем случае OpenVAS использует самозаверяющий сертификат SSL, который в противном случае не будет проверяться, мы должны разрешить все сертификаты. Как и в предыдущих примерах, мы создаем метод Dispose(), чтобы можно было выполнить очистку после работы с сетевыми или файловыми потоками. Если поток в классе OpenVASSession не равен нулю, мы удаляем внутренний поток [2], используемый для связи с OpenVAS.

Получение версии OpenVAS


Теперь мы можем управлять OpenVAS для отправки команд и получения ответов, как показано в листинге ниже. Например, мы можем запускать такие команды, как команда get_version, которая возвращает информацию о версии экземпляра OpenVAS. Позже мы добавим аналогичную функциональность в класс OpenVASManager.

The Main() method driving OpenVAS to retrieve the current version

Мы создаем новый OpenVASSession [1], передавая имя пользователя, пароль и хост. Затем мы передаем ExecuteCommand() [2] в XDocument, запрашивая версию OpenVAS, сохраняем результат в новом XDocument, а затем записываем его на экран. Вывод листинга выше должен выглядеть так же, как в листинге ниже.

На этом все. Всем хорошего дня!

Цикл статей по Gray Hat C#. Руководство для хакера по созданию и автоматизации инструментов безопасности.