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

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

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

Чтобы автоматизировать отправку команд и получение ответов от Nessus, мы создадим сеанс с классом NessusSession и выполним команды API, как показано в листинге ниже.

The beginning of the NessusSession class showing the constructor and Authenticate() method

Как Вы можете видеть в листинге выше, этот класс реализует интерфейс IDisposable [1], поэтому мы можем использовать класс NessusSession внутри оператора using. Как Вы, возможно, помните из предыдущих глав, интерфейс IDisposable позволяет нам автоматически очищать наш сеанс с Nessus путем вызова Dispose(), который мы вскоре реализуем, когда текущий экземпляр класса в инструкции using удаляется во время сборки мусора.
Кроме того [3], мы присваиваем свойству Host значение параметра хоста, переданного конструктору NessusSession [2], а затем пытаемся выполнить аутентификацию [4], поскольку для любых последующих вызовов API потребуется аутентифицированный сеанс. Если аутентификация не удалась, мы создаем исключение и печатаем предупреждение «Ошибка аутентификации». Если аутентификация прошла успешно, мы сохраняем ключ API для дальнейшего использования.
В методе Authenticate() [5] мы создаем JObject [6] для хранения учетных данных, передаваемых в качестве аргументов. Мы будем использовать их для попытки аутентификации, а затем вызовем метод MakeRequest() [7] (обсуждается далее) и передадим метод HTTP, URI целевого хоста и JObject. Если аутентификация прошла успешно, MakeRequest() должен вернуть JObject с токеном аутентификации; если аутентификация не удалась, он должен вернуть пустой JObject.
Когда мы получаем токен аутентификации, мы присваиваем его значение свойству Token [8], присваиваем свойству Authenticated значение true и возвращаем true вызывающему методу, чтобы сообщить программисту, что аутентификация прошла успешно. Если аутентификация не удалась, мы возвращаем false.

Выполнение HTTP-запросов


Метод MakeRequest() выполняет фактические HTTP-запросы, а затем возвращает ответы, как показано в листинге ниже.

 The MakeRequest() method from the NessusSession class
 The MakeRequest() method from the NessusSession class

Метод MakeRequest() имеет два обязательных параметра (HTTP и URI) и два необязательных (JObject и токен аутентификации). Значение по умолчанию для каждого равно нулю.
Чтобы создать MakeRequest(), мы сначала создаем базовый URL-адрес для вызовов API [2], объединяя параметры хоста и URI и передавая результат в качестве второго аргумента; затем мы используем HttpWebRequest для создания HTTP-запроса и устанавливаем для свойства метода HttpWebRequest [3] значение переменной метода, переданной в метод MakeRequest(). Затем мы проверяем, предоставил ли пользователь токен аутентификации в JObject. В этом случае мы присваиваем заголовку HTTP-запроса X-Cookie значение параметра [4] токена, который Nessus будет искать при аутентификации. Мы устанавливаем для свойства ContentType [5] HTTP-запроса значение application/json, чтобы гарантировать, что сервер API знает, как обращаться с данными, которые мы отправляем в теле запроса (в противном случае он откажется принять запрос).
Если JObject передается в MakeRequest() в третьем аргументе [1], мы преобразуем его в массив байтов с помощью GetBytes() [6], поскольку метод Write() может записывать только байты. Мы присваиваем свойству ContentLength размер массива, а затем используем Write() [7], чтобы записать JSON в поток запросов. Если JObject, переданный в MakeRequest(), имеет значение null, мы просто присваиваем ContentLength значение 0 и двигаемся дальше, поскольку мы не будем помещать какие-либо данные в тело запроса.
Объявив пустую строку для хранения ответа от сервера, мы начинаем блок try/catch по адресу [8], чтобы получить ответ. В инструкции using мы создаем StreamReader [9] для чтения HTTP-ответа, передавая поток HTTP-ответа сервера конструктору StreamReader; затем мы вызываем ReadToEnd(), чтобы прочитать полное тело ответа в нашу пустую строку. Если чтение ответа вызывает исключение, мы можем ожидать, что тело ответа пусто, поэтому мы перехватываем исключение и возвращаем пустой JObject в ReadToEnd(). В противном случае мы передаем ответ в Parse() [10] и возвращаем полученный JObject.


Выход из системы и очистка

Чтобы завершить работу над классом NessusSession, мы создадим LogOut() для выхода из сервера и Dispose() для реализации интерфейса IDisposable, как показано в листинге ниже.

The last two methods of the NessusSession class, as well as the Host, Authenticated, and Token properties
The last two methods of the NessusSession class, as well as the Host, Authenticated, and Token properties

Метод LogOut() [1] проверяет, прошли ли мы аутентификацию на сервере Nessus. Если да, мы вызываем MakeRequest(), передавая DELETE в качестве метода HTTP; /session как URI; и токен аутентификации, который отправляет HTTP-запрос DELETE на сервер Nessus, фактически отключая нас. После завершения запроса мы устанавливаем для свойства Authenticated значение false. Чтобы реализовать интерфейс IDisposable, мы создаем Dispose() [2] для выхода из системы, если мы прошли аутентификацию.


Тестирование класса NessusSession

Мы можем легко протестировать класс NessusSession с помощью небольшого метода Main(), как показано в листинге ниже.

Testing the NessusSession class to authenticate with NessusManager

В методе Main() [1] мы создаем новый NessusSession [3] и передаем IP-адрес хоста Nessus, имя пользователя и пароль Nessus в качестве аргументов. В сеансе с аутентификацией мы печатаем токен аутентификации [4], который Nessus предоставил нам при успешной аутентификации, а затем выходим.


Примечание
NessusSession создается в контексте оператора using [2], поэтому метод Dispose(), который мы реализовали в классе NessusSession, будет автоматически вызываться по завершении блока using. Это приведет к выходу из сеанса NessusSession, что сделает недействительным токен аутентификации, который нам предоставил Nessus.


Запуск этого кода должен вывести токен аутентификации, аналогичный показанному в листинге ниже.

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

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