PHP表格安全与Referer

时间:2010-05-15 19:12:37

标签: php security xss

我正在组建一个可供用户输入的网站。我想知道是否写了一个函数:

if(getenv("HTTP_REFERER") != 'http://www.myURL.com/submitArea'){
        die('don\'t be an jerk, ruin your own site');   
    }else{
        // continue with form processing    
    }

足以阻止提交跨站点表单。

编辑:如果没有,阻止从其他主机提交表单的最佳做法是什么?

6 个答案:

答案 0 :(得分:10)

Nope - HTTP_REFERER可以在客户端自由欺骗,并不是请求来自何处的可靠指标。

更新:我误读了关于跨站点伪造的部分:为此,检查引用有效的安全措施,因为CSRF依赖于指向受保护页面的被操纵链接(被攻击用户拥有特权)。用户@Rook是正确的。

唯一的例外是,如果攻击可能发生在受到攻击的Web应用程序中,例如通过注入恶意JavaScript代码。在这种情况下,引用检查是无用的,因为攻击来自“安全”URL ,但可以说是基于会话或一次性令牌的解决方案,因为令牌已达到可以轻松检索恶意JavaScript。

但是,使用一次性令牌非常有利于防止此类攻击,因为某些代理会删除HTTP_REFERER

答案 1 :(得分:3)

使用SESSION很可能是阻止提交跨站点表单的更好途径。

答案 2 :(得分:3)

实际上是的,根据OWASP CSRF Prevention Cheat Sheet,在大多数情况下,检查引用程序足以修补CSRF漏洞。虽然在OWN BROWSER上欺骗引用者是微不足道的,但是不可能在另一个浏览器(通过CSRF)上欺骗它,因为它breaks the rules

事实上,在内存稀缺的嵌入式网络硬件上查看引用器非常常见。摩托罗拉为他们的Surfboard Cable调制解调器做了这个。我知道这第一手,因为I hacked them with csrf然后他们使用引用检查修补它。此漏洞的严重度指标为13.5,根据国土安全部的说法,这是迄今为止发现的最危险的CSRF漏洞,也是有史以来最危险的1000个软件漏洞。

答案 3 :(得分:3)

虽然在另一个用户的浏览器中欺骗 Referer是不可能的,但是很容易欺骗缺乏引用者(例如,使用元刷新),此外某些用户代理根本没有发送Referer。

因此,要么您允许使用missing-referrer并拥有非防水XSRF保护,要么要求与您的网站匹配的引荐来源,在这种情况下,您会对可访问性产生重大影响。如果使用该脚本的唯一人员是您,并且您知道您将始终使用可靠地传递引用者的浏览器/防火墙/代理/等组合,那么该命中可能是可接受的。但是对于你期望其他人使用的任何东西,通常都不是一个好主意。

Referer是一种相当弱的反XSRF机制。最好使用服务器发出的每用户/事件令牌,必须返回服务器验证提交。

  

$ query =“SELECT * FROM users WHERE name ='$ name'”;

潜在的SQL注入漏洞。请使用mysql_real_escape_string或参数化查询。

  

input.setAttribute('name','add_bar');

     

input.setAttribute('value','');

不要在HTML属性上使用setAttribute。在某些情况下,IE中存在阻止它工作的错误,并且有些属性不符合您的想法。例如,设置value属性与设置value属性相同。该属性保存表单字段的当前值;该属性仅保存字段的“默认值”,如果使用<input type="reset">,则将重置该字段。这将映射到defaultValue属性。在某些浏览器中,设置默认值也会设置值,但这是非标准的,不能依赖。

使用DOM Level 1 HTML属性,它们更具可读性和可靠性:

input.name= 'add_bar';
input.value= <?php echo json_encode(generate_session_token(), JSON_HEX_TAG); ?>;

使用json_encode为JavaScript文字创建值。虽然您可以确定MD5-sum不包含JS特有的字符,如'\,或</序列结束<script>块(对此HEX_TAG参数是保护),知道会话令牌可能包含的内容不是输出模板的工作。这是将任何字符串输出到<script>块的安全方法。

有关生成反XSRF令牌的方法,请参阅this question,该会话或数据库中不需要额外的令牌存储。

答案 4 :(得分:2)

是的,它是安全的

不幸的是,holy text鼓励提供禁用引荐来源的选项(但您仍然无法创建自己的引荐来源机制);事实上,有人可能会禁用他浏览器上的推荐人,从而拒绝自己访问您的网站。

您的解决方案是安全的,但如果您的网站仅适用于推荐人,则用户可以合法地投诉。

这非常令人难过,因为它现在意味着没有理智的方式来确保您的网站不能抵御CSRF。

<强>替代

您唯一能做的就是在每个经过身份验证的请求中为您的网络服务添加nonce。但这有点危险,因为您必须确保Web服务上的每个请求点都验证了nonce。但是,您可以使用框架为您执行此操作,以稍微迁移此烦恼。 Stack Overflow本身似乎使用了nonces。

<强>然而

推荐人原则上更安全一点,因为你可以应用一个全局规则,除非推荐人在同一个域中,否则不会发出任何请求。如果您愿意放弃禁用引荐来源的用户,这是可以接受的。

与人们在这里所说的无意义相反,您无法使用来自非特权浏览器代码的欺骗性标头发出HTTP请求。正如预期的那样,Flash能够绕过反依赖引用者的反csrf一次这样做,但它被修补了。为什么要打补丁?因为HTTP RFC规定了引用者的内容,因此,不允许在客户端代码中更改它的含义,以免客户端不安全。

有人甚至声称Java applet可以通过HTTP向另一个域发出任意标头,但事实并非如此,因为不允许使用沙盒的Java applet向任何发出请求,除非加载它的域。在任何人纠正他之前,他迅速删除了他的评论......

案例

Web浏览器是HTTP客户端。 HTTP客户端必须符合HTTP RFC;因此,它必须遵守RFC声明引用标头应该是什么样子。由于Web浏览器是HTTP客户端,因此嵌入在Web浏览器中的任何应用程序都不能能够发出违反HTTP协议的请求。事实是每次违反标准都是一个潜在的安全漏洞。

在任何情况下:没有正确的方式来确定请求来自您的域或攻击者域的天气。这只是网络中许多令人遗憾的缺陷之一。您必须使用这些提到的解决方法之一。

答案 5 :(得分:-3)

实际上,您可以为该表单使用动态地址。就像当用户转到您的表单时,您将他转发到具有随机地址的页面,例如www.something.com/form.php转发到www.something.com/form.php?13mklasdkl34123,其中为每个用户和商店随机生成13mklasdkl34123它在$ _SESSION中。收到表单提交后,您可以检查引荐来源地址是您为用户生成的地址。引用者可能是欺骗性的,但动态引用不能因为欺骗者无法知道地址,除非他(单独)访问您的表单页面。