一个HTTPS查询字符串是否安全?

429

我正在创建一个安全的基于Web的API,使用HTTPS; 但是,如果我允许用户使用查询字符串配置它(包括发送密码),这样做是否也安全,还是应该强制使用POST?

9个回答

530

是的,可以使用GET方法传输数据。但是对于敏感数据来说,使用GET方法是不明智的,有以下几个原因:

  • 大部分HTTP引用泄漏(目标页面中的外部图像可能会泄露密码[1])
  • 密码将存储在服务器日志文件中(这显然是不好的)
  • 浏览器中的历史缓存

因此,即使查询字符串是安全的,也不建议通过查询字符串传输敏感数据。

[1] 尽管我需要注意的是RFC规定浏览器不应从HTTPS发送引用到HTTP。但这并不意味着恶意的第三方浏览器工具栏或来自HTTPS网站的外部图像/Flash不会泄露它。


4
https到https的引用如何处理?如果我使用https从第三方网站获取图像,浏览器是否会将我之前请求中的整个查询字符串发送给第三方服务器? - Jus12
4
@Jus12 是的,它会这样做,虽然这听起来没有意义,但这就是设计初衷。 - dr. evil
2
那么为什么OAuth2规范不建议在查询参数(URL中)发送敏感数据呢?即使始终建议使用TLS(HTTPS)。请参考http://tools.ietf.org/html/draft-ietf-oauth-v2-bearer-16#section-4.3中的最后一点。@volka - gihanchanuka
1
为了提供最新的信息,这里有一个完整的答案:http://www.securitynewspaper.com/2016/08/01/proxy-pac-hack-allows-intercept-https-urls/(代理PAC黑客允许拦截HTTPS URLS)。 - Tom
1
@Arthur,它从来没有说过服务器到服务器。API经常从浏览器中调用。 - GaTechThomas
显示剩余8条评论

94

从“嗅探网络数据包”的角度看,GET请求是安全的,因为浏览器会首先建立安全连接,然后发送包含GET参数的请求。但是,GET URL将被存储在用户浏览器历史记录/自动完成中,这不是一个好地方来存储密码等数据。当然,只有当您采用更广泛的“Web服务”定义,并从浏览器访问该服务时,才适用此规则;如果您仅从自定义应用程序访问,则不应该存在此问题。

因此,对于密码对话框,至少使用POST应该是首选。另外,正如littlegeek发布的链接所指出的那样,GET URL更可能被写入服务器日志。


79

是的,您的查询字符串将被加密。

原因是查询字符串是HTTP协议的一部分,而安全(SSL / TLS)部分来自传输层。先建立SSL连接,然后发送属于HTTP协议的查询参数到服务器。

建立SSL连接时,客户端将按以下顺序执行以下步骤。假设您正在尝试登录名为example.com的站点,并希望使用查询参数发送凭据,则完整的URL可能如下所示:

https://example.com/login?username=alice&password=12345)
  1. 您的客户端(例如浏览器/移动应用程序)将使用DNS请求将您的域名example.com解析为IP地址(124.21.12.31)。在查询该信息时,仅使用特定于域的信息,即仅使用example.com
  2. 现在,您的客户端将尝试使用IP地址124.21.12.31连接服务器,并尝试连接到端口443(SSL服务端口,而不是默认的HTTP端口80)。
  3. 现在,example.com上的服务器将向您的客户端发送其证书。
  4. 您的客户端将验证证书并开始交换用于会话的共享密钥。
  5. 成功建立安全连接后,您的查询参数才会通过安全连接发送。

因此,您不会暴露敏感数据。但是,使用这种方法通过HTTPS会话发送凭据并不是最佳方式。您应该选择另一种方法。


4
但是请看@dr. evil的答案,查询字符串可能会出现在日志文件和缓存中,因此在服务器上可能不安全。 - zaph
3
嗨zaph,在HTTPS安全方面,目标是在不让中间任何人嗅探数据的情况下将数据安全地发送到服务器。虽然这是可能的,并回答了问题,但实际上很难控制服务器之后的操作。所以我也提到这不是正确的方法。此外,您永远不应该从客户端发送密码。您应该始终在设备上对其进行哈希处理,然后将哈希值发送到服务器。 - Ruchira Randana
1
从安全角度来看,在查询字符串中发送机密信息是不安全的,最好使用POST方法发送。此外,密码通常在服务器上进行哈希处理,而不是由客户端处理。语句“您不应该从客户端发送密码”与答案(例如http://example.com/login?username=alice&password=12345)相矛盾。 - zaph
@RuchiraRandana 在客户端进行哈希处理是毫无意义的,因为私钥可以轻易地从前端检索到。 - James W
@JamesW "私钥可以轻松地从前端检索出来" 什么密钥? - curiousguy
@curiousguy 是的,说得好。而且,拥有哈希算法并不能使事物本身“不可逆转”。在前端对其进行哈希限制了中间人攻击。我的错误是由于某种原因我把哈希和加密混淆了。 - James W

32

是的。HTTPS会话的整个文本都由SSL进行安全保护,包括查询和标题。在这方面,POST和GET请求是完全相同的。

至于您的方法的安全性,没有适当的检查就无法真正地确定。


32
安全不仅仅是浏览器和服务器之间的通信。 - JoeBloggs
2
是的,但在我的浏览器历史记录中会显示: https : //www.google.com?query=mySecretQuery - Robin van Leeuwen

28

SSL首先连接到主机,因此主机名和端口号会以明文形式传输。当主机响应并成功挑战后,客户端将使用实际URL(即第三个斜杠后的任何内容)加密HTTP请求并发送到服务器。

有几种方法可以破坏这种安全性。

可能会配置代理作为“中间人”。基本上,浏览器将连接到真实服务器的请求发送到代理。如果代理以这种方式配置,则它将通过SSL连接到真实服务器,但浏览器仍将与代理通信。因此,如果攻击者能够访问代理,他可以查看所有流经代理的数据。

您的请求也将出现在浏览器历史记录中。用户可能会尝试将站点添加到书签。一些用户已安装了书签同步工具,因此密码可能最终出现在deli.ci.us或其他地方。

最后,某人可能已经黑掉了您的计算机并安装了键盘记录器或屏幕抓取程序(很多特洛伊木马病毒都这么做)。由于密码直接显示在屏幕上(而不是在密码对话框中的“*”),这是另一个安全漏洞。

结论:谈到安全性,始终依赖于已知的路线。因为有太多你不知道、不能想到,而这些会让你遭受损失。


3
“浏览器仍然会与代理服务器通信”并不完全正确,实际上,代理服务器需要向浏览器提供一个有效的证书,而这个证书只有在代理服务器控制下的受浏览器信任的CA(证书颁发机构)才能生成。 - Pieter

13

是的,只要没有人在你的监视器旁边看着你。


12

我不同意在Slough的回答中所述的有关HTTP引荐泄漏的说法(目标页面中的外部图像可能会泄漏密码)。

HTTP 1.1 RFC明确规定

如果引用页使用安全协议传输,则客户端不应在非安全的HTTP请求中包括Referer头字段。

无论如何,服务器日志和浏览器历史记录都足以证明不要将敏感数据放在查询字符串中。


3
又出现了那个词“应该”。你会相信每个浏览器的每个版本都能保护好你的密码吗? - JoeBloggs
1
这与GET和POST有什么关系?如果您使用HTTPS上的POST,那么“每个浏览器的每个版本”是否安全? - Arnout
3
此外,HTTPS网页可能会通过HTTPS检索外部图片 - 在这种情况下,浏览器应该包含引用页头,并因此暴露您的密码... - AviD
3
请阅读这个RFC文档,它告诉你“SHOULD NOT”的含义:http://www.ietf.org/rfc/rfc2119.txt。这与“MUST NOT”不同,所以你引用的部分并不是很相关,浏览器代理仍然可能包含HTTP引用页(referer)。 - Andy

10

是的,一旦您建立HTTPS连接,所有内容都是安全的。查询字符串(GET)和POST都通过SSL发送。


使用GET方法传输敏感信息是一个众所周知的安全漏洞,应该避免使用。另外,请参考下面@VolkA的帖子,了解一些不应该使用GET方法的原因。 - undefined

-7

您可以将密码作为MD5哈希参数发送,并添加一些盐。在服务器端进行身份验证时进行比较。


13
MD5不适合用于密码哈希函数。 - slawek
1
无论是哈希还是明文,将密码发送到GET参数中都是不好的做法。请参考得票最高的答案以获取解释。 还有...MD5不应该再在任何地方使用了... - Thomas
1
“不适合用于密码的哈希函数”,但仍比明文发送密码到服务器更好,哈哈。 - curiousguy

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接