在函数之间安全地传递令牌

时间:2016-04-26 08:53:54

标签: javascript security

我正在寻找一种方法,即一段代码(A)可以生成某种令牌,然后以第3段代码的方式将其传递给其他一段代码(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中)操纵object参数也会更改其在堆栈上的值,因此堆栈上的arguments对象现在包含一个空对象。 有没有其他方法E可以访问传递的数据? 如果是,可以减轻这些方法,还是应该以更好的安全性来研究其他选项?

澄清的编辑:假设E通过A或B控制之外的方式注入 - 例如greasemonkey用户脚本

2 个答案:

答案 0 :(得分:2)

你可以使用run-once getter和closure来保护私有数据不受堆栈影响:

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()或任何其他用户区技巧来恢复代码中的A和B之间的123以上。

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

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

答案 1 :(得分: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