REST与安全性

3
几天前,我看到了新闻,报道了黑客如何通过更改URL中的数字窃取了200,000多个花旗账户。开发人员为了成为RESTful而破坏了安全性,也没有将会话ID放在用户ID的位置上。我也正在开发一个安全性是主要关注点的产品,所以我想知道在这种情况下我们是否应该避免使用REST并在任何地方使用post请求?或者我是否忽略了REST的一些重要内容?

你的问题似乎表明REST需要使用GET方法。从我的阅读来看,REST要求使用GET方法来获取客户端无法更改的数据,而使用POST方法来处理客户端可以更改的数据。有时这可能会令人困惑,因为REST要求通信是无状态,而允许数据发生变化。 - this.josh
1
@this.josh 这里是一篇关于RESTful API设计的不错介绍:http://blog.apigee.com/detail/restful_api_design/ - r15habh
7个回答

5

不要因为实现不好而责怪模型,相反地,要从他人的错误中吸取教训。

这是我的(简短)意见,但我相信会有更好的答案 :)

(附注:使用Post方式并不会增加任何安全性)


在我看来,通过安全的 SSL 连接发布帖子并使用临时会话 ID 代替永久用户 ID 仍然是更好的选择。 - r15habh
请解释这个实现中出了什么错误。 - this.josh
Josh和KCR提到了引发这个问题的错误。 - Nathan

4
问题中提到的安全问题与REST、SOAP或Web基本无关,而是与应用程序的设计有关。以下是另一个常见例子:假设电子商务应用程序中有一个屏幕用于显示订单的详细信息。对于已登录的用户,URL可能如下所示:http://example.com/site/orders?orderId=1234。假设订单在该系统的所有用户中都是全局唯一的,那么可以轻松地将该orderId替换为其他有效的OrderId,而不属于该用户并查看详细信息。保护此类信息的简单方法是确保底层查询(SQL等)也添加了用户Id作为连接条件(SQL的WHERE子句中的AND)。在这种特定情况下,良好的应用程序设计将确保URL中传入的帐户ID与相关的已验证会话进行验证。

2

无论您使用GET还是POST,都会在网络上传输相同的数据。这是一个样例GET请求,是提交表单的结果[因为User-Agent值太长,已去除]:

GET /Testing/?foo=bar&submit=submit HTTP/1.1
Host: localhost
User-Agent: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost/Testing/demoform.html

现在,以下是相同的请求,使用POST方式发送:
POST /Testing/ HTTP/1.1
Host: localhost
User-Agent: ...
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip,deflate
Accept-Charset: ISO-8859-1,utf-8;q=0.7,*;q=0.7
Keep-Alive: 115
Connection: keep-alive
Referer: http://localhost/Testing/demoform.html
Content-Type: application/x-www-form-urlencoded
Content-Length: 21
foo=bar&submit=submit

请注意,这是服务器在您提交请求时看到的内容,或者是在拦截请求时中间人攻击者可能会看到的内容。
在GET请求中,我们可以看到请求的第一行中有“foo = bar”和“submit = submit”。在POST请求中,我们必须查看最后一行才能看到...嘿!“foo = bar”和“submit = submit”。同样的内容。
在浏览器层面上,区别体现在地址栏中。第一个请求显示了“?foo=bar&submit=submit”字符串,而第二个请求则没有。想要拦截这些数据的恶意人士并不关心浏览器地址栏中显示的内容。主要的危险在于任何人都可以从地址栏中复制URL并传递它们,从而泄露参数;事实上,这种情况非常普遍。
唯一的方法来防止我们的恶意人士看到这两种类型的请求是在发送给服务器之前对其进行加密。服务器提供公钥,该公钥通过https协议和SSL / TLS使用。浏览器使用该密钥加密请求,服务器使用其私钥解密请求。客户端仍然存在一个问题,即它接收到的密钥是否真的属于运行服务器的人。这必须通过某些带外信任系统进行验证,例如第三方验证或指纹比较等。
所有这些都与REST完全无关。无论您如何做,如果您使用HTTP在网络上传输信息,您都会遇到此问题,并且需要加密请求/响应以防止恶意人员查看它们。

0

POST请求并不比RESTful请求更安全,而RESTful请求也不比GET请求更安全。

有许多措施可以增加应用程序的安全性,这里无法一一列举。维基百科上有很多方法和预防措施。

这里举个例子:不应该使用GET请求进行重要操作,例如提取银行账户,因为如果您已经登录到银行账户中,某人可以设置一个源为http://yourbank.com/actions/withdraw/300USD的假图片,然后URL将被加载,从您的银行账户中提取资金。这可以通过使用POST请求轻松解决。

此外,我们还需要考虑一些进一步的安全问题来处理这个POST请求,因为它也可能被欺骗。


你有关于为什么POST和GET具有相同的安全性的解释或示例吗? - this.josh
@this.josh 我猜这个问题有点主观。当使用正确时,POST比GET更安全,但也有更多限制。POST和GET请求都容易受到XSRF攻击,尤其是在安全规则较不严格的旧浏览器上。在POST请求中,攻击向量不再是图像,而是一些Javascript代码。 - foxy
而且也无法通过代理来抵御攻击者 - 请查看@stand的回答 :-) - Rory Alsop
@Rory,你需要使用代理才能使攻击向量起作用。而且,谁会在正常情况下使用一些不受信任的代理来处理他们的机密数据呢?正确地使用POST而不是GET可以防止XSCF和XSS攻击。 - foxy
我同意POST有所帮助,但你关于代理的评论大多是无关紧要的,因为攻击者在许多情况下可以相对容易地将代理放入路径中。而且,在这种攻击情况下,攻击者是一个有效的经过身份验证的用户,本来就可以使用自己的代理! - Rory Alsop

0

将POST用于安全措施而不是GET只是一种“安全通过模糊性”的使用。实际上,它并不比任何人都可以伪造POST请求的情况更安全。

使用会话ID而不是用户ID也只是另一种模糊安全漏洞的方法,它并没有真正解决问题,因为会话ID也可能被劫持。

在这种特定情况下,通过更改URL使安全漏洞变得极易利用,并不意味着REST的使用是安全问题的原因。

正如其他人所提到的,每当您需要保护REST服务时,HTTPS是开始寻找的地方。


HTTPS也不会好多少,因为您仍然可以在URL中更改用户ID... - tc.
@tc 我并不是想表达HTTPS可以消除授权访问资源的需求。它只是使您能够安全地授权访问。无论用户ID是否在URL中都没有关系。 - Darrel Miller
1
这对花旗银行没有任何帮助,而且在当前的“生态系统”中,HTTPS主要用于防范FireSheep之类的事情。也许花旗银行甚至使用了HTTPS;但我没看到有人给出实际使用的URL。 - tc.

0

我认为REST和所有Web应用程序安全问题非常相似。

在问题陈述中提到的问题被认为是“学校”错误 - 有经验的Web开发人员不会犯这种错误。因此,如果您了解Web应用程序安全性 - 您也将了解REST安全性。

因此,如果您没有任何经验丰富的Web开发人员,请将其添加到您的团队中 - 他将帮助您处理REST。


-1
如果安全是主要问题,只使用 https://POST,永远不要使用 http://GET
这将避免您所描述的攻击以及许多其他攻击,例如会话劫持和简单的窃听线路。
(...并且,避免犯认证时使用 https:// 并稍后切换到 http:// 的错误,这曾经是“事实上的标准”,直到几个月前有人发布了一个明显的工具)

那就是关键。如果您在任何地方都使用https://和POST,且没有例外(否则请遵循基本的安全实践),那么除非破解加密算法,否则不可能验证或冒充另一个用户。而这只是超出了大多数人的范畴。如果您做一些愚蠢的事情,比如通过SSL进行身份验证,然后将其重定向到带有URL中会话ID的普通正常http连接中(直到最近有很多人这样做),那么系统就变得容易攻击。 - Damon
3
不,他们的问题是,如果已认证为一个用户(显然是自己拥有的),则会访问其他用户的数据。这与https或post无关。 - k_b
2
如果URL类似于citibank.com/user/12345,那么您只需要将其更改为citibank.com/user/123456,就可以访问他们的所有帐户信息。这正是HTTP / GET的问题所在。通过HTTPS / POST传输的非平凡长度的随机生成的会话ID,服务器将其映射到相应的用户,这样就无法以这种方式利用它。 - Damon
2
从安全角度来看,使用POST或GET请求方式并不重要。您应该按照符合RESTful原则的方式使用HTTP动词。如果您将它们用作应用程序的安全功能,则需要停止编码并寻找其他工作。使用适当的安全措施来保护您的应用程序,并正确使用HTTP以使设计/维护等更加轻松和快捷。 - James Butler
1
@Damon:不不不不不不!整个花旗银行的问题都是由于弱或不存在的身份验证引起的!使用POST只会产生虚假的安全感。使用SSL可以防止简单的嗅探攻击。POST本身也不维护任何状态。通过使用HTTP头,您认为自己正在维护的任何状态都可以更好地实现。 - James Butler
显示剩余6条评论

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