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

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

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


当前回答

GET对任何人都是可见的(甚至是你肩膀上的人),并且保存在缓存中,所以使用post不太安全,顺便说一句,没有一些加密程序的post是不确定的,为了一点安全性,你必须使用SSL (https)

其他回答

Neither one of GET and POST is inherently "more secure" than the other, just like neither one of fax and phone is "more secure" than the other. The various HTTP methods are provided so that you can choose the one which is most appropiate for the problem you're trying to solve. GET is more appropiate for idempotent queries while POST is more appropiate for "action" queries, but you can shoot yourself in the foot just as easily with any of them if you don't understand the security architecture for the application you're maintaining.

最好是阅读第9章:HTTP/1.1 RFC的方法定义,以全面了解get和POST最初的含义。

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中,而是使用服务器端代码来处理敏感信息?

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

GET和POST之间的区别不应该从安全性的角度来看待,而应该从它们对服务器的意图来看待。GET永远不应该改变服务器上的数据——至少除了日志之外——但是POST可以创建新的资源。

好的代理不会缓存POST数据,但它们可能缓存来自URL的GET数据,因此可以说POST应该更安全。但是POST数据仍然可以用于那些性能不佳的代理。

正如在许多答案中提到的,唯一确定的赌注是通过SSL。

但是一定要确保GET方法不会提交任何更改,比如删除数据库行等等。

我通常的选择方法是:

GET用于稍后将通过URL检索的项 例如,搜索应该是GET,所以你可以做Search .php?s=XXX POST将被发送的项目 与GET相比,这是相对不可见的,并且更难发送,但数据仍然可以通过cURL发送。

这是一篇旧文章,但我想反对其中的一些答案。如果要传输敏感数据,则需要使用SSL。如果您使用带有GET参数的SSL(例如?userid=123),该数据将以纯文本形式发送!如果使用POST发送,则将值放在消息的加密正文中,因此大多数MITM攻击都无法读取。

最大的区别在于数据传递的位置。如果数据放在URL中,就不能加密,否则就无法路由到服务器,因为只有你可以读取URL。这就是GET的工作方式。

简而言之,您可以在POST中通过SSL安全地传输数据,但您不能使用GET,无论是否使用SSL。