【问题标题】:Securely passing tokens between functions在函数之间安全地传递令牌
【发布时间】:2016-08-19 23:41:27
【问题描述】:

我正在寻找一种方法,让一段代码 (A) 可以生成某种令牌,然后将其传递给另一段代码 (B),以使第三段代码无法拦截它(E)。

就本问题而言,假设 A 可以安全地生成令牌。

如果 B 向 A 公开某个函数 F,该函数接受包含令牌的对象作为其参数之一,则 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 控制之外的方式注入的 - 例如油脂猴用户脚本

【问题讨论】:

  • 我认为您将很难阻止其他解决方案是:自己托管第三段代码。在不同来源的 iframe 中运行它。

标签: javascript security


【解决方案1】:

您可以使用一次运行的 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 使用基于引用的安全性,删除 ref 提供了安全性。

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

你必须运行函数来获取值,运行函数会破坏值。

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

【讨论】:

  • 对该创意解决方案投了赞成票。虽然仍然可以挂钩到函数 B 来拦截令牌?
  • @Roberto:我不知道怎么做,但你可以让愚蠢的吸气剂变得更聪明。在非严格的情况下,甚至还有 function tell(){alert(Function.prototype.toString.call(arguments.callee.caller));} function coolName(){ tell(); } coolName(); 的酷炫技巧,这样 tell() 可以准确地知道调用它的内容,并在需要时验证代码。也许是 MD5?
  • 恶意代码可以在你之前定义函数B,也可以覆盖Function.prototype.toString = () => 'asd';
  • @RolandStarke:是的,如果他们替换了B,所有的赌注都没有了,这在 OP 提出的控制范围内。旁白:首先运行delete Function.prototype.toString 将允许callee.caller 代码不模糊,我认为还没有办法解决这个问题;)
  • 我还没有尝试过,但我喜欢这个解决方案的想法。目前,我无法确保其他方面也安全(令牌来自哪里以及接下来要去哪里),所以这可能会变得没有意义。
【解决方案2】:

如果您使用第三方库可能会出于不良目的覆盖您自己的代码,这已经是一场灾难。因此,最好的解决方案是使用另一个值得信赖的解决方案。

如果您仍然对保护这些库中的令牌感兴趣,您可以使用 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

【讨论】:

    猜你喜欢
    • 2011-01-20
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 2010-10-31
    • 2021-01-22
    • 1970-01-01
    • 1970-01-01
    • 2011-08-19
    相关资源
    最近更新 更多