My favorites | Sign in
Logo
                
Search
for
Updated Jun 03, 2008 by mikesamuel
Labels: Attack-Vector
ArgumentsExposesCaller  
Reflective call stack traversal leaks references.

arguments Array and function object expose caller

Effect

An untrusted function can steal a reference to a trusted caller function which it can later invoke.

Background

http://developer.mozilla.org/en/docs/Core_JavaScript_1.5_Reference:Objects:Function:call describes both caller and the caller property of Functions.

The members of function objects are described in EcnaScript 262 Section 15.3.5. In addition to these, many implementations expose properties caller, and __caller__.

Many implementations also expose caller as part of the arguments Array.

Assumptions

Untrusted code can call a trusted function to escalate privileges if it holds a reference to it.

Untrusted code can access the currently executing function. This can normally be done at runtime via arguments.callee.

Calls of untrusted functions are not passed through a launderer function which recurses to itself as in

  function launderer(fn, varargs) {
    if (arguments.caller !== arguments.callee) {
      arguments.callee.apply(this, arguments);
    } else {
      arguments[0].apply(
          this, [].splice.call(arguments, 1, arguments.length));
    }
  }

This laundering scheme does not work if __caller__ is exposed. __caller__ was removed from Firefox.

Versions

At least on FF and IE. Only old versions of Firefox expose __caller__

Example

function untrusted() {
  alert('got function ' + untrusted.caller + ' : '
        + arguments.callee.caller.arguments[0]);
}

(function trusted() { untrusted(); })(4);

Comment by andrea.campi, Oct 14, 2007
many implementations expose properties "caller", and "caller".

The second instance was probably meant to be "callee".

Comment by mikesamuel, Oct 25, 2007

Actually, the second "caller" was supposed to be __caller__ (note the underscores), but wiki markup uses underscores to delimit italicized regions.

Thanks for pointing that out.

Comment by harkeran, Feb 05, 2008

I do not see why exposing caller is any different than exposing caller. Certainly using array access to object data will allow access to a "caller" field.

Comment by mikesamuel, Apr 29, 2008

The launderer makes sure that the caller of the function is itself, so if you try to follow arguments.callee.caller.caller.caller... you get stuck in an infinite loop.

Comment by mikesamuel, Jun 03, 2008

I believe the difference between __caller__ and caller is that the former is an "activation object" (a proxy fr a call-stack frame) whereas the latter is a function.


Sign in to add a comment