【问题标题】:How can I better protect my php, jquery, ajax requests from malicious users如何更好地保护恶意用户的 php、jquery、ajax 请求
【发布时间】:2011-05-10 18:41:55
【问题描述】:

我通过jquerys的getJSON方法发送了很多数据,一个函数的例子是

function doSomething(sid){
    if(sid){

    $.getJSON("ajax/ajaxDoSomething.php",{sid:""+sid+""}, function(data){
        //alert(data);
        if(data.success == true){
            $('#add_vote_div').html('vote received');
            $('#list_data_div').html(data.html);
        }
        else{
            $('#add_vote_div').html(data.message);
        }
    });
  } 
}`

问题是任何人都可以查看源代码并看到将 GET 数据发送到的 php 文件的位置,因此您只需将浏览器指向那里并将数据附加到 URL。我会检查数据以确保其数据类型正确,但我根本不希望用户能够访问该 url。

我想也许把所有的 ajax 文件放在主文档根目录后面,这样可以工作,但是 jquery 不能链接到绝对路径,比如

$.getJSON("var/www/ajax/doSomething.php",{sid:""+sid+""}

(主文档根目录是 var/www/html/)

如果他们制作了一个更好的 $.postJSON,但它不存在,有什么想法吗?

【问题讨论】:

  • "var/www/ajax/doSomething.php" 是一个服务器端路径 - 在服务器外部无法访问它,因此 JavaScript 永远无法直接访问它。
  • @Skilldrick:是的,如果是的话,会是个问题。 :-)

标签: php security jquery


【解决方案1】:

您需要做的是打击一些特定类型的攻击。即使对于非常引人注目的网站,这通常也足够了。对于一个不是最大的网站之一的网站,这些东西应该足以阻止脚本小子。

跨站请求伪造:

本质上,这就是您在最初的帖子中试图指出的内容。正如您所指出的,这种攻击需要找出可以执行某些用户特定操作并直接调用它的 URL。或者,更难防范的是,通过诱骗登录用户点击导致该用户特定操作的链接来完成。

第一种可以通过使用会话密钥标记每个呼叫并确保其有效来阻止。但是,这并不能阻止第二次。

好消息是这种攻击可以通过作为 url 一部分的秘密值来阻止,该值经常更改,在后端被记住足够长的时间以确保它被正确调用。我们在这里讨论的是 AJAX,所以最简单的方法是在整个页面加载时创建一个随机数秘密值。对于传统形式也是如此,请记住这一点,并在创建新的秘密值之前检查旧的秘密值。您在会话数据中保存此值并将其附加到所有 AJAX 调用或来自后续页面的表单提交。如果它们匹配,则它是同一用户。如果没有,您只需忽略该请求。

每次用户加载一个全新的页面时,都会为该用户创建一个新密钥。这意味着只有攻击者是用户,他们才能找到这个值。这意味着你已经击败了这种攻击类型。

跨站脚本:

XSS 攻击的不同之处在于它们是 CSRF 攻击的反面,等等。这很容易。只需确保来自用户或数据库的所有数据都通过一些将 html 字符转换为实体的函数传递,例如 PHP 中的htmlentities(),然后再将其显示在您的网站上。这将阻止用户使用 JavaScript 将用户重定向到操作链接或其他恶意内容。它还将防止 Flash 和其他对象嵌入到页面中。

不幸的是,它还会阻止在 cmets 或文章正文中使用任何 HTML。这可以通过非常严格的标签白名单或某些版本的替代代码来规避。 (如本站使用)

确实没有什么好的方法可以尝试创建黑名单。我试过了。我们都试过了。它们不起作用。

SQL 注入:

我不会在这里详细介绍,但是,与可能造成的损害相比,上述攻击根本算不上什么。了解它。

除此之外,您还应该遵循一些准则。例如,永远不要陷入相信您发送到 javascript 的数据会以您期望的方式返回的陷阱。假设最坏的情况。这同样适用于传统形式。无论您如何加密,发送给用户的数据都应该被视为来自用户的全新数据。

如果您有论坛帖子的编辑方法。检查提交用户是否有权编辑该帖子。确保他们已登录。确保密码匹配。确保他们输入的数据没有 SQL 注入。

做这些事情,你将阻止绝大多数攻击。

不是全部。 FireSheep 使用的攻击类型仍然可以通过,任何针对用户而不是您的站点的攻击也将通过。您可以使用 https 而不是 http 来防止 FireSheep。但即便如此,对于各种针对用户的攻击也无济于事。例如从他们的机器上窃取会话 cookie,或者对他们的机器进行物理访问。

【讨论】:

  • 在我服务器上每个页面的顶部,我启动了一个会话验证过程,我使用 sha512 作为默认哈希方案,此外我添加了一个 $_SESSION['fingerprint'] 变量,它是用户代理的 md5 哈希和静态盐。因此,在考虑任何请求之前,这将需要被劫持。 $_POST 或 $_GET 的每一部分都使用 strip_tags() 擦洗并使用 mysqli_real_escape_string() 进行转义,我想看看跨站点请求伪造,我认为 docs.jquery.com/Tutorials:Safer_Contact_Forms_Without_CAPTCHAs 是你指的?
  • 你最终会对 strip_tags() 感到失望,因为它在某些情况下会遗漏某些东西。谷歌在那。并且 CSRF 不会受到该 jQuery 链接的保护。但是,只要知道它叫什么就可以帮助您找到针对该问题的“秘密”解决方案。
  • 使用 MVC,我将 ajax 调用转换为 POST 并需要防伪令牌进行验证。
【解决方案2】:

无法使用 JavaScript 保护数据。因为客户端代码中的所有代码都可供攻击者使用。您可以尝试通过复杂的 JSON 来屏蔽数据连接。但是每个脚本小子都可以轻松使用wireshark并查看源代码并查看数据是如何生成的或发送到哪里。

解决方案是使用闪存对数据进行哈希处理。创建一个小闪存文件来接收数据,对其进行 SALT 处理并使用 MD5 对其进行加密。而不是将其发送到服务器。攻击者能够看到数据,但它是加密的。

攻击者仍然可以尝试反编译flash。

【讨论】:

  • 做过一次,这是保护 ajax 通信的唯一方法。如果您需要对所有流量进行类似隧道的加密,或者使用 HTTPS
  • 看来“Ran Bar-Zik 先生搞错了”:stackoverflow.com/questions/5036975/secure-ajax-with-flash
  • 我从来没有说过这是安全的,数据仍然在客户端接收,反编译flash很容易。
【解决方案3】:

它只是略微提高了黑客攻击的门槛,但您可以通过jQuery.ajax(这是一个链接)或jQuery.post(就是这样)发布 JSON。 jQuery.getJSON 只是 ajax 的包装器(.post.get 也是如此)。来自getJSON docs

这是一个简写的Ajax函数,相当于:

$.ajax({
    网址:网址,
    数据类型:'json',
    数据:数据,
    成功:回调
});

因此,要实现您的 postJSON 概念,您只需为其添加一个 type 参数:

$.ajax({
    url:      url,
    type:     'POST',   // <== the new bit
    dataType: 'json',
    data:     data,
    success:  callback
});

如果你真的想,你可以添加一个postJSONjQuery 对象,预处理参数,然后调用$.ajax。这基本上是从the jQuery source 复制粘贴,但将.get 切换为.post

if (!jQuery.postJSON) {
    jQuery.postJSON = function( url, data, callback ) {
        return jQuery.post(url, data, callback, "json");
    };
}

请注意,伪造 POST 仍然很容易。不像 GET 那样简单,但仍然很容易。

【讨论】:

  • 在 Ajax 请求中,无论是 GET 还是 POST,GET 只是意味着您可以在浏览器中直接输入 URL 并查看响应,您仍然可以使用 cURL 伪造 POST 请求。
  • 是的,我知道你也可以伪造 POST,但它比 GET 更好。
  • 如果恶意用户不将自己的数据提交到 PHP 文件很重要,那么这个解决方案就毫无用处 - 它只会阻止那些不想使用 cURL 的黑客。
  • @phpNutt: "在 Ajax 请求中,GET 还是 POST 无关紧要..." 当然可以。 GETPOST 是不同的 HTTP 动词,定义不同,代理处理不同,浏览器处理不同。使用XMLHttpRequest 会改变浏览器部分,但几乎没有其他改变。 GET 请求应该(必须?)是幂等的,例如; POST 请求通常不是。
  • @Brian:对于知道自己在做什么和/或有工具的人来说,这真的非常容易。基本上,您必须将 所有 传入用户输入视为可能受到损害、伪造和/或恶意的。您尽最大努力进行服务器端验证,保存和监控日志,保存备份,并且完成了您希望最好的事情。 :-)
【解决方案4】:

为了更好地保护您的服务器免受恶意用户的侵害,您需要检查每个请求附带的数据。即使您混淆了客户端代码,也始终可以使用其他方式跟踪请求的去向。即使您切换到 POST 请求,也可以手动创建这些请求。

【讨论】:

    【解决方案5】:

    查看this question 以讨论非常相似的问题。真的不容易让别人冒充你的 JavaScript,因为你的 JavaScript 是完全向世界开放的。

    【讨论】:

      【解决方案6】:

      您将需要查看用于防止跨站点请求伪造 (CSRF) 攻击的类似方法。 phpsec.org 有一些很好的examples,您可能能够适应您的 Ajax 请求。

      【讨论】:

        【解决方案7】:

        其实通过 ajax 做 post 请求很简单,参考 jquery 的通用 ajax 函数即可。但这并不能回答您的问题,因为伪造发布请求与伪造获取请求几乎一样容易。 您无法可靠地隐藏脚本与之通信的服务器 url。因此,如果这导致任何安全问题,您必须重新考虑您的网站或应用程序的安全架构。

        【讨论】:

          【解决方案8】:

          如果这些 AJAX 请求返回敏感数据,那么您将有某种形式的身份验证,以便只有来自您的应用程序的真正请求返回数据;任何人只要从第三方网站点击 URL 就会收到错误代码。

          希望对您有所帮助。

          【讨论】:

            【解决方案9】:

            解决方案两部分方法是将所有 ajax / json 请求发送到重定向伪地址文件夹下的我的 php 文件。然后测试请求的域。

            yourdomain.com/somePsuedoFolder/?postRequestData....

            然后你在 .htaccess 中放置一个重定向,扫描“somePsuedoFolder”并重定向到 您的长格式 php 文件位置。这样你就问什么,这样人们就看不到你服务器上文件的位置。

            当然,您仍然需要与使用您的 Psuedo 地址发送不需要的请求的人打交道。但是,这样他们只有有限的关于您服务器上的文件夹结构的信息,并且不太可能对该位置的其他文件进行攻击(通过随机文件名目标测试)。

            【讨论】:

              【解决方案10】:

              我为同一个问题做了什么,转录到你的例子中;

              • 在调用Javascript的PHP控制器中生成一个随机数;将其连接到您传递给 Javascript 的变量并将其放入会话中,例如:
              $randnum = rand(1,100000);
              $_SESSION['sidrandnum'] = $sid.'-'.$randnum;
              
              • 在 Javascript 中,使用这个新变量来替换你的 sid

              • 在数据提供者中,如果随机变量不相同,则不返回任何内容

              function dataprovider($sidrandnum) { 
              
              if ($sidrandnum != $_SESSION('sidrandnum')) 
                  return;
              $sidrandtable = explode ('-', $sidrandnum);
              $sid = $sidrandtable [0];
              ...
              

              这样,只能在同一服务器执行中访问数据:您可以看到数据源,而只能看到最终用户页面已经显示的内容。

              【讨论】:

                猜你喜欢
                • 2014-06-01
                • 2016-01-30
                • 2011-02-11
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2010-10-25
                • 2017-03-13
                • 1970-01-01
                相关资源
                最近更新 更多