我怎样才能更好地保护我的恶意用户的php,jquery,ajax请求

时间:2010-11-16 11:53:39

标签: php security jquery

我通过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。我检查数据以确保其数据类型正确,但我不希望用户能够访问该网址。

我想也许把所有ajax文件放在主文档根目录后面会起作用但jquery无法链接到绝对路径,如

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

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

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

10 个答案:

答案 0 :(得分:18)

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

跨站点请求伪造:

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

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

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

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

跨站点脚本:

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

不幸的是,它还会阻止在评论或文章正文中使用任何HTML。这可以使用非常严格的白色标签列表或替代代码的某些版本。 (例如本网站使用)

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

SQL注入:

我不会在这里详细说明,但是,足以说上述攻击与这可能导致的伤害无关。了解它。

除此之外,您应遵循一些指导原则。比如永远不要陷入相信你发送到javascript的数据将会回归你期望的陷阱。假设最坏的情况。传统形式也是如此。无论您如何加密数据,都应该处理发送给用户的数据,就好像它是来自用户的全新数据一样。

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

执行这些操作,您将停止绝大多数攻击。

不是全部。 FireSheep使用的攻击类型仍然可以通过,针对用户而不是您的站点的任何类似攻击也会通过。您可以使用https而不是http来防范FireSheep。但即使这样也无法抵御各种用户定位攻击。比如从他们的机器上窃取会话cookie,或者对他们的机器进行物理访问。

答案 1 :(得分:4)

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

解决方案是使用flash来散列数据。创建一个小的flash文件来接收数据,SALT并使用MD5对其进行加密。而不是发送到服务器。攻击者能够看到数据但是已加密。

攻击者仍然可以尝试对闪存进行反编译。

答案 2 :(得分:3)

它只会略微提高攻击力,但你可以通过jQuery.ajax(这是一个链接)或jQuery.post POST JSON(就是这样)。 jQuery.getJSON只是ajax的包装器(.post.get)。来自getJSON docs

  

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

$.ajax({
    url:      url,
    dataType: 'json',
    data:     data,
    success:  callback
});

因此,要执行postJSON概念,您只需向其添加type参数:

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

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

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

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

答案 3 :(得分:1)

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

答案 4 :(得分:1)

请查看this question,讨论一个非常类似的问题。制作它真的不容易,所以有人不能伪装成你的JavaScript,因为你的JavaScript完全对世界开放。

答案 5 :(得分:1)

您将需要查看为防止跨站点请求伪造(CSRF)攻击而采取的类似方法。 phpsec.org有一些很好的examples,你可以根据你的Ajax请求进行调整。

答案 6 :(得分:1)

通过ajax发布请求实际上很容易,只需要参考jquery的通用ajax函数。但这并没有回答你的问题,因为伪造发布请求和伪造请求几乎一样容易。 您无法可靠地隐藏脚本与之通信的服务器URL。因此,如果这会导致任何安全问题,您必须重新考虑您的网站或应用程序的安全架构。

答案 7 :(得分:0)

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

希望有所帮助。

答案 8 :(得分:0)

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

... yourdomain.com/somePsuedoFolder/?postRequestData

然后你在.htaccess中放置一个重定向,扫描“somePsuedoFolder”并重定向到 你的长形式php文件位置。这就是你要问的方式,这样人们就无法在你的服务器上看到文件的位置。

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

答案 9 :(得分:0)

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

  • 在PHP控制器中生成一个调用Javascript的随机数;将它连接到您传递给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];
...

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