当比较HTTP GET和HTTP POST时,从安全角度看有什么不同?其中一个选择是否天生就比另一个更安全?如果有,为什么?

我意识到POST没有公开URL上的信息,但其中有任何真正的价值吗?或者它只是通过隐匿性来实现安全?当安全性是一个问题时,我是否有理由更喜欢POST ?

编辑: 通过HTTPS, POST数据被编码,但url会被第三方嗅探吗?此外,我正在处理JSP;当使用JSP或类似的框架时,是否可以公平地说,最佳实践是避免将敏感数据完全放在POST或GET中,而是使用服务器端代码来处理敏感信息?


当前回答

最近发布了一种攻击,它允许中间人泄露压缩HTTPS请求的请求体。由于请求头和URL没有被HTTP压缩,GET请求可以更好地防止这种特定的攻击。

在某些模式下,GET请求也容易受到攻击,SPDY压缩请求头,TLS也提供可选的(很少使用)压缩。在这些情况下,攻击更容易预防(浏览器供应商已经提供了修复程序)。HTTP级别的压缩是一个更基本的特性,供应商不太可能禁用它。

这只是一个示例,展示了GET比POST更安全的场景,但从这种攻击原因来看,我不认为选择GET而不是POST是一个好主意。这种攻击相当复杂,需要非常重要的先决条件(攻击者需要能够控制部分请求内容)。在攻击可能有害的情况下,最好禁用HTTP压缩。

其他回答

考虑一下这种情况:一个草率的API接受如下GET请求:

http://www.example.com/api?apikey=abcdef123456&action=deleteCategory&id=1

在某些设置中,当您请求此URL时,如果有关于请求的错误/警告,则整行内容将记录在日志文件中。更糟糕的是:如果您忘记禁用生产服务器中的错误消息,则此信息将在浏览器中显示!现在你已经把你的API密钥给了所有人。

不幸的是,有一些真正的API是这样工作的。

我不喜欢在日志中有一些敏感信息或在浏览器中显示它们的想法。POST和GET是不同的。在适当的地方使用它们。

Post与安装SSL一起是最安全的,因为它在消息体中传输。

但所有这些方法都是不安全的,因为它下面使用的7位协议可以通过擒纵被破解。即使是通过四级网络应用防火墙。

套接字也不能保证…尽管它在某些方面更安全。

POST在安全性方面较差的一个原因是GET在默认情况下被记录,参数和所有数据几乎都被你的web服务器记录。

POST则相反,它几乎没有被记录,导致很难发现攻击者的活动。

我不相信“它太大了”的说法,这不是不记录任何东西的理由,至少1KB,这对人们识别攻击者很有帮助,直到它出现,然后POST做了双重破坏服务,通过启用任何基于HTTP的后门来无声地传递无限数量的数据。

就安全性而言,它们本质上是相同的。虽然POST确实不通过URL公开信息,但它在客户机和服务器之间的实际网络通信中公开的信息与GET一样多。如果需要传递敏感信息,那么第一道防线就是使用Secure HTTP传递。

GET或查询字符串帖子对于标记特定项目或协助搜索引擎优化和索引项目所需的信息非常有用。

POST适用于用于提交一次性数据的标准表单。我不会使用GET来发布实际的表单,除非在搜索表单中,您希望允许用户将查询保存在书签中,或者类似的东西。

GET请求的安全性略低于POST请求。两者本身都不能提供真正的“安全”;使用POST请求并不能神奇地使你的网站免受恶意攻击。但是,使用GET请求会使原本安全的应用程序变得不安全。

“不能使用GET请求进行更改”的咒语仍然非常有效,但这与恶意行为没有多大关系。登录表单对于使用错误的请求类型发送最为敏感。

搜索蜘蛛和网络加速器

这就是应该使用POST请求来更改数据的真正原因。搜索蜘蛛会跟踪你网站上的每个链接,但不会提交他们找到的随机表单。

Web加速器比搜索蜘蛛更糟糕,因为它们运行在客户端机器上,并且“点击”登录用户上下文中的所有链接。因此,使用GET请求删除内容的应用程序,即使它需要管理员,也会很高兴地服从(非恶意的!)web加速器的命令,删除它看到的所有内容。

混淆副攻

不管使用GET请求还是POST请求,都可能出现混淆代理攻击(代理是浏览器)。

在攻击者控制的网站上,GET和POST同样容易提交,无需用户交互。

POST不太容易受到影响的唯一情况是,许多不受攻击者控制的网站(比如第三方论坛)允许嵌入任意图像(允许攻击者注入任意GET请求),但阻止所有方式注入任意POST请求,无论是自动还是手动。

有人可能会说,网络加速器是混淆代理攻击的一个例子,但这只是一个定义的问题。如果有的话,恶意攻击者无法控制这一点,所以即使副手感到困惑,这也很难说是攻击。

代理日志

代理服务器可能会完整地记录GET url,而不剥离查询字符串。POST请求参数通常不会被记录。在这两种情况下,cookie都不太可能被记录。(例子)

这是支持POST的一个非常薄弱的论点。首先,未加密的流量可以被完整地记录;恶意代理已经拥有了它所需要的一切。其次,请求参数对攻击者的用处有限:他们真正需要的是cookie,所以如果他们唯一拥有的是代理日志,他们就不太可能攻击GET或POST URL。

登录请求有一个例外:这些请求往往包含用户的密码。将此保存在代理日志中会打开一个在POST情况下不存在的攻击向量。然而,通过纯HTTP登录本身就是不安全的。

代理缓存

缓存代理可能会保留GET响应,但不会保留POST响应。话虽如此,GET响应可以变得不可缓存,而不是将URL转换为POST处理程序。

HTTP“推荐人”

如果用户从响应GET请求的页面导航到第三方网站,该第三方网站将看到所有GET请求参数。

属于“向第三方透露请求参数”的类别,其严重性取决于这些参数中包含的内容。POST请求自然不受此影响,但是要利用GET请求,黑客需要在服务器的响应中插入到他们自己网站的链接。

浏览器历史记录

这与“代理日志”参数非常相似:GET请求连同它们的参数一起存储在浏览器历史记录中。如果攻击者有物理访问机器的权限,他们可以很容易地获得这些信息。

浏览器刷新动作

一旦用户点击“刷新”,浏览器就会重新尝试GET请求。它可能在关闭后恢复选项卡时这样做。因此,任何行为(比如付款)都会在没有任何警告的情况下重复发生。

浏览器不会在没有警告的情况下重试POST请求。

这是只使用POST请求来更改数据的一个很好的理由,但与恶意行为无关,因此与安全性无关。

那我该怎么办呢?

Use only POST requests to change data, mainly for non-security-related reasons. Use only POST requests for login forms; doing otherwise introduces attack vectors. If your site performs sensitive operations, you really need someone who knows what they’re doing, because this can’t be covered in a single answer. You need to use HTTPS, HSTS, CSP, mitigate SQL injection, script injection (XSS), CSRF, and a gazillion of other things that may be specific to your platform (like the mass assignment vulnerability in various frameworks: ASP.NET MVC, Ruby on Rails, etc.). There is no single thing that will make the difference between "secure" (not exploitable) and "not secure".


通过HTTPS, POST数据被编码,但url会被第三方嗅探吗?

不,他们不能嗅。但url将存储在浏览器历史记录中。

是否可以公平地说,最佳实践是避免将敏感数据完全放在POST或GET中,而是使用服务器端代码来处理敏感信息?

这取决于它有多敏感,或者更具体地说,以何种方式敏感。显然客户会看到它。任何可以实际访问客户端计算机的人都可以看到它。客户端可以在发送回给您时欺骗它。如果这些很重要,那么是的,把敏感数据保存在服务器上,不要让它离开。