如何保护Ajax链接请求?

时间:2015-04-24 08:15:16

标签: javascript php jquery ajax

想象一下下一个场景:用户想要注册到网页并填写表单。当他填写表单时,如果字段有效,jQuery会继续检查regular expression等等。

将电子邮件作为用户在注册登录后将使用的主键,需要使用Ajax检查电子邮件字段,以便用户知道该电子邮件是否已注册。我想用Ajax检查它,以避免发送完整的表单并清空它,刷新页面等...

因此,当用户结束填写电子邮件字段时,会将Ajax请求发送到服务器,类似于下一个链接:

example.com/check.php?email=abcdefg@gmail.com

当check.php收到电子邮件时,它询问数据库是否存在,如果用户存在则返回如下信息:User already exists或如果用户不存在则返回null

问题是:如果有人通过我的.js挖掘并发现类似的链接,他们可以使用该链接发送大量请求以查明是否存在这些随机电子邮件。这可能导致大量使用数据库,或者在最糟糕的情况下甚至导致崩溃和私人信息泄露。

有人可以做一个巨大的for循环检查电子邮件,如:

//Getting the response of the next links
example.com/check.php?email=aaaaaaa@gmail.com // Returns null
example.com/check.php?email=aaaaaab@gmail.com // Returns null
example.com/check.php?email=aaaaaac@gmail.com // Returns null
example.com/check.php?email=aaaaaad@gmail.com // Returns User already exists

-------------------------------------------- -------------------------------------------------- --------------------------------------

自从我上次接受答案以来,我一直在调查这个并找到了避免这种行为的解决方案。以下代码适用于JAVA,但逻辑可应用于任何其他服务器端语言。

在对服务器执行任何ajax请求之前,我向服务器请求令牌。这个令牌看起来像这个fmf5p81m6e56n4va3nkfu2ns8n它是由一个简单的方法制作的,然而它可以更复杂,但这很好。

public String getToken() throws UnsupportedEncodingException {
    return new BigInteger(130, new SecureRandom()).toString(32);
}

当请求令牌时,服务器不仅返回令牌,而且还返回一个小脚本,以防有人使用浏览器检查元素(和浏览器导航栏),这样脚本将运行并且令牌将被清除。 Servlet返回如下内容:

_html += "<head>"
    + "<script> "
    + "window.onload=function(){\n"
    + "       document.body.innerHTML = \"\";\n"
    + "    }"
    + "window.location.href='http://mywebsite.com' "
    + "</script>"
    + "</head>"
    + "<body>"
    + "[" + token+ "]"
    + "</body>"
    + "</html>";

首先将身体清空,然后导航回我们想要的任何地方。然而,javascript / jquery将整个内容作为字符串捕获,然后我只是在[和]之间提取字符串。此令牌仅适用于下一个请求,因此每个AJAX请求都将具有其唯一令牌。在第二个请求中,删除刚刚使用的令牌。

获得令牌后,我将其作为参数添加到我请求的任何链接中,如下所示:

ajaxRequestObjet = $.ajax({
    url: "http://localhost:8084/mywebsite.com/servlet", //<-- local tomcat server
    method: "POST",
    data: "type=AJAX&page=some-article&token=fmf5p81m6e56n4va3nkfu2ns8n"
});

此方法适用于手动检查网站并尝试使用链接的人,但是自动执行此操作的java / php / IIS服务器呢?

为此请求标题!像这样:

boolean isAjax = "XMLHttpRequest".equals(request.getHeader("X-Requested-With")); 

只有当XMLHttpRequest存在时才会成立....

最后要记住一件事。确保'Access-Control-Allow-Origin' header is NOT present in your app确保服务器中的任何javascript都不会获得服务器资源。如果此标头不存在,Chrome将返回此信息:

XMLHttpRequest cannot load http://localhost:8084/mywebsite.com/servlet. No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access.

Java服务器在tomcat中,我有另外一个apache用于这个测试,这是apache中存在的小html,它给出了上面的错误:

<html>
<head>
    <script src="http://code.jquery.com/jquery-latest.min.js" type="text/javascript"></script>

    <script>
    ajaxRequestObjet = $.ajax({
        url: "http://localhost:8084/mywebsite.com/servlet",
        method: "POST",
        data: "type=AJAX&page=Token"
    });

    ajaxRequestObjet.done(function (msg) { 
        alert(msg);
    });

    </script>

</head>
<body>
</body>
</html>

8 个答案:

答案 0 :(得分:9)

您网站上的JavaScript代码是在用户的计算机上执行的,因此您无法阻止他挖掘您的代码。即使您使用代码混淆器(例如,https://www.javascriptobfuscator.com/),黑客也可以调试您的应用程序并记录发送到服务器的所有请求。

安全相关的一切都必须在服务器上进行。您可以限制来自特定IP地址的请求数量。

答案 1 :(得分:9)

虽然你无法控制这100%...但有一些选择..

尝试使用人们用于Captcha脚本的相同方法。

基本上当用户加载表单/页面时..你在他们的PHP会话中生成一个随机字符串/ id并存储它..当他们发送ajax请求时,让你的ajax检查还附加字符串/ id并要求它在允许检查执行之前返回500或其他什么的标题..

对会话使用此方法,您可以设置允许的检查限制(例如5),一旦用户尝试了超过5次检查,他们需要重新加载页面或执行人工检查(例如Captcha)。然后重置他们的计数..甚至允许在1小时/每个IP或其他内容中总共说30个。

还可以在完成ajax检查时触发智能事件,例如字段/标签更改或按下按钮..或者当检测到有效的电子邮件时...但是.com.au会触发两次。

基本上就是这样,即使有人嗅探你的JS文件并试图自动化电子邮件检查器..这将要求他们找到一种方法来附加你生成的字符串/ id,并限制他们执行的请求数量。

除此之外,你可以轻松做到更多......但还有一些其他的想法。

他们中的大多数都会使用PHP会话/ cookie。例如,如果他们检查并找到3个电子邮件地址。然后再次将其设置为限制并强制他们要求手动提交或其他。< / p>

了解上述建议如何适用于您,任何问题都可以随时提出。但是可能需要一两天才能回复周末。还要研究Captcha脚本如何为他们提供大量的源代码..因为他们的工作理念相同。

时间延迟只会看起来很糟糕/使您的网站看起来很慢/等待用户等待响应。

你需要限制每个会话/ IP地址的查找量。否则总有办法通过这些检查..基本上一旦达到限制..强制用户/ ip /会话等待几分钟/小时并使用Captcha脚本验证它们,因此无法编写脚本...

Javascript安全/隐藏源

虽然你不能真正做到这一点,你可以做某些事情使用带有JS头的PHP页面生成JS ..所以<script src='myjscode.php'></script>这允许PHP检查有效的会话..所以停止外部请求到一定程度..但这对于允许JS仅在成员资格/登录后面可用是非常有用的。

多次检查/如果可能,在这种情况下

根据您的方法,这是否由用户检查他们是否已拥有帐户?如果是这样..你可以将电子邮件检查与其名称/国家/年龄/ dob等结合起来......所以他们需要选择两个或三个正确的匹配值才能从ajax调用中获得检查/响应?

也许不是你的情况,但只是想也会加上这个。

答案 2 :(得分:1)

您可以使用与CSRF tokens类似的方式防范暴力攻击:

为每个客户端会话分配服务器生成的ID。对check.php的每个请求都应包含此ID。

check.php应拒绝不包含ID的请求,或者包含服务器未生成的ID(以防止使用欺骗ID进行攻击)。它还应对ID进行速率限制 - 如果给定的ID在(比方说)最后一秒发出请求,或者给定ID在10秒间隔内发出超过n个请求,则应返回错误响应。这可以防止来自多个IP地址的单个会话的请求。

您还应该按IP地址进行速率限制,以通过打开大量Web应用程序会话来防止暴力破解。

您无法阻止攻击者查找特定电子邮件地址的单个或少数 - 这是此类验证的固有风险。

答案 3 :(得分:0)

首先:我对邮件地址进行URL编码。 ap1019@sharifvm:~$ g++ myt.cpp myt.cpp: In function âint main()â: myt.cpp:12:11: error: ânullptrâ was not declared in this scope float *p=nullptr; ^ ap1019@sharifvm:~$

广告您的问题:调用check.php时,您可以

  • 检查用户的会话及其IP是否在最后几秒内发送了请求
  • 如果没有,请将用户的会话,用户的IP以及当前时间戳写入帮助程序表加上cookie并点击您的数据库
  • 如果是,则阻止请求

但我担心这会让你免于欺诈,因为每个人都可以检查你的JavaScript,如果有人想要利用这个,他会找到方法。

答案 4 :(得分:0)

这种类型的攻击可以像任何其他暴力攻击一样对待,唯一有效的解决方案是使用Captcha。但是当然,Captchas对用户体验不利,所以你必须考虑额外的安全性是否值得,特别是对于不太可能发生的攻击。也就是说,您可能希望在注册表上使用Captcha,以防止机器人创建帐户。

对于攻击者来说,这种攻击的成本很高。有数十亿个可能的电子邮件地址需要测试。如果有问题的网站特别敏感,例如某种成人网站,攻击者希望敲诈他发现的用户,那么这个网站的价值可能会非常大。

<强>的CloudFlare

不如Captcha解决方案,但CloudFlare的DDoS系统可能会检测到并阻止暴力攻击。此外,CF可以强制Tor用户在访问您的站点之前解决Captcha,这可以防止攻击者使用Tor作为攻击的载体。

IP速率限制

基于IP的速率限制存在问题,因为如果攻击者决定承担如此大的任务,他可能会使用Botnet或其他多台计算机系统来发起攻击。

考虑一个大型组织,例如大学,所有用户共享公共IP。其中一个用户在您的网站上发起攻击,并阻止他的IP,并在阻止其他人的进程中。该对策实际上可用于发起DoS攻击。

会话ID / CRSF令牌

绝对不是解决方案,因为攻击者需要首先向页面发出请求,以获取令牌。这是一个额外的请求,但只给攻击者带来不便。

答案 5 :(得分:-1)

check.php应该取决于设置,只能在内部访问,或验证连接的位置。看一下上一个问题 - 我希望它可能是您正在寻找的东西。 how to verify the requesting server in php?

答案 6 :(得分:-1)

如果检测到无效CSRF token,则可以使用CSRF token并从脚本中提前退出。几乎(如果不是全部)PHP框架都支持这个。

另请查看来自安全社区的此问题:https://security.stackexchange.com/questions/23371/csrf-protection-with-custom-headers-and-without-validating-token

答案 7 :(得分:-1)

解决此问题的一种方法可能是:

假设您有ajax请求,请求您的服务器接收来自特定用户或客户端的响应。您可以在数据库中拥有一个表,为每个用户或散列值提供唯一标记,每次用户向服务器发出ajax请求时都可以检查该标记。如果令牌值与用户请求值匹配,则他是真正的用户。您还可以在桌面上记录他的请求数量,以确保他提出合法请求。我承认它可能会降低您的应用程序性能,但这是安全的选择。注意:您需要在HTML页面上检索令牌以使用ajax发送它。

请评论以了解更多信息。我一直在使用这种方法,直到现在都没有问题。

示例: