Web 应用程序安全性的 GET 和 POST 之间有区别吗?

信息安全 Web应用程序 隐私 开发 攻击预防
2021-08-17 16:34:38

在 2 个 Web 应用程序之间发送数据时,我有 2 个选择。

  1. 我在 Base64 中对数据进行编码并附加到 URL,然后在我的目标应用程序中检索这些参数并解码这些参数。

    例如, http:/myDomain/someCode/pages/somePage.jsf?pin=MzAwMDY3MDI2OQ

  2. 将参数作为隐藏值从 application1 发送到 application2。

    字符串 res=(String)request.getAttribute("paramValue");
    document.myForm.action='myDestinationURL';
    document.myForm.method="POST";
    document.myForm.submit();
    
    <form name="myForm" method="post">
    <input type="hidden" name="paramValue" value="<%=res%>" />

在选项 1 中,可以知道发送的参数和我的编码技术。在选项 2 中,可以通过查看源轻松查看正在发送的数据。

除了上述情况外,入侵者还有哪些可能的方法来更好地了解我的系统?哪个选项通常更适合开发人员?选择1还是选择2?

4个回答

无论如何,选项 1 可能会引入许多与安全无关的问题:

  • 生成的 URL 可能会被浏览器缓存或添加书签,从而导致用户重新提交。
  • 生成的 URL 可能会被用户共享,导致第三方提交。
  • 该 URL 可能会发送给您的浏览器供应商,他们可能会访问该站点。

但这是关于安全性的,它引入了选项 2 中不存在的一些风险:

  • 带有参数的 URL 可能最终会出现在所有内容的代理日志中,从而泄露您的数据。
  • 您的 decode 函数现在是一个额外的攻击向量。(它是否正确处理 unicode?它有长度限制吗?)
  • 您可能会倾向于认为您的编码字符串以某种方式安全,而它只是通过默默无闻(而不是非常晦涩)的安全性,或者更恰当地说是安全剧院

话虽如此;在其他方面,它们在提供的安全性方面基本相同它们都在 HTTP 标头中提交纯文本数据,并且 base64 并不完全是火箭科学(您可以对您的 POST 版本进行 base64 编码)。

两者都没有为您的数据提供任何有意义的保护。

如果是您不希望用户看到的信息;你为什么要把它发送给用户?考虑您正在使用的架构,看看是否有一种方法可以通过不在客户端处理该信息来完全消除风险。

所以,回答这个问题:关于发送数据——两者都向攻击者透露了相同的信息;选择更适合这种情况的选项(这篇 Treehouse 博客文章可能对此有所帮助),但您不应依赖任何一种方法来实际保护任何东西。

通过在网页中包含一个简单的标签,可以很容易地进行跨站点GET请求。<img>例如,在来自 的页面中www.evilhacker.com,一些 Javascript 会生成一长串<img>标记,其中包含攻击者选择的路径,所有路径都指向www.targetbank.com-- 并且您的浏览器将在所有请求中包含银行 cookie。

仅此一项就意味着您最好不要支持意味着对目标站点进行GET任何修改的请求。作为一般规则,GET应将请求保留给不存在重放攻击问题的操作——即,在实践中,仅对静态数据进行读取访问

使用 POST 发送修改服务器数据的请求。

根据HTTP 规范,GET 请求(例如,URL 中的参数)应该只用于请求检索(因此称为 GET)而不是修改数据。每当请求创建/更新/修改要存储在数据库中的数据(标准日志除外)时,都应使用 POST 请求(不可见的参数,但在 HTTP 请求中仍然未加密)。这使得攻击者更难进行跨站点请求伪造,并且不太可能意外地在您的网页历史记录/网络服务器日志中重复提交或存储秘密信息。

pin变量是秘密吗?

您目前正在做的事情似乎不安全,具体取决于pin变量的含义。这是否需要对潜在的窃听者保密,或者拦截该引脚的人是否可以对其进行某种攻击?如果是这样,请仅对包含此机密数据的每个请求使用 HTTPS(用于传输层上的端到端加密)。您使用的 base-64 值似乎是3000670269(当然我必须附加两个等号才能使其成为正确的 b64 编码)。

如果攻击者尝试使用其他引脚会发生什么?

假设我的pin='300670269',但是为了测试我发送的系统MzAwMDY3MDI1OQ(for pin='3000670259')。这会让他们有效地侵入另一个用户帐户吗?如果是这样,至少,你应该做一些事情,比如有一个额外的 POST 变量,比如 一些长的随机字符串checksum=SHA256(pin+secret_server_side_string)在哪里(例如40 个随机的大写+小写+数字字符有 lg(62)*40 = 238 位熵),并且您的应用程序仅在校验和与引脚匹配时才对引脚起作用。您的应用程序应该生成校验和(不向客户端透露 secret_server_side_string)。您还必须小心,在使用 pin 检查校验和时,您的应用程序会进行恒定时间的字符串比较,因此您的应用程序不容易受到计时攻击。secret_server_side_stringde10RRORX50UAUhx0dDIxJnzXKBAs68yjdWVz8QQ

最近有一种有趣的攻击被用来规避 Web 应用程序防火墙规则,称为“ HTTP 参数污染攻击”。我将用一个例子来解释

POST /index.aspx?par=1&par=2 HTTP/1.1
User-Agent: Mozilla/5.0
Host: Host
Cookie: par=5; par=6
Content-Length: 19
par=3&par=4 

对于此 Post Request Application 行为将取决于开发人员,并且喜欢 java。

  1. javax.servlet.ServletRequestInterface(查询字符串直接解析)
  2. java.lang.StringgetParameter(java.lang.Stringname) 将请求参数的值作为字符串返回,如果参数不存在,则返回 null
  3. java.lang.String[] getParameterValues(java.lang.Stringname) 返回包含给定请求参数具有的所有值的 String 对象数组,如果参数不存在,则返回 null。