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

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

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


当前回答

安全的概念是没有意义的,除非你定义了你想要防范的是什么。

如果您希望对存储的浏览器历史记录、某些类型的日志记录以及查看您的url的人保持安全,那么POST更安全。

如果您希望安全防范某人嗅探您的网络活动,那么没有什么区别。

其他回答

除非使用https,否则不存在安全性—使用https, GET和POST之间的传输安全性是相同的。

但是一个重要的方面是客户机和服务器在记住请求时的区别。在考虑使用GET或POST进行登录时,要记住这一点非常重要。

使用POST,密码由服务器应用程序处理,然后丢弃,因为一个好的设计不会在数据库中存储密码——只存储加密安全的散列。

但是使用GET,服务器日志最终将包含包含查询参数的请求。因此,无论数据库中的密码哈希值有多好,服务器日志仍然会以明文形式包含密码。除非对文件系统进行加密,否则即使在删除日志文件之后,服务器磁盘仍将包含这些密码。

使用访问令牌作为查询参数时也会出现同样的问题。这也是为什么考虑在HTTP报头数据中提供任何访问令牌是有意义的原因——比如在授权报头中使用承载令牌。

服务器日志通常是web服务中最薄弱的部分,允许攻击者从泄露的信息中提升他们的访问权限。

我通常的选择方法是:

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

正如之前一些人所说,HTTPS带来了安全性。

但是,POST比GET更安全,因为GET可以存储在历史记录中。

但更令人遗憾的是,有时POST或GET的选择并不取决于开发人员。例如,一个超链接总是通过GET发送(除非它使用javascript转换成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暗示了一些副作用,这些副作用通常会阻止请求的安全性。

GET url显示在浏览器历史记录和web服务器日志中。因此,永远不要将它们用于登录表单和信用卡号之类的内容。

然而,仅仅发布这些数据也不能保证它的安全。为此,您需要SSL。当通过HTTP使用时,GET和POST都以明文形式通过网络发送数据。

POST数据还有其他很好的理由——比如可以提交无限量的数据,或者对普通用户隐藏参数。

缺点是用户不能收藏通过POST发送的查询结果。为此,您需要GET。