首页 文章

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

提问于
浏览
266

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

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

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

25 回答

  • 1

    GET和POST中的任何一个本身都不是"more secure",就像传真和电话中的任何一个都不是另一个一样 . 提供了各种HTTP方法,以便您可以选择最适合您尝试解决的问题的方法 . 对于idempotent查询,GET更适合,而对于"action"查询,POST更适合你,但如果你不进行维护,你可以轻松地用自己的任何一个射击自己 .

    如果您阅读了HTTP/1.1 RFCChapter 9: Method Definitions,那么最好能够全面了解GET和POST最初的设想 .

  • 1

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

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

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

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

  • 2

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

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

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

  • -3

    GET请求的安全性略低于POST请求 . 两者都没有提供真正的"security"本身;使用POST请求不会神奇地使您的网站安全地抵御恶意攻击 . 但是,使用GET请求可能会使安全的应用程序不安全 .

    您"must not use GET requests to make changes"的口头禅仍然非常有效,但这与恶意行为无关 . 登录表单是使用错误的请求类型发送最敏感的表单 .

    搜索蜘蛛和网络加速器

    这是您应该使用POST请求更改数据的真正原因 . 搜索蜘蛛将关注您网站上的每个链接,但不会提交他们找到的随机表单 .

    Web加速器比搜索蜘蛛更糟糕,因为它们在客户端的计算机上运行,并且在登录用户的上下文中都是"click"所有链接 . 因此,使用GET请求删除内容的应用程序,即使它需要管理员,也会很乐意遵守(非恶意!)Web加速器和delete everything it sees的命令 .

    迷茫的副攻击

    confused deputy attack(代理人是浏览器)是possible regardless of whether you use a GET or a POST request .

    在攻击者控制的网站上,GET和POST是equally easy to submit without user interaction .

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

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

    代理日志

    代理服务器可能会完整地记录GET URL,而不会剥离查询字符串 . 通常不会记录POST请求参数 . 在任何一种情况下都不太可能记录Cookie . (example)

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

    登录请求有一个例外:这些例外往往包含用户的密码 . 将其保存在代理日志中会打开一个在POST情况下不存在的攻击向量 . 但是,无论如何,通过普通HTTP登录本身就是不安全的 .

    代理缓存

    缓存代理可能会保留GET响应,但不会保留POST响应 . 话虽如此,与将URL转换为POST处理程序相比,GET响应可以使用不可缓存的方式 .

    HTTP“Referer”

    如果用户要导航到第三方为响应GET请求而提供的页面网站,该第三方网站可以查看所有GET请求参数 .

    属于“向第三方显示请求参数”的类别,其严重性取决于这些参数中存在的内容 . POST请求自然不受此限制,但是为了利用GET请求,黑客需要将自己网站的链接插入到服务器的响应中 .

    浏览器历史记录

    这与“代理日志”参数非常相似:GET请求与其参数一起存储在浏览器历史记录中 . 如果攻击者可以物理访问机器,则可以轻松获取这些内容 .

    浏览器刷新操作

    一旦用户点击“刷新”,浏览器将重试GET请求 . 关机后恢复标签时可能会这样做 . 因此,任何行动(例如付款)都将在没有警告的情况下重复 .

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

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

    那我该怎么办?

    • 仅使用POST请求更改数据,主要是出于与安全无关的原因 .

    • 仅对登录表单使用POST请求;否则会引入攻击向量 .

    • 如果您的网站执行敏感操作,您确实需要知道他们正在做什么的人,因为这不能在单个答案中涵盖 . 您需要使用HTTPS,HSTS,CSP,缓解SQL注入,script injection (XSS)CSRF以及可能特定于您的平台的大量其他内容(例如各种框架中的批量分配漏洞:ASP.NET MVCRuby on Rails等) . 没有任何一件事可以区分"secure"(不可利用)和"not secure" .


    通过HTTPS,POST数据被编码,但是第三方可以嗅探URL吗?

    不,他们不能被嗤之以鼻 . 但URL将存储在浏览器历史记录中 .

    最好的做法是避免将敏感数据放在POST或GET中,并使用服务器端代码来处理敏感信息,这是否公平?

    取决于它是多么敏感,或者更具体地说,取决于它的方式 . 显然客户会看到它 . 任何有物理访问客户端计算机的人都会看到它 . 客户端可以在发送给您时欺骗它 . 如果那些问题然后是,请将敏感数据保留在服务器上,不要让它离开 .

  • 3

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

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

    • 选项

    • GET

    • HEAD

    • POST

    • PUT

    • 删除

    • TRACE

    • CONNECT

    假设您使用GET拥有以下HTML文档:

    <html>
    <body>
    <form action="http://example.com" method="get">
        User: <input type="text" name="username" />
    Password: <input type="password" name="password" />
    <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
    

    BOTH 这些HTTP请求是:

    • 未加密

    • 包含在两个示例中

    • 可以被evesdroped,并受到MITM攻击 .

    • 由第三方和脚本机器人轻松复制 .

    许多 browsers 不支持POST / GET以外的HTTP方法 .

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

    所以具体来说:

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

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

    通过https,POST数据被编码,但可能会被第三方嗅探?

    这里's how SSL works. Remember those two requests I sent above? Here'是他们在SSL中的样子:(我将页面更改为https://encrypted.google.com/,因为example.com不响应SSL) .

    通过SSL POST

    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并且您的站点不包含XSS漏洞,您也可能会被_1124600攻击 . 简而言之,此攻击情形假定受害者(您的站点或服务的用户)已经登录并且具有适当的cookie然后是受害者's browser is requested to do something with your (supposedly secure) site. If you do not have protection against CSRF the attacker can still execute actions with the victims credentials. The attacker cannot see the server response because it will be transferred to the victim'浏览器,但是此时通常已经完成了损坏 .

  • 414

    There is no added security.

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

  • 0

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

    • 信息 POST ed将不会保存在用户的历史记录中 .

    • 稍后在URL栏中将无法看到表单中发送的敏感信息(密码等)(通过使用 GET ,它将在历史记录和URL栏中可见) .

    此外, GET 具有理论上的数据限制 . POST 没有 .

    对于真正的敏感信息,请务必使用 SSLHTTPS

  • 1

    我通常的选择方法是这样的:

    • GET 用于稍后将通过网址 retrieved 的项目

    • 例如搜索应该是GET所以你可以稍后搜索search.php?s = XXX

    • POST 适用于 sent 的物品

    • 这对GET来说是相对不可见的,并且难以发送,但数据仍然可以通过cURL发送 .

  • 169

    这与安全无关,但是...... browsers doesn't cache POST requests .

  • 0

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

    GET URL显示在浏览器历史记录和Web服务器日志中 . 出于这个原因,它们永远不应该用于登录表单和信用卡号码之类的东西 .

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

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

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

  • 0

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

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

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

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

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

  • 5
    • 安全作为数据安全IN TRANSIT:POST和GET之间没有区别 .

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

  • -3

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

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

    如果你想要对某人嗅探你的网络活动是安全的,那么没有区别 .

  • 6

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

  • 1

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

  • 18

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

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

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

  • 1

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

  • 194

    RFC7231:

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

    服务的作者应该避免提交敏感数据的基于GET的表格,因为这些数据将被放置在请求目标中 . 许多现有服务器,代理和用户代理在第三方可见的位置记录或显示请求目标 . 这些服务应该使用基于POST的表单提交 . “

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

  • 6

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

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

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

  • 32

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

  • 1

    默认情况下记录 POST is worse for security is that GET 的一个原因是,您的网络服务器几乎普遍记录参数和所有数据 .

    POST是相反的,它几乎普遍 not logged ,导致很难发现攻击者的活动 .

    我没有理由不记录任何内容,至少1KB,对于人们识别攻击者在弱入口点工作直到它弹出,然后POST通过启用任何HTTP进行双重解除服务将有很长的路要走基于后门,默默地传递无限量的数据 .

  • 27

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

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

  • 0

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

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

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

  • 15

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

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

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

  • 6

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

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

相关问题