Closed Bug 323501 Opened 19 years ago Closed 19 years ago

security check of js_ValueToFunctionObject() can be circumvented


(Core :: JavaScript Engine, defect, P1)






(Reporter: sync2d, Assigned: mrbkap)


(Keywords: verified1.8.0.2, verified1.8.1, Whiteboard: [sg:critical][rft-dl] doesn't affect ff1.0.x)


(2 files, 1 obsolete file)
2139     caller = JS_GetScriptedCaller(cx, cx->fp);
2140     if (caller &&
2141         !js_CheckPrincipalsAccess(cx, funobj,
2142                                   caller->script->principals,
2143                                   JS_GetFunctionName(fun))) {

This security check can be circumvented by using setTimeout()
or similar that calls a function without any scripted caller.
Attached file testcase
privilege escalation testcase

Works on:
Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.9a1) Gecko/20060114 Firefox/1.6a1
Mozilla/5.0 (Windows; U; Win98; en-US; rv:1.8) Gecko/20060114 Firefox/1.5
Flags: blocking1.8.0.2?
Whiteboard: [sg:critical]
Attached patch proposed fix (obsolete) — Splinter Review
Clever testcase.  I blame the Array extras added for JS1.6 (half-kidding, shaver ;-).  Compare the Function case (visible in patch due to fix to use the declared string constant), where if there's no scripted caller, principals is null and the check will fail.

In the js_ValueTo{Function,Callable}Object case, we don't give up so easily.  If the callee's object principals (the callee is Array.forEach) subsume those of the callable, we're ok.  So chrome could use setTimeout as this testcase does, and it would work as it should.

I wish eval weren't a universal method, but we can't fix that this time around.

Attachment #208546 - Flags: superreview?(shaver)
Attachment #208546 - Flags: review?(mrbkap)
Flags: testcase+
Assignee: general → brendan
Flags: blocking1.8.1?
Priority: -- → P1
Target Milestone: --- → mozilla1.9alpha
Comment on attachment 208546 [details] [diff] [review]
proposed fix

The extra effort to get the principals from the callee scare me here. This means that if you manage to get your hands on a priviledged Array object, you'd be able to do this same exploit. I know that AJAX people are using this stuff, but setTimeout(Array.forEach, ...) feels like a real edge case. If this starts biting people, I'd argue for adding a belt (or is it braces?) to the array extras.
Attachment #208546 - Flags: review?(mrbkap) → review-
(In reply to comment #4)
> If this starts biting people, I'd argue for adding a belt (or is it braces?) to the array
> extras.

Of course, I mean in addition to getting the principals from the callee.
Comment on attachment 208546 [details] [diff] [review]
proposed fix

clearing req based on mrbkap's r-.
Attachment #208546 - Flags: superreview?(shaver)
Attached patch safer fixSplinter Review
This is basically brendan's fix, but without the scary get-principals-from-callee behavior.
Assignee: brendan → mrbkap
Attachment #208546 - Attachment is obsolete: true
Attachment #209540 - Flags: superreview?(shaver)
Attachment #209540 - Flags: review?(brendan)
Comment on attachment 209540 [details] [diff] [review]
safer fix

> js_ValueToFunctionObject(JSContext *cx, jsval *vp, uintN flags)
> {
>     JSFunction *fun;
>     JSObject *funobj;
>-    JSStackFrame *caller;
>+    JSStackFrame *fp, *caller;
>+    JSPrincipals *principals;
>     if (JSVAL_IS_FUNCTION(cx, *vp))
>         return JSVAL_TO_OBJECT(*vp);
>     fun = js_ValueToFunction(cx, vp, flags);
>     if (!fun)
>         return NULL;
>     funobj = fun->object;
>     *vp = OBJECT_TO_JSVAL(funobj);
>-    caller = JS_GetScriptedCaller(cx, cx->fp);
>-    if (caller &&
>-        !js_CheckPrincipalsAccess(cx, funobj,
>-                                  caller->script->principals,
>-                                  JS_GetFunctionName(fun))) {
>+    fp = cx->fp;
>+    caller = JS_GetScriptedCaller(cx, fp);

Minimize the patch by eliminating fp again -- it's a single-use variable.  Fix that and r=me.


>+    if (caller) {
>+        principals = caller->script->principals;
>+    } else {
>+        /* No scripted caller, don't allow access. */
>+        principals = NULL;
>+    }
>+    /*
>+     * FIXME: Reparameterize so we don't call js_AtomToPrintableString unless
>+     *        there is an error.
>+     */
>+    if (!js_CheckPrincipalsAccess(cx, funobj, principals,
>+                                  fun->atom
>+                                  ? js_AtomToPrintableString(cx, fun->atom)
>+                                  : js_anonymous_str)) {
>         return NULL;
>     }
>     return funobj;
> }
> JSObject *
> js_ValueToCallableObject(JSContext *cx, jsval *vp, uintN flags)
> {
>     JSObject *callable;
Attachment #209540 - Flags: review?(brendan) → review+
Fix checked into trunk.
Closed: 19 years ago
Resolution: --- → FIXED
Flags: blocking1.8.1?
Flags: blocking1.8.1+
Flags: blocking1.8.0.2?
Flags: blocking1.8.0.2+
Comment on attachment 209540 [details] [diff] [review]
safer fix

I think we want this on the 1.8 branches, but I need approval.
Attachment #209540 - Flags: approval1.8.0.2?
Comment on attachment 209540 [details] [diff] [review]
safer fix

approved for 1.8.0 branch, a=dveditz for drivers
Attachment #209540 - Flags: approval1.8.0.2? → approval1.8.0.2+
Fix checked into the 1.8 branches.
Whiteboard: [sg:critical] → [sg:critical][rft-dl]
Whiteboard: [sg:critical][rft-dl] → [sg:critical][rft-dl] doesn't affect ff1.0.x
v.fixed on 1.8.0 branch with Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv: Gecko/20060301 Firefox/, anonymous function call blocked in testcase.
testcase does not alert in Bon Echo 20060517 / winxp or Minefield 20060517 / winxp  and does show the error message.
Group: security
Keywords: fixed1.8.1
shutdown,  can you contact me at  Having a problem getting mail though to you.  thanks.
You need to log in before you can comment on or make changes to this bug.