Fuzzer, Gray Hat C#, Программирование, Фаззинг

#22 Gray Hat C#. Руководство для хакера по созданию и автоматизации инструментов безопасности. Фаззинг порта HTTP POST SOAP.

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

Фаззинг порта HTTP POST SOAP для данного сервиса SOAP, очень похож на фаззинг порта GET SOAP. Единственное отличие состоит в том, что данные отправляются как параметры HTTP POST, а не как параметры строки запроса. При передаче SoapBinding для порта HTTP POST в метод FuzzHttpPostPort() нам необходимо перебирать каждую операцию и систематически искажать значения, отправляемые операциям, чтобы вызвать ошибки SQL с веб-сервера. В листинге ниже показана первая половина метода FuzzHttpPostPort().

Determining the operation and parameters to fuzz within the FuzzHttpPostPort() method
Determining the operation and parameters to fuzz within the FuzzHttpPostPort() method

Сначала мы выбираем SoapPortType [1], который соответствует SoapBinding, переданному методу. Затем мы перебираем каждую операцию SoapBindingOperation, чтобы определить текущую SoapBinding, используя цикл foreach. Во время итерации мы печатаем сообщение, в котором указывается, какую операцию мы в данный момент подвергаем фаззингу, а затем создаем URL-адрес для отправки данных. Мы также выбираем соответствующую SoapOperation [2] для переменной portType, чтобы мы могли найти нужное нам SoapMessage, содержащее HTTP-параметры, которые нам нужно отправить на веб-сервер. Как только у нас будет вся информация, необходимая для создания и выполнения корректных запросов к службе SOAP, мы создаем небольшой словарь [3], содержащий имена параметров и их типы, которые будут обрабатываться позже.
Теперь мы можем создать параметры HTTP, которые будем отправлять в службу SOAP, как показано в листинге ниже. Продолжайте вводить этот код в метод FuzzHttpPostPort().

Building the POST parameters to be sent to the POST HTTP SOAP port

Теперь у нас есть все данные, необходимые для построения POST-запросов. Мы объявляем строку для хранения параметров POST, и объявляем логическое значение, которое будет определять, будет ли параметр иметь префикс амперсанда для определения параметров POST. Мы также объявляем список Guid, чтобы мы могли хранить значения, которые мы добавляем к параметрам HTTP, для дальнейшего использования в методе.
Теперь мы можем перебрать каждый из параметров HTTP, используя цикл foreach, и построить строку параметров, которую мы отправим в теле запроса POST. Во время итерации сначала мы проверяем, заканчивается ли тип параметра строкой [1]. Если да, мы создаем строку для значения параметра. Чтобы отслеживать, какие строковые значения мы используем, и гарантировать уникальность каждого значения, мы создаем новый Guid и используем его в качестве значения параметра. Используя тернарную операцию [2], мы определяем, следует ли ставить перед параметром амперсанд. Затем мы сохраняем Guid в списке Guid. После того как мы добавили параметр и значение в строку параметров POST, мы проверяем логическое значение и, если оно истинно, устанавливаем для него значение false [3], чтобы последующие параметры POST обозначались амперсандом.
Далее нам нужно отправить параметры POST на сервер, а затем прочитать ответ и проверить наличие ошибок, как показано в листинге ниже.

Sending the POST parameters to the SOAP service and checking for server errors

Для начала мы объявляем целое число с именем k, которое будет увеличиваться и использоваться во время фаззинга для отслеживания потенциально уязвимых параметров, и присваиваем k значение 0. Затем мы перебираем список Guid, используя цикл foreach. Во время итерации первое, что мы делаем, — это создаем новую строку параметра POST, заменяя текущий Guid испорченным значением с помощью метода replace() [1]. Поскольку каждый Guid уникален, при замене Guid изменится только значение одного параметра. Это позволяет нам точно определить, какой параметр имеет потенциальную уязвимость. Далее мы отправляем запрос POST и читаем ответ.
Получив новую строку параметра POST для отправки в службу SOAP, мы преобразуем эту строку в массив байтов с помощью метода GetBytes(), который будет записан в поток HTTP. Затем мы создаем HttpWebRequest [2], для отправки байтов на сервер и устанавливаем для свойства Method HttpWebRequest значение «POST», для свойства ContentType — application/x-www-form-urlencoded, и
свойство ContentLength к размеру массива байтов. После его построения мы записываем массив байтов в поток запросов, передавая массив байтов, индекс массива, с которого начинается запись (0), и количество байтов для записи методу Write() [3].
После того, как параметры POST были записаны в поток запроса, нам нужно прочитать ответ от сервера. После объявления пустой строки для хранения ответа HTTP мы используем блок try/catch для перехвата любых исключений, возникающих при чтении из потока ответов HTTP. Создавая StreamReader в контексте оператора using, мы пытаемся прочитать весь ответ с помощью метода ReadToEnd() [4] и присвоить ответ пустой строке. Если сервер отвечает HTTP-кодом 50x (что означает, что на стороне сервера произошла ошибка), мы перехватываем исключение, пытаемся прочитать ответ еще раз и переназначаем строку ответа на пустую строку, чтобы обновить ее. Если ответ содержит синтаксическую ошибку [5] фразы, мы печатаем сообщение, предупреждающее пользователя о том, что текущий параметр HTTP может быть уязвим для SQL-инъекции. Чтобы определить, какой параметр был уязвим, мы используем целое число k в качестве индекса списка параметров, чтобы получить имя текущего параметра. Наконец, мы увеличиваем целое число k на 1, чтобы на следующий параметр можно было ссылаться в следующей итерации, а затем начинаем процесс заново для следующего параметра POST.
На этом работа методов FuzzHttpGetPort() и FuzzHttpPostPort() завершена. Далее мы напишем метод FuzzSoapPort() для фаззинга порта XML SOAP.

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

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