使用 HTTP 的 Web 应用程序应禁止将 HTTP ``GET'' 或 ``HEAD'' 方法用于查询以外的任何操作。HTTP 包括多种不同的方法;最常用的两种方法是 GET 和 POST。GET 和 POST 都可以用于从表单传输数据,但 GET 方法在 URL 中传输数据,而 POST 方法单独传输数据。
使用 GET 执行非查询操作(例如更改数据、转账或注册服务)的安全问题在于,攻击者可以创建一个包含恶意表单数据的 URL 的超文本链接。如果攻击者说服受害者点击链接(在超文本链接的情况下),或者仅仅是查看页面(在来自 HTML 的 img 标签的图像等包含信息的情况下),受害者将执行 GET。当执行 GET 时,攻击者创建的所有表单数据将由受害者发送到指定的链接。这是一种跨站恶意内容攻击,在 第 7.15 节 中进一步讨论。
如果恶意跨站内容攻击可以执行的唯一操作是让用户查看意外数据,那么这不是一个非常严重的问题。当然,这仍然可能是一个问题,因为可以使用此功能进行一些攻击。例如,由于用户请求意外内容,可能存在隐私泄露的风险;由于看起来请求非法或具罪证性的材料,可能会产生现实世界的影响;或者通过使用户以某些方式请求信息,信息可能会以通常不会暴露的方式暴露给攻击者。但是,如果恶意攻击者不仅可以通过跨站链接导致数据查看,还可以导致数据更改,则可能会造成更严重的后果。
典型的 HTTP 接口(例如大多数 CGI 库)通常会隐藏 GET 和 POST 之间的差异,因为对于获取数据,以“相同方式”处理这些方法很有用。但是,对于实际导致数据查询以外的操作,请检查请求是否为 POST 以外的其他内容;如果是,只需显示一个已填充的表单,其中包含给定的数据,并要求用户确认他们确实要执行该请求。这将防止跨站恶意内容攻击,同时仍然使用户能够方便地通过单击一下来确认操作。
实际上,HTTP 规范强烈建议这种行为。根据 HTTP 1.1 规范(IETF RFC 2616 第 9.1.1 节),“GET 和 HEAD 方法不应具有执行检索以外操作的意义。这些方法应被视为“安全”的。这允许用户代理以特殊方式表示其他方法,例如 POST、PUT 和 DELETE,以便用户意识到正在请求可能不安全的操作。”
为了公平起见,我应该指出,这并没有完全解决问题,因为在某些浏览器(在某些配置中),脚本化的 POST 请求可以执行相同的操作。例如,想象一下一个启用了 ECMAscript (Javascript) 的 Web 浏览器接收到以下 HTML 代码片段 - 在某些浏览器上,仅显示此 HTML 代码片段将自动强制用户向攻击者选择的网站发送 POST 请求,并带有攻击者定义的表单数据
<form action=http://remote/script.cgi method=post name=b> <input type=hidden name=action value="do something"> <input type=submit> </form> <script>document.b.submit()</script> |