如何防止自动AJAX攻击

时间:2011-01-25 04:31:14

标签: php mysql security csrf

如何防止用户自动发帖/垃圾邮件?

这是我的方式这样做,每个页面请求的新php会话,它有自己的限制,没有多重协议。

我为每个页面使用了新会话作为对CSRF和自动攻击的防御。假设我们有一个论坛,它使用AJAX发布线程,并通过PHP SESSION进行验证。

add_answer.php?ID = 123

<?php
if(!is_ajax()){// function that determines whether the request is from ajax (http header stuff)
$_SESSION['token'] = md5(rand());
}
//some ajax request to ajax.php?id=123
?>

ajax.php?ID = 123

<?php
if($_SESSION['token'] == $_GET['token']){
echo 'MYSQL INSERT stuff';
}else{
echo 'Invalid Request';
}
?>

除非用户在另一个标签页上打开page.php?id = 456,否则ajax会在ajax.php上返回'无效请求'?id = 123 This is related to another question I asked。他们建议一直只使用一个会话哈希,直到他/她注销 - 只有会话重新生成。如果令牌是相同的,则USER可以简单地绕过它并执行自动攻击。有什么想法吗?

无论如何 以你的方式 阻止自动AJAX攻击?

PS:

  1. 不要用验证码折磨用户。
  2. Google未能向我展示有用的内容。
  3. 以此为挑战。
  4. 或者至少投票选出你认为很棒的专家答案

3 个答案:

答案 0 :(得分:2)

只要浏览器处于打开状态,您就会反对让会话保持开放,这是自动攻击的问题。不幸的是,刷新每个页面加载的令牌只会阻止大多数业余攻击者。

首先,我假设我们正在讨论专门针对您网站的攻击。 (如果我们谈论的是那些只是漫游并提交各种形式的机器人,这不仅会阻止它们,而且会有更好更简单的方法。)如果是这样的话,那我就是针对我的网站,这是我的机器人会做的事情:

  1. 加载表单页面。
  2. 在表单页面上读取令牌。
  3. 使用该令牌提交自动请求。
  4. 转到第1步。
  5. (或者,如果我对你的系统进行了足够的调查,我会发现,如果我在每个请求中包含“这是AJAX”标题,我可以永远保留一个令牌。或者我会意识到令牌是我的会话ID,并发送我自己的PHPSESSID Cookie。)

    这种在每个页面加载时更改令牌的方法绝对没有任何阻止实际想要攻击你的人。因此,由于令牌对自动化没有影响,请关注其对CSRF的影响。

    从阻止CSRF的角度来看,创建一个令牌并维护它直到用户关闭浏览器似乎可以实现所有目标。简单的CSRF攻击失败,用户可以打开多个选项卡。

    TL; DR:每次请求刷新令牌一次不会提高安全性。寻求可用性并在每个会话中执行一个令牌。


    然而!如果您非常担心重复的表单提交,无论是意外还是其他方式,这个问题仍然可以轻松解决。答案很简单:为两个不同的工作使用两个令牌。

    第一个令牌将保持不变,直到浏览器会话结束。此令牌用于防止CSRF攻击。此用户使用此令牌提交的任何内容都将被接受。

    将为每个加载的表单唯一生成第二个标记,并将其存储在用户打开表单标记的会话数据的列表中。此令牌是唯一的,并且在使用后无效。此用户使用此令牌提交的内容将被接受一次且仅一次。

    这样,如果我打开表格A的标签和表格B的标签,每个人都有我的个人反CSRF令牌(CSRF照顾)和我的一次性表格令牌(表格重新提交照顾)。解决这两个问题对用户体验没有任何不良影响。

    当然,您可能会认为实现这么简单的功能太多了。无论如何,我认为它是。无论如何,如果你想要它,都会有一个可靠的解决方案。

答案 1 :(得分:1)

如果您试图阻止让一个客户端DoS,那么一个不常见但可行的策略是在请求中包含hashcash令牌(已经有PHP and JavaScript个实现)。

为了防止破坏选项卡式浏览和返回按钮,理想情况下,您希望hashcash令牌的挑战包含每会话防伪标记和为每个请求新生成的唯一性部分。如果您的代币费用很高,为了尽量减少对可用性的影响,请在您花费前一个代码后立即开始预先计算您网页中的下一个代码。

这样做会限制客户端生成有效请求的速率,因为每个hashcash令牌只能使用一次(这意味着您需要将附加到会话的有效,已用完的hashcash令牌的缓存保留到防止无限次重复使用单个令牌),它们无法在会话开始之前计算(因为随机防伪值),并且生成每个新的有效令牌需要花费大量的CPU时间,但只需要很简单验证一个人的时间。

虽然这并不妨碍您的AJAX API 本身的自动化,但它确实限制了API的大量锤击。

答案 2 :(得分:1)

如何阻止用户自动发帖/垃圾邮件?

这可能会以与常规请求相同的方式解决。每页加载一个令牌并停止新选项卡可能过度。当然,每个表单的时间敏感令牌可以在某种程度上缓解CSRF攻击。但除此之外,最好定义和实施提交策略引擎,而不是限制用户体验。

冒着让所有人听起来浮夸或贬低的风险:通常网站使用基于积分的奖励系统,例如“业力”或“徽章”。这样的系统实际上添加到用户体验,因为提交然后成为用户的一种游戏。他们可能经常限制在特定时间范围内仅向受信任的用户或最大数量发布提交的能力。看一下SO系统的好用例。

一个非常基本的答案,只是展示了一些常见的网站政策:

  • 如果用户在过去的y分钟内超过了x个帖子的数量,则拒绝数据库插入并显示“抱歉,自上次发布以来太早”警告。这可以通过在允许新记录插入之前在给定的最近时间段内向DB查询用户的帖子数来实现。
  • 如果用户没有特定的业力门槛 - 例如,新用户或反复标记为垃圾邮件发送者的用户 - 拒绝DB写入并显示“抱歉,您在这里的时间不够长”或一个“抱歉,你垃圾邮件太多了”的警告。这可以通过在允许新记录插入之前向DB查询总共用户的“业力”来实现,该业务在单独的表或站点模块中管理。
  • 如果网站规模小且易于管理,仅由一个或两个用户审核,请先审核并批准所有新用户请求和帖子。这可以通过在移动到实时表之前将新条目保存在单独的表中以供查看,或者通过在主表上具有“已批准”标志列来实现。

此外,可以对每个用户保留违反政策的计数,如果超过某个时间段内的某个点,您可以选择让它们在特定时间段内自动禁止。如果您愿意,可以通过拒绝与该用户相关的所有数据库写入来实施禁令。

在关于“http header stuff”的说明中,标题仅用于最好的猜测,并且客户要求提供礼貌。它们与饼干一样难以伪造,锻造饼干只需点击鼠标即可。老实说,我个人不会有任何其他方式。