Расширенная защита HTTP POST?

Я застрял здесь около 24 часов по проблеме, с которой я не могу опустить голову.

Страховая компания, в которой я работаю, полагается на запрос данных котировок с нескольких веб-сайтов, некоторые для анализа, некоторые для котировок для клиентов. Я создаю класс для программного обеспечения, которое я разработал, чтобы добавить нового поставщика страхования к нашим нынешним провайдерам.

Я в основном отправляю запрос POST с информацией о клиентах и ​​наш реферал. Но для жизни я не могу заставить это работать. Я делал это сотни раз без проблем.

Я контролировал заголовки в Fiddler и полностью копировал их. Единственное, что, по-видимому, делает сайт, - это 4 значения cookie. Один из них - xsrf (который автоматически устанавливается при посещении страницы представления, я могу получить это из исходного кода или путем доступа к CookieContainer), другие 2, похоже, связаны с сеансом, но зашифрованы. Итак, что я делаю, это заставить мое программное обеспечение посещать страницу, файлы cookie сохраняются, а затем отправлять запрос на отправку.

Я пробовал отправить форму вручную с отключенным JavaScript. И это работает. Поэтому я могу предположить, что с JavaScript не установлены никакие переменные или файлы cookie.

Я не могу понять, почему форма не отправляется.

Единственное, о чем я могу думать, это данные сеанса в файлах cookie зашифрованы и хранятся некоторые значения, предоставляемые браузером. Но без JavaScript какие значения могут предоставить браузер, чтобы мое программное обеспечение не было?

Я установил весь обычный User-Agent и т.д. Как я уже сказал, я делал это сотни раз и никогда не сталкивался с такой проблемой.

Я также использовал Fiddler для получения информации о файлах cookie и поместил их непосредственно в программное обеспечение (используя тот же браузер, что и агент пользователя, установленный на программном обеспечении), что теоретически должно работать, но это не так.

Я сравнил мой запрос POST с запросом POST из браузера, бок о бок, и они оба идентичны. Единственное, что отличается, - это значения cookie сеанса, которые зашифрованы.

С веб-сервера не возвращается ошибка. Код ответа - 200. Единственная разница заключается в том, когда цитата успешно отправлена, страница будет включать текст "Котировка успешная". Который я не могу достичь с помощью программного обеспечения.

Я позвонил страховому провайдеру, который не может помочь, так как они не управляют своим сайтом. У них нет API, но они позволяют нашей компании делать запросы через программное обеспечение, пока мы предоставляем идентификатор реферала.

Любые идеи о том, что здесь может происходить?

Для записи я использую С# и HTTPClient. Я не уверен, что это важно.

Edit:

Одна вещь, которую я заметил, это то, что после запроса GET на страницу, содержащую форму цитаты - с помощью браузера - я замечаю, что с сервера возвращается следующий заголовок:

 P3P: CP="CAO PSA OUR"

Кроме того, когда запрос POST успешно отправлен в браузере, он также возвращает этот заголовок.

Но когда я выдаю запрос GET с помощью программного обеспечения, я замечаю, что сервер отвечает заголовком P3P, но на запрос POST нет. Может ли это быть релевантным/значительным?

Ответ 1

Возможно, вы опережаете меня, и это кажется довольно неожиданным, но возможно ли, что они используют какую-то временную или условно-временную защиту? Например:

  • Вы должны запросить страницу X и Y перед отправкой формы (зашифрованные файлы cookie могут включать в себя предварительно запрошенные URI или результирующее состояние сеанса с сервера)

  • Вы должны запросить X-страницу за несколько секунд до отправки POST формы (зашифрованные файлы cookie могут включать эту дату/время)

  • Вы НЕ ДОЛЖНЫ ПОЛУЧИТЬ эту форму раньше/в течение определенного периода времени, с/с cookie файлов, которые были скорректированы соответственно.

Возможно, какой-то программист пытался сорвать автоматическое подчинение или закрыть вектор гитлексической атаки.

Я не уверен, что вы уже это сделали, но, возможно, стоит попробовать очистить сайт от его первой страницы (или как можно ближе к отправке формы для работы вручную) с явным cookie файлом и кеш и просмотр трафика HTTP-запроса/ответа с самого начала, чтобы увидеть:

  • Точно, какие заголовки браузера отправляются с каждым запросом.
  • В каком ответе содержатся файлы cookie, о которых идет речь (и в чем заключался этот запрос)

Для этого я, вероятно, проповедую хор, но в браузере Chrome вы можете очистить файлы cookie, открыть пустую вкладку, нажать F12 для инструментов dev, ввести URL-адрес, а затем через окно F12'd, выбрать Сеть, и вы увидите список всех пар запросов/ответов. Нажмите любой из них и посмотрите на исходный текст запроса и ответа, и найдите вкладку "Куки", которая позволяет просматривать файлы cookie как отправленные, так и полученные, чтобы вы могли видеть, какой запрос дал куки. Возможно, посещение этой страницы обязательно/отслеживается.

(Googling предполагает, что заголовок P3P является электронным выражением о конфиденциальности и поэтому вряд ли будет связан.)

Ответ 2

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

  • Откройте новую форму окна и поместите на нее элемент управления веб-браузером.
  • Перейдите на страницу формы, с которой вы столкнулись.
  • Используйте свойство Document для заполнения формы. Что-то вроде этого должно делать.

    webBrowser1.Document.GetElementById("QuoteID").SetAttribute(
        "value", 
        "100"
    );    
    
    etc...
    
  • Отправьте форму и посмотрите, что произойдет.

        foreach (HtmlElement f in webBrowser1.Document.Forms)
            f.InvokeMember("submit");
    

Или, если вы знаете идентификатор кнопки формы:

        HtmlElement form = webBrowser1.Document.GetElementById("FormID");

        if (form != null)
            form.InvokeMember("submit");

Если это сработает, то в худшем случае вам придется использовать тяжелый контроль только для одного веб-сайта freakin в вашем приложении. Но, с другой стороны, по крайней мере, у вас будет одно потенциальное решение проблемы. BTW... Если это будет так, я бы отвлек его в своей сборке и попытался сделать код вызова похожим на существующую базу кода. Таким образом, вы просто улучшаете свое приложение, добавив новую возможность подключения к сети:).

Я также попытался бы использовать класс WebClient вместо HTTPClient и посмотреть, ведут ли они себя по-другому..

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

Я попытался бы удалить кеш cookie прямо перед использованием HTTPClient и убедиться, что он получает его собственный идентификатор сеанса.

Посмотрим.. это неясно.. есть ли какая-либо возможность, что одно из полей, которые вы отправляете программно, имеет апостроф в поле или любые символы, которые могут вызвать проблему для серверного приложения?

Я попытался бы хотя бы получить помощь от страховой компании. Они не могут контролировать веб-приложение, но они могут подтвердить, взяли ли они ваши тесты. Возможно, форма отправляется, и ошибка возникает после этого. Возможно ли, что проблема связана с перенаправлением, которое HTTPClient не нравится. Например, может ли этот элемент управления обработать его, если после отправки формы он перенаправляется на защищенный сайт, прежде чем перенаправляется на страницу защищенного ответа?

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

Что касается шифрования, файлы cookie могут быть зашифрованы или, чаще всего, они кодируются только base64. В любом случае клиент обычно смотрит только на поля, которые он создал или запросил. В противном случае он просто передает информацию на сервер. Таким образом, это не кажется мне вероятным виновником. Я не говорю, что это определенно не так. Но я тоже буду искать в другом месте.

Я знаю, что некоторые из них могут быть глупыми, но когда вы застреваете, вы должны все это выпустить. Теория перенаправления кажется интересной, поскольку она может объяснить, почему это единственный раз, когда вы столкнулись с этой проблемой. Может быть, это на их конце. Они беспокоятся о безопасности и продажах, а не о том, что вы делаете. Итак, вы просто не знаете.

Во всяком случае, все, что я получил сейчас. Я действительно надеюсь, что вы найдете проблему. Дайте мне знать, как все получается. Будьте осторожны.

Обновление

Я снова посмотрел на ваш вопрос, чтобы узнать, могу ли я подумать о чем-нибудь еще, и я подумал. Является ли страница подтверждения страницей фреймов или является результатом, который вы ищете внутри iframe?

Просто пища для размышлений.

Ответ 3

Поскольку у вас есть файл cookie с именем xsrf, я бы предположил, что это cookie для защиты CSRF.

Если вы посмотрите на ответ от запроса GET, созданного вашим программным обеспечением, есть ли скрытое поле, содержащее токен?

например. <input type="hidden" name="xsrfToken" value="123456" />

Когда ваше программное обеспечение делает POST, может быть, что значение этого скрытого поля опущено или установлено на неправильное значение. Возможно, это должно совпадать с динамическим значением, полученным в запросе GET, для проверки защиты CSRF. Обычно это значение будет таким же, как cookie (xsrf cookie в этом случае), или оно будет содержать закодированную или зашифрованную версию (или, возможно, файл cookie будет закодированной зашифрованной версией скрытого поля).

Ответ 4

С веб-сервера не возвращается ошибка. Код ответа - 200. Единственная разница заключается в том, когда цитата успешно отправлена, страница будет включать текст "Котировка успешная". Который я не могу достичь с помощью программного обеспечения.

Так как вы ищете текст: "Quotation Successful" на веб-странице, убедитесь, что этот текст не динамически загружается на страницу. Это угловой случай (как и ваша проблема:)), но возможно, что страница отправляет некоторые запросы AJAX на сервер после загрузки DOM или какое-то другое событие и получает этот фрагмент текста. Что может быть метрикой, чтобы определить, работает ли ваше программное обеспечение нормально или нет, это сравнить исходный код (HTML через view-source/ Ctrl + U), возвращающий нормальную форму-представление, и что ваше программное обеспечение возвращение.

Ответ 5

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

Ожидаемый процесс отправки может быть примерно таким:

  • ПОЛУЧИТЕ страницу отправки и сохраните файлы cookie, установленные сервером.
  • Получите тег пикселя безопасности с сервера с правильными заголовками, чтобы проверить серверную сторону сеанса
  • НАЧАТЬ значения формы с правильными заголовками

Использование тегов пикселей, таких как это довольно простой и эффективный метод защиты от спама, поскольку несколько ботов беспокоятся о загрузке ресурсов страницы.

Ответ 6

Это ответ на манжета, основанный на очень близком мне опыте. В конце концов, после нескольких попыток получить согласованность между запросами, которые я отправлял на разные установки одной и той же конечной точки, это оказалось отсутствующим или неправильно установленным заголовком Content-Length, который ожидал сервер. Различные серверы, которые я отправлял, были настроены несколько иначе.

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

Я говорю проверку и двойную проверку правильности заголовков HTTP.