2016-04-26 77 views
0

我正在寻找一种方法,即一段代码(A)可以生成某种类型的令牌,然后将它传递给另一段代码(B)一段代码无法拦截它(E)。在函数之间安全地传递令牌

为了这个问题的目的,假设A可以安全地生成令牌。

如果B公开了一些函数F给A,它接受一个包含该标记的对象作为参数之一,那么A可以直接传递该标记。

但E可以通过例如覆盖console.log并检查堆栈来找到该令牌。

var x = console.log 
console.log = function Eve() 
{ 
    x.apply(this, arguments); 
    console.info(Thing.caller.arguments); 
} 

(假设那个F调用当然console.log,但在现实中也有很多,可以通过这种方式被覆盖等功能)

我想我对这个缓解,这是删除在调用任何可能受损的函数之前,从传递的对象中获取安全令牌 即

var y = function Y(Secure) 
{ 
    var Thing = Secure.Arg; 
    delete Secure.Arg; 
    console.log('SomeMessage', arguments) ; 
} 
y({Arg:'SomeArg'}) 

(在FF至少)操纵对象参数也改变其在栈上的值,以便在堆栈上arguments对象现在包含一个空对象。 E还有其他什么方法可以访问传递的数据吗? 如果是,那么这些方法是可以缓解还是应该考虑其他更好的安全性?为了清晰起见进行编辑:假定E通过在A或B的控制之外的方式注入 - 例如, Greasemonkey的用户脚本

+0

我想你会有一个不好的时间阻止这个其他的解决方案是:自己托管第三块代码。在不同来源的iframe中运行它。 –

回答

2

你可以使用一个运行一次的getter和关闭,以保持私人数据,从堆栈:

function A(secret){ 
    return function(){ 
     var s=secret; 
     secret=null; 
     return s; 
    }; 
} 

function B(fn){ 
    var v=fn(); 
    console.log(fn); 
    alert("In B(): " + v); 
} 

var x=A(123); //give secret number to A, getting back a function 
alert(x); // no secret here 

B(x); // extract the secret by executing a one-time getter 
alert(x); // no secret here 

alert(x()); // still no secret, it's used-up 

因为JS使用基于参考的安全性,除去裁判提供了安全性。

另请注意,您可以设置断点以获取参数值,但不能使用try/catch,console.log()或任何其他用户空间技巧来恢复123中的A和B之间的上面的代码。

您必须运行该函数才能获取该值,并且运行该函数会破坏该值。

OP的代码使用的对象属性的问题是,如果发生异常,秘密值在对象上可见,而闭包会保持其秘密。

+0

up投这个创造性的解决方案。虽然可能还会钩入函数B来拦截令牌? – Roberto

+1

@罗伯托:我不明白,但你可以让愚蠢的吸气者变得更聪明。在非严格的情况下,甚至还有''function tell(){alert(Function.prototype.toString.call(arguments.callee.caller))这个很酷的技巧;} function coolName(){tell(); } coolName();'这样tell()就可以确切地说明是什么调用它,如果需要的话验证代码。也许MD5? – dandavis

+0

恶意代码可以在你之前定义函数B,也可以覆盖'Function.prototype.toString =()=>'asd';' –

1

如果您使用第三方库,可能会因为不良目的而覆盖自己的代码,那么这已经是一个失败了。所以最好的解决方案是使用另一个值得信赖的解决方案。

如果您仍然对从这些库中保护令牌感兴趣,则可以使用Object.defineProperty定义不可写入的函数。

var obj = {}; 
Object.defineProperty(obj,'unwritableMethod',{ 
    value: function(token){ 
     //do stuff with this token 
    }, 
    writable: false 
}); 
var x = obj.unwritableMethod; 
var maliciousMethod = function Eve() 
{ 
    x.apply(this, arguments); 
    console.info(Thing.caller.arguments); 
}; 
// This will be silently ignored. 
obj.unwritableMethod = maliciousMethod; 
//you can test the result with this 
console.log(obj.unwritableMethod === maliciousMethod); //false