#22 Gray Hat C#. Руководство для хакера по созданию и автоматизации инструментов безопасности. Фаззинг порта HTTP POST SOAP.
Здравствуйте, дорогие друзья.
Фаззинг порта HTTP POST SOAP для данного сервиса SOAP, очень похож на фаззинг порта GET SOAP. Единственное отличие состоит в том, что данные отправляются как параметры HTTP POST, а не как параметры строки запроса. При передаче SoapBinding для порта HTTP POST в метод FuzzHttpPostPort() нам необходимо перебирать каждую операцию и систематически искажать значения, отправляемые операциям, чтобы вызвать ошибки SQL с веб-сервера. В листинге ниже показана первая половина метода FuzzHttpPostPort().
Сначала мы выбираем SoapPortType [1], который соответствует SoapBinding, переданному методу. Затем мы перебираем каждую операцию SoapBindingOperation, чтобы определить текущую SoapBinding, используя цикл foreach. Во время итерации мы печатаем сообщение, в котором указывается, какую операцию мы в данный момент подвергаем фаззингу, а затем создаем URL-адрес для отправки данных. Мы также выбираем соответствующую SoapOperation [2] для переменной portType, чтобы мы могли найти нужное нам SoapMessage, содержащее HTTP-параметры, которые нам нужно отправить на веб-сервер. Как только у нас будет вся информация, необходимая для создания и выполнения корректных запросов к службе SOAP, мы создаем небольшой словарь [3], содержащий имена параметров и их типы, которые будут обрабатываться позже.
Теперь мы можем создать параметры HTTP, которые будем отправлять в службу SOAP, как показано в листинге ниже. Продолжайте вводить этот код в метод FuzzHttpPostPort().
Теперь у нас есть все данные, необходимые для построения POST-запросов. Мы объявляем строку для хранения параметров POST, и объявляем логическое значение, которое будет определять, будет ли параметр иметь префикс амперсанда для определения параметров POST. Мы также объявляем список Guid, чтобы мы могли хранить значения, которые мы добавляем к параметрам HTTP, для дальнейшего использования в методе.
Теперь мы можем перебрать каждый из параметров HTTP, используя цикл foreach, и построить строку параметров, которую мы отправим в теле запроса POST. Во время итерации сначала мы проверяем, заканчивается ли тип параметра строкой [1]. Если да, мы создаем строку для значения параметра. Чтобы отслеживать, какие строковые значения мы используем, и гарантировать уникальность каждого значения, мы создаем новый Guid и используем его в качестве значения параметра. Используя тернарную операцию [2], мы определяем, следует ли ставить перед параметром амперсанд. Затем мы сохраняем Guid в списке Guid. После того как мы добавили параметр и значение в строку параметров POST, мы проверяем логическое значение и, если оно истинно, устанавливаем для него значение false [3], чтобы последующие параметры POST обозначались амперсандом.
Далее нам нужно отправить параметры POST на сервер, а затем прочитать ответ и проверить наличие ошибок, как показано в листинге ниже.
Для начала мы объявляем целое число с именем 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.
На этом все. Всем хорошего дня!