【问题标题】:Advanced HTTP POST Protection?高级 HTTP POST 保护?
【发布时间】:2014-01-16 16:06:00
【问题描述】:

我已经被困在这里大约 24 小时了,我无法解决这个问题。

我工作的保险公司依赖于从多个网站请求报价数据,一些用于分析,一些用于向客户报价。我正在为我开发的软件创建一个类,以便将新的保险提供商添加到我们当前的提供商中。

我基本上发送一个带有客户信息和我们推荐的 POST 请求。但是对于我的生活,我无法让它发挥作用。我已经这样做了数百次,没有任何问题。

我在 Fiddler 中监控了标头,并完全复制了它们。该网站似乎唯一设置的是 4 个 cookie 值。一个是 xsrf(当您访问提交页面时自动设置,我可以从源代码中检索它,或者通过访问 CookieContainer),另外两个似乎与会话相关,但已加密。所以我要做的是让我的软件访问页面,存储 cookie,然后提交发布请求。

我尝试在禁用 JavaScript 的情况下手动提交表单。它有效。所以我可以假设 JavaScript 没有设置变量或 cookie。

我不明白为什么没有提交表单。

我唯一能想到的是 cookie 中的会话数据是加密的,并存储了浏览器提供的一些值。但是如果没有 JavaScript,浏览器可以提供哪些值而我的软件没有?

我已经设置了所有常用的 User-Agent 等。正如我所说,我已经这样做了数百次,从未遇到过这样的问题。

我还使用 Fiddler 获取 cookie 信息,并将其直接放入软件中(使用与软件上设置的用户代理相同的浏览器),理论上应该可以工作,但事实并非如此。

我将我的 POST 请求与来自浏览器的 POST 请求并排比较,它们是相同的。唯一不同的是会话 cookie 值,它们是加密的。

Web 服务器没有返回错误。响应码为 200。唯一的区别是报价成功提交后,页面将包含“报价成功”文本。这是我无法使用该软件实现的。

我已致电无法提供帮助的保险提供商,因为他们不管理自己的网站。他们没有 API,但允许我们公司通过软件提出请求,只要我们提供推荐 ID。

关于这里可能发生什么的任何想法?

作为记录,我正在使用 C# 和 HTTPClient。我不确定这是否相关。

编辑:

我注意到的一件事是,在对包含报价单的页面发出 GET 请求时 - 使用浏览器 - 我注意到服务器返回了以下标头:

 P3P: CP="CAO PSA OUR"

此外,当 POST 请求在浏览器中成功发送时,它也会返回此标头。

但是,当我使用软件发出 GET 请求时,我注意到服务器使用 P3P 标头进行响应,但在 POST 请求上却没有。这可能是相关/重要的吗?

【问题讨论】:

  • cookies/token 只能使用一次。
  • @SLaks 我访问了包含提交表单的页面。 cookie/令牌在那里设置,然后我提交数据。我每个请求只使用一次。每次访问带有提交表单的页面时,都会按预期提供新的 cookie/令牌。我不想重复使用 cookie/令牌。
  • 在发布 check fiddler 时,是否使用了全部 4 个 cookie?
  • @AydinAdn 在 Fiddler 中所有 4 都显示为已使用。虽然当我在 FireFox 中使用 LiveHTTPHeaders 重播请求时,我可以删除其中的 2 个。会话在第一次请求后仅持续约 20 秒,因此很难测试。真正困扰我的是我的软件请求与浏览器请求相同,我不明白为什么它不起作用。我感觉这与我在上面发布的 P3P 内容有关,或者网站从浏览器获取某些内容并将其存储在加密的 cookie 中。
  • 尝试使用wire-shark 看看到底传递了什么。

标签: c# http automation bots


【解决方案1】:

您可能领先于我,这似乎很离谱,但他们是否有可能使用某种形式的临时或请求条件保护?例如:

  • 您必须在 POST 表单之前请求 X 页和 Y 页(加密的 cookie 可能包括先前请求的 URI,或来自服务器的生成会话状态)

  • 您必须在 POST 表单之前请求 X 页 Y n 秒(加密的 cookie 可能包括该日期/时间)

  • 您之前/在特定时间范围内不得发布此表单,相应地调整/不调整 cookie

也许某些程序员正试图阻止自动提交或关闭假设的攻击向量。

我不确定您是否已经这样做了,但可能值得尝试使用清晰的 cookie 从其首页(或尽可能接近手动提交表单)进行干净的站点访问并从一开始就缓存和观察 HTTP 请求/响应流量,以查看:

  • 浏览器随每个请求发送的具体标头
  • 哪个响应包含有问题的 cookie(以及该请求包含什么)

为此,我可能是在向合唱团布道,但使用 Chrome 浏览器,您可以清除 cookie、打开一个空白选项卡、按 F12 获取开发工具、输入 URL,然后通过 F12 窗口选择网络,您将看到所有请求/响应对的列表。单击任何一个并查看请求和响应源文本,然后查找 Cookies 选项卡,该选项卡可让您查看发送的 cookie 和接收的 cookie - 这样您就可以看到哪个请求产生了 cookie。也许对该页面的访问是强制性的/被跟踪的。

(谷歌搜索表明 P3P 标头 is an electronic privacy statement 不太可能相关。)

【讨论】:

  • 不,这很有趣。这是我发布问题时希望获得的回复类型。我知道很多网站都在做类似的事情,但我没有尝试过。
  • 在一家保险公司工作了多年,他们会竭尽全力(或要求他们的科技公司)阻止这种做法,这并不让我感到惊讶。基本上,许多保险公司希望保护他们的在线报价系统免受未经授权的报价比较聚合器网站的影响,并且会提出一些非常强大的技术,比如这个答案中提到的那些。我知道 OP 已经提到公司已授权他这样做,但开发人员可能在设计时有不同的简介。
【解决方案2】:

如果我遇到你的情况,我会尝试做一些事情来获取更多信息来解决问题。以下是我脑海中的一些想法。

  1. 打开一个新的 windows 窗体并在其上放置一个 webbrowser 控件。
  2. 导航到您遇到问题的表单页面。
  3. 使用 Document 属性填写表单。应该这样做。

    webBrowser1.Document.GetElementById("QuoteID").SetAttribute(
        "value", 
        "100"
    );    
    
    etc...
    
  4. 提交表格,看看会发生什么。

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

或者,如果您知道表单按钮的 ID:

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

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

如果它有效,那么最坏的情况是您最终不得不为您的应用程序中的一个该死的网站使用重量级控件。但是,从好的方面来说,至少你会有一个潜在的解决方案。顺便说一句......如果最终是这样,我会将它抽象到它自己的程序集中,并尝试使调用代码类似于现有的代码库。这样,您只需通过添加新的网络连接选项来增强您的应用程序:)。

我也会尝试使用WebClient 类而不是HTTPClient,看看它们的行为是否不同..

我可能会尝试将用户代理设置为每个主要浏览器,以确认结果。

我会在使用 HTTPClient 之前尝试删除 cookie 缓存并验证它是否正在获取它自己的会话 ID。

让我们看看..这很模糊..您以编程方式发送的某个字段是否有可能在字段中包含撇号,或者任何可能导致服务器应用出现问题的字符?

我至少会尝试从保险公司获得帮助。他们可能无法控制 Web 应用程序,但他们可能能够确认他们是否已捕获您的测试。也许表单正在提交,然后错误发生。问题是否可能与 HTTPClient 不喜欢的重定向有关。例如,如果在提交表单后将其重定向到安全站点,然后再重定向到不安全的回复页面,控件是否可以处理它?

如果可能,您是否可以在某个地方设置一个虚拟页面来接受您的表单数据并将其打印在屏幕上,以便您可以准确地查看服务器上的内容?

至于加密,cookie 可以是加密的,或者通常只是 base64 编码。无论哪种方式,客户端通常只查看它创建或请求的字段。否则,它只是将信息传递给服务器。所以,对我来说,这似乎不是罪魁祸首。我不是说绝对不是。但是,我也会继续寻找其他地方。

我知道其中一些可能很愚蠢,但是当您遇到困难时,您必须排除一切。重定向理论似乎很有趣,因为它可以解释为什么这是你唯一一次遇到这个问题。也许是在他们的尽头。他们担心的是安全和销售,而不是你在做什么。所以,你永远不知道。

无论如何,这就是我现在所得到的。我真的希望你能找到问题。让我知道结果如何。保重。

更新

我再次浏览了您的问题,看看我是否能想到其他任何事情,我有一个想法。确认页面是框架页面还是您在 iframe 中寻找的结果?

只是思考的食物。

【讨论】:

  • 谢谢老兄,这里有很多很棒的信息。明天会经历一些。
【解决方案3】:

既然你有一个名为 xsrf 的 cookie,我猜这是一个用于 CSRF 保护的 cookie。

如果您查看来自您的软件发出的GET 请求的响应,是否有一个包含令牌的隐藏字段?

例如<input type="hidden" name="xsrfToken" value="123456" />

当您的软件进行 POST 时,可能是该隐藏字段的值被省略或设置为不正确的值。它可能需要与在 GET 请求中检索到的动态值相同,以验证 CSRF 保护。通常这个值与 cookie 相同(在这种情况下为xsrf cookie),或者它将包含它的编码或加密版本(或者可能 cookie 将是隐藏字段的编码加密版本)。

【讨论】:

  • 似乎是罪魁祸首。
  • @SilverlightFox - xsrf +1。我什至都没有意识到这一点。一定是“对互联网安全的浓厚兴趣”在谈论':) 很好的答案。
  • “一个是 xsrf(当您访问提交页面时会自动设置,我可以从源代码中检索它”......我已经这样做了,正如我在我的问题。
  • @JamesJeffery:你在谈论 cookie。我说的是表单中的 CSRF 令牌。如果您监控您的请求,您是否也在 cookie 机制之外发送有效的 CSRF 令牌
  • 我不是在谈论 cookie,我的意思是在 cookie 和 HTML 的隐藏字段中都设置了 xrfs 令牌。对困惑感到抱歉。但是,是的,我确实检查了这一点。它似乎是通过 cookie 而不是在 POST 请求中传递它。我工作的公司仍在等待他们的“技术”团队回复我们。
【解决方案4】:

Web 服务器没有返回错误。响应码为 200。唯一的区别是报价成功提交后,页面将包含“报价成功”文本。这是我无法通过该软件实现的。

既然您在网页中寻找文本:“报价成功”,那么请确保该文本不是在页面中动态加载的。这是一个极端情况(就像你的问题:))但是在 DOM 加载或其他事件之后页面可能会向服务器发送一些 AJAX 请求并且正在获取这段文本。确定您的软件是否工作正常的指标可能是比较正常的源代码(通过 view-source/Ctrl+U 的 HTML)表单提交正在返回以及您的软件正在返回什么。

【讨论】:

  • 他写道:“我尝试在禁用 JavaScript 的情况下手动提交表单。它可以工作。”
【解决方案5】:

如果您生成的请求与浏览器请求完全相同但仍然失败,我会调查提交页面加载的资源,它可能包含用作服务器端会话验证标记的像素标记。

预期的提交过程可能是这样的:

  • 获取提交页面并存储服务器设置的cookies
  • 从服务器获取带有正确标头的安全像素标签,以验证会话服务器端
  • POST 带有正确标题的表单值

使用像这样的像素标签是一种非常简单有效的反垃圾邮件技术,因为很少有机器人会费心去下载页面资源。

【讨论】:

    【解决方案6】:

    根据我最近的一次非常相似的经历,这是一个即兴的反应。最后,经过几天尝试使我发送到同一端点的各种安装的请求保持一致后,它发现是服务器期望的丢失或错误设置的 Content-Length 标头。我发送到的不同服务器的配置略有不同。

    基本上,我手动更改了我正在测试的一两个请求的内容,要么未能更新 Content-Length 属性,要么完全错过了请求。

    我说检查并仔细检查您的 HTTP 标头是否正确。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-03-16
      • 2011-09-04
      • 1970-01-01
      • 2013-12-17
      • 1970-01-01
      • 2019-12-27
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多