GET或POST比另一个更安全吗?

时间:2008-10-13 18:08:02

标签: html security http

将HTTP GET与HTTP POST进行比较时,从安全角度来看有何不同?其中一个选择本身比另一个更安全吗?如果是这样,为什么?

我意识到POST不会公开有关URL的信息,但是它是否有任何实际价值,还是仅通过默默无闻的安全性?当担心安全问题时,我是否应该更喜欢POST?

修改
通过HTTPS,POST数据被编码,但是第三方可以嗅探URL吗?另外,我正在处理JSP;在使用JSP或类似框架时,最好的做法是避免将敏感数据放在POST或GET中并使用服务器端代码来处理敏感信息吗?

28 个答案:

答案 0 :(得分:417)

答案 1 :(得分:199)

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

GET或查询字符串帖子非常适用于为特定项目添加书签或协助搜索引擎优化和索引项目所需的信息。

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

答案 2 :(得分:170)

您没有提供更高的安全性,因为变量是通过HTTP POST发送的,而不是通过HTTP GET发送的变量。

HTTP/1.1 provides us with a bunch of methods to send a request

  • OPTIONS
  • GET
  • HEAD
  • POST
  • PUT
  • DELETE
  • TRACE
  • CONNECT

假设您使用GET获得以下HTML文档:

<html>
<body>
<form action="http://example.com" method="get">
    User: <input type="text" name="username" /><br/>
    Password: <input type="password" name="password" /><br/>
    <input type="hidden" name="extra" value="lolcatz" />
    <input type="submit"/>
</form>
</body>
</html>

您的浏览器会问什么?它问:

 GET /?username=swordfish&password=hunter2&extra=lolcatz HTTP/1.1
 Host: example.com
 Connection: keep-alive
 Accept: application/xml,application/xhtml+xml,text/html;q=0.9,text/ [...truncated]
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; en-US) [...truncated]
 Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-US,en;q=0.8
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

现在让我们假装我们将该请求方法更改为POST:

 POST / HTTP/1.1
 Host: example.com
 Connection: keep-alive
 Content-Length: 49
 Cache-Control: max-age=0
 Origin: null
 Content-Type: application/x-www-form-urlencoded
 Accept: application/xml,application/xhtml+xml,text/ [...truncated]
 User-Agent: Mozilla/5.0 (Windows; U; Windows NT 6.0; [...truncated]
 Accept-Encoding: gzip,deflate,sdch
 Accept-Language: en-US,en;q=0.8
 Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.3

 username=swordfish&password=hunter2&extra=lolcatz
这些HTTP请求的

BOTH 是:

  • 未加密
  • 包含在两个示例中
  • 可以被开除,并受MITM攻击。
  • 由第三方和脚本机器人轻松复制。

许多浏览器不支持POST / GET以外的HTTP方法。

许多浏览器行为会存储页面地址,但这并不意味着您可以忽略其他任何问题。

具体来说:

  

一个人本来就比另一个更安全吗?我意识到POST不会暴露关于URL的信息,但是它是否有任何实际价值,还是仅通过默默无闻的安全性?这里的最佳做法是什么?

这是正确的,因为您用来说HTTP的软件倾向于使用一种方法存储请求变量而不是另一种方法只能阻止某人查看您的浏览器历史记录或其他一些认为10岁的人的天真攻击他们了解h4x0r1ng或检查历史存储的脚本。如果你有一个可以检查你的历史存储的脚本,你可以很容易地检查你的网络流量,所以通过默默无闻的整个安全性只是为脚本小子和嫉妒的女朋友提供默默无闻。

  

通过https,POST数据被编码,但是第三方可能会嗅到网址?

以下是SSL的工作原理。还记得上面发过的那两个请求吗?这是他们在SSL中的样子: (我将页面更改为https://encrypted.google.com/,因为example.com没有响应SSL)。

通过SSL发布

q5XQP%RWCd2u#o/T9oiOyR2_YO?yo/3#tR_G7 2_RO8w?FoaObi)
oXpB_y?oO4q?`2o?O4G5D12Aovo?C@?/P/oOEQC5v?vai /%0Odo
QVw#6eoGXBF_o?/u0_F!_1a0A?Q b%TFyS@Or1SR/O/o/_@5o&_o
9q1/?q$7yOAXOD5sc$H`BECo1w/`4?)f!%geOOF/!/#Of_f&AEI#
yvv/wu_b5?/o d9O?VOVOFHwRO/pO/OSv_/8/9o6b0FGOH61O?ti
/i7b?!_o8u%RS/Doai%/Be/d4$0sv_%YD2_/EOAO/C?vv/%X!T?R
_o_2yoBP)orw7H_yQsXOhoVUo49itare#cA?/c)I7R?YCsg ??c'
(_!(0u)o4eIis/S8Oo8_BDueC?1uUO%ooOI_o8WaoO/ x?B?oO@&
Pw?os9Od!c?/$3bWWeIrd_?( `P_C?7_g5O(ob(go?&/ooRxR'u/
T/yO3dS&??hIOB/?/OI?$oH2_?c_?OsD//0/_s%r

通过SSL获取

rV/O8ow1pc`?058/8OS_Qy/$7oSsU'qoo#vCbOO`vt?yFo_?EYif)
43`I/WOP_8oH0%3OqP_h/cBO&24?'?o_4`scooPSOVWYSV?H?pV!i
?78cU!_b5h'/b2coWD?/43Tu?153pI/9?R8!_Od"(//O_a#t8x?__
bb3D?05Dh/PrS6_/&5p@V f $)/xvxfgO'q@y&e&S0rB3D/Y_/fO?
_'woRbOV?_!yxSOdwo1G1?8d_p?4fo81VS3sAOvO/Db/br)f4fOxt
_Qs3EO/?2O/TOo_8p82FOt/hO?X_P3o"OVQO_?Ww_dr"'DxHwo//P
oEfGtt/_o)5RgoGqui&AXEq/oXv&//?%/6_?/x_OTgOEE%v (u(?/
t7DX1O8oD?fVObiooi'8)so?o??`o"FyVOByY_ Supo? /'i?Oi"4
tr'9/o_7too7q?c2Pv

(注意:我将HEX转换为ASCII,其中一些显然不能显示)

整个HTTP会话已加密,唯一可见的通信部分位于TCP / IP层(即IP地址和连接端口信息)。

所以,让我在这里做一个大胆的声明。与一个HTTP方法相比,您的网站没有提供更高的安全性,全世界的黑客和新手都知道如何做我刚刚在这里演示的内容。如果您需要安全性,请使用SSL。浏览器倾向于存储历史记录,RFC2616 9.1.1推荐不使用GET执行操作,但认为POST提供安全性是完全错误的。

POST唯一的安全措施是什么?通过浏览器历史记录保护您免受嫉妒。而已。世界其他地方都会嘲笑你的帐号。

为了进一步说明为什么POST不安全,Facebook会在整个地方使用POST请求,那么FireSheep等软件如何存在?

请注意,即使您使用HTTPS并且您的网站不包含CSRF个漏洞,您也可能会被XSS攻击。简而言之,此攻击情形假定受害者(您的站点或服务的用户)已经登录并拥有适当的cookie,然后请求受害者的浏览器对您的(据称是安全的)站点执行某些操作。如果您没有针对CSRF的保护,攻击者仍然可以使用受害者凭据执行操作。攻击者无法看到服务器响应,因为它会被转移到受害者的浏览器,但损坏通常已经在那时完成。

答案 3 :(得分:32)

没有额外的安全措施。

发布数据未显示在历史记录和/或日志文件中,但如果数据应保持安全,则需要SSL。
否则,任何嗅探电线的人都可以读取您的数据。

答案 4 :(得分:27)

即使POSTGET相比没有真正的安全优势,对于登录表单或任何其他具有相对敏感信息的表单,请确保您使用POST作为:

  1. 信息POST ed不会保存在用户的历史记录中。
  2. 稍后会在网址栏中显示表单中发送的敏感信息(密码等)(使用GET,它会在历史记录和网址栏中显示)。
  3. 此外,GET具有理论上的数据限制。 POST没有。

    要获得真实的敏感信息,请务必使用SSLHTTPS

答案 5 :(得分:18)

GET和POST中的其中一个本身并不比另一个“更安全”,就像传真和电话中的任何一个都不比另一个“更安全”一样。提供了各种HTTP方法,以便您可以选择最适合您尝试解决的问题的方法。对于idempotent查询,GET更合适,而POST更适合“动作”查询,但如果您不了解应用程序的安全体系结构,您可以轻松地使用其中任何一个进行拍摄'维持。

最好是阅读Chapter 9: Method DefinitionsHTTP/1.1 RFC,以全面了解最初设想的GET和POST。

答案 6 :(得分:15)

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

好的代理不会缓存POST数据,但是它们可能会缓存来自URL的GET数据,所以你可以说POST应该更安全。但是POST数据仍然可用于不能很好地运行的代理。

正如许多答案所述,唯一可靠的赌注是通过SSL。

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

答案 7 :(得分:6)

我通常的选择方法是:

  • 获取,以便稍后通过网址检索的项目
    • E.g。搜索应该是GET所以你可以稍后在
    • 上搜索search.php?s = XXX
  • 发布表示已发送的项目
    • 这是相对隐形comapred到GET并且难以发送,但数据仍然可以通过cURL发送。

答案 8 :(得分:6)

这与安全无关,但...... 浏览器不会缓存POST请求

答案 9 :(得分:6)

两者都没有神奇地赋予请求安全性,但是GET意味着一些通常会阻止其安全的副作用。

GET网址显示在浏览器历史记录和网络服务器日志中。因此,它们永远不应用于登录表单和信用卡号等。

但是,仅仅发布该数据也不会使其安全。为此你想要SSL。当通过HTTP使用时,GET和POST都通过线路以明文形式发送数据。

还有其他很好的理由来发布数据 - 比如能够提交无限量的数据,或隐藏临时用户的参数。

缺点是用户无法为通过POST发送的查询的结果添加书签。为此,你需要GET。

答案 10 :(得分:5)

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

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

在某些设置中,当您请求此URL并且有关于请求的错误/警告时,整行将记录在日志文件中。更糟糕的是:如果您忘记在生产服务器中禁用错误​​消息,则此信息仅在浏览器中以简单方式显示!现在,您刚刚将API密钥提供给所有人。

不幸的是,有真正的API以这种方式工作。

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

答案 11 :(得分:3)

  1. 作为数据安全的安全性IN TRANSIT:POST和GET之间没有区别。

  2. 安全作为计算机上数据的安全:POST更安全(无URL历史记录)

答案 12 :(得分:2)

除非您定义了您想要保护的安全性,否则安全概念毫无意义。

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

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

答案 13 :(得分:1)

您还应该知道,如果您的网站包含指向其他外部网站的链接,您无法使用GET控制,当他们按您网站上的链接时,会将这些数据放入外部网站上的refeerer标头中。因此,通过GET方法传输登录数据始终是一个大问题。由于这可能只是通过检查日志或查看Google分析(或类似)来公开登录凭据以便于访问。

答案 14 :(得分:1)

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

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

但更糟糕的是,有时候POST或GET的选举不适合开发人员。例如,GET总是发送超链接(除非使用javascript将其转换为帖子形式)。

答案 15 :(得分:1)

RFC7231:

&#34; URI即使在识别时也要共享,而不是安全    安全的资源。 URI经常显示在显示器上,添加到    打印页面时的模板,并存储在各种页面中    未受保护的书签列表。因此,包括在内是不明智的    URI中敏感,可识别个人身份的信息,    或披露的风险。

服务的作者应该避免提交的基于GET的表格    敏感数据因为该数据将被放入    请求目标。许多现有服务器,代理和用户代理都会记录    或者在可能可见的地方显示请求目标    第三方。这些服务应该使用基于POST的表单提交    代替&#34;

此RFC明确规定不应使用GET提交敏感数据。由于这种说法,一些实现者可能无法处理从GET请求的查询部分获得的数据。我自己正在制定一个确保数据完整性的协议。根据这个规范,我不应该保证GET数据的完整性(我会因为没有人遵守这些规范)

答案 16 :(得分:1)

更改POST请求更加困难(比编辑查询字符串需要更多的精力)。 编辑:换句话说,它只是默默无闻的安全,而且几乎没有。

答案 17 :(得分:1)

我不打算重复所有其他答案,但有一个方面我还没有看到 - 这是数据消失的故事。我不知道在哪里找到它,但是......

基本上它是关于一个网络应用程序神秘地每隔几晚就放弃了所有数据而没有人知道原因。后来检查日志显示该网站是谷歌或其他任意蜘蛛发现的,很高兴GET(读取:GOT)它在网站上找到的所有链接 - 包括“删除此条目”和“你确定吗?”链接。

实际上 - 已经提到了部分内容。这是“不要在GET上更改数据而只在POST上更改数据”背后的故事。爬行者将很乐意遵循GET,从不POST。甚至robots.txt也无助于防止行为不端的抓取工具。

答案 18 :(得分:1)

许多人采用一种约定(Ross提到),GET请求只检索数据,不修改服务器上的任何数据,POST请求用于所有数据修改。虽然一个并不比另一个更安全,但如果您 遵循此约定,则可以应用横切安全逻辑(例如,只有拥有帐户的人才能修改数据,因此拒绝未经身份验证的POST)。

答案 19 :(得分:0)

区别在于GET发送数据打开并且POST隐藏(在http-header中)。

因此,非安全数据会更好,例如Google中的查询字符串。永远不会通过GET发送Auth数据 - 所以在这里使用POST。当然整个主题有点复杂。如果您想阅读更多内容,请阅读this article(德语)。

答案 20 :(得分:0)

POST安全性更差的一个原因是默认情况下会记录GET ,您的网络服务器几乎会普遍记录参数和所有数据。

POST相反,它几乎普遍未记录,导致很难发现攻击者活动。

我不会购买“它太大”的论点,没有理由不记录任何,至少1KB,对于人们识别攻击弱者的攻击者来说还有很长的路要走入口点直到弹出,然后POST通过启用任何基于HTTP的后门来静默传递无限量的数据,从而实现双重解除服务。

答案 21 :(得分:0)

最近发布了an attack,允许中间人员显示压缩HTTPS请求的请求体。由于HTTP不会压缩请求标头和URL,因此可以更好地保护GET请求免受此特定攻击。

其中GET请求也容易受到攻击的

There are modes,SPDY压缩请求标头,TLS还提供可选(很少使用)压缩。在这些情况下,攻击更容易预防(浏览器供应商已经提供了修复)。 HTTP级别压缩是一个更基本的功能,供应商不太可能禁用它。

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

答案 22 :(得分:0)

任何人都可以看到GET(即使是现在你肩上的那个)并且保存在缓存中,所以使用post,btw post不太安全,没有一些密码例程也不确定,为了一点点安全,你需要使用SSL(https)

答案 23 :(得分:0)

免责声明:以下几点仅适用于API调用,不适用于网站URL。

网络安全性:您必须使用HTTPS。在这种情况下,GET和POST同样安全。

浏览器历史记录:对于Angular JS,React JS等前端应用程序,API调用是由前端进行的AJAX调用。这些不会成为浏览器历史记录的一部分。因此,POST和GET同样安全。

服务器端日志:使用数据屏蔽和访问日志格式的写入集,可以从请求URL中隐藏所有或仅敏感数据。

浏览器控制台中的数据可见性:对于具有恶意意图的人来说,查看POST数据和获取GET一样多。

因此,采用正确的日志记录做法,GET API与POST API一样安全。到处都是POST,这会导致API定义不正确,应避免使用。

答案 24 :(得分:0)

除非使用 https,否则没有安全性 - 使用 https,GET 和 POST 之间的传输安全性是相同的。

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

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

但是使用 GET,服务器日志最终将包含完整的请求和查询参数。因此,无论数据库中的密码哈希有多好,服务器日志仍将包含明文密码。除非文件系统被加密,否则即使日志文件被删除,服务器磁盘也会包含这些密码。

使用访问令牌作为查询参数时会发生同样的问题。这也是考虑在 HTTP 标头数据中提供任何访问令牌有意义的原因 - 例如通过在 Authorization 标头中使用不记名令牌。

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

答案 25 :(得分:-2)

Post是最安全的安装SSL,因为它在邮件正文中传输。

但是所有这些方法都是不安全的,因为在其下面使用的7位协议很容易被擒纵。即使通过4级Web应用程序防火墙。

套接字也不保证...即使在某些方面更安全。

答案 26 :(得分:-3)

这是一篇旧帖子,但我想反对一些答案。如果您要传输敏感数据,则需要使用SSL。如果您将SSL与GET参数一起使用(例如?userid = 123),那么该数据将以纯文本形式发送!如果使用POST发送,则值将被放入消息的加密主体中,因此对大多数MITM攻击都不可读。

最大的区别在于数据传递的位置。只有将数据放在URL中才能进行加密,否则就无法加密,否则您将无法路由到服务器,因为只有您可以读取URL。这就是GET的工作原理。

简而言之,您可以通过SSL在POST中安全地传输数据,但使用SSL时无法使用SSL进行数据传输。

答案 27 :(得分:-3)

即使POST接受GET请求。假设您有一个包含user.name和user.passwd等输入的表单,那些应该支持用户名和密码。如果我们只是添加一个?user.name =“我的用户&amp; user.passwd =”我的密码“,那么”绕过登录页面“将接受请求。

解决方法是在服务器端实现过滤器(java过滤器作为e),并检测不会将任何字符串查询作为GET参数传递。