Javascript Uso di Window Object tramite mezzi alternativi

4

Ignora i tuoi soliti paradigmi per un semplice momento qui ...

Ho visto alcuni siti che hanno utilizzato la seguente logica:

a=[];
b=a["sort"];
c=(b)();
c["alert"](1); // intended output: Alert displaying "1"...

presumibilmente per accedere (sto indovinando qui) la primitiva della funzione sort per ottenere l'accesso all'oggetto window, e quindi usarlo per accedere a "alert" ...

Ho provato a farlo da un secolo fa, e ha funzionato con un certo fascino ... Ma circa dodici mesi dopo ho provato ad eseguirlo di nuovo ... e non è stato eseguito, e ho ricevuto il seguente errore:

TypeError: can't convert undefined to object

La mia domanda è: perché questa logica non dovrebbe funzionare? Sembra abbastanza ... O è?

E sì, so che potrei semplicemente fare alert(1) e aver finito con esso, ma sto cercando di capire i modi alternativi di codifica ... Io lavoro nella sicurezza IT e so che certe persone hanno modi di usare XSS per trovare modi alternativi per eseguire funzioni generiche per compromettere i sistemi ...

    
posta Eliseo d'Annunzio 13.12.2013 - 00:47
fonte

3 risposte

1

Non sono sicuro del motivo per cui non funzionerebbe in un determinato ambiente ma funziona in una console di Chrome.

Esaminiamolo:

a=[];

a è definito senza una dichiarazione var in modo che diventi implicitamente un membro dell'oggetto globale che nei browser è l'oggetto finestra. Questo non funzionerebbe in modalità rigorosa (cerca 'use strict'; - potrebbe essere doppiamente quotato), che genererebbe un errore piuttosto che fare la cosa globale implicita, che sì, è una delle poche verruche di design JS che in realtà sono d'accordo una cattiva idea senza qualità redentori. Ma la modalità rigorosa sconfiggerà il tutto proprio qui.

b=a["sort"];
//b=a.sort; // to make it even more clear. bracket notation is for obfuscation purposes

Assegniamo il metodo di ordinamento degli array alla variabile b. Chiamato come b() , non è più chiamato come proprietà / metodo dell'array.

c=(b)();
//c=b(); // no need for (b) since b is already an evaluated function you can call

Quindi, b è il metodo array sort , ma ora è solo una funzione allentata. Cosa fa quella funzione generica? Prende la funzione è passata come un arg per ordinare tutto ciò che è rappresentato dalla parola chiave 'this', lo ordina e poi restituisce 'this'. Poiché b ora è solo una funzione libera, "questo" dovrebbe essere l'oggetto finestra. Per rompere a questo punto, passare undefined dovrebbe interrompere il metodo sort (che potrebbe essere più sensato dato il tuo errore) o il metodo sort dovrebbe comportarsi come se fosse stato applicato in modo permanente ad Array.prototype come se fosse stata utilizzata la funzione bind (vedere "bind" su MDN).

Nota: uso parole come "sembrano" perché sort restituisce come metodo [codice nativo] in Chrome, il che significa che potrebbe fare tutti i tipi di cose nei dettagli purché soddisfi tecnicamente le specifiche ECMA che tutti i browser i fornitori hanno preso sul serio dal IE5.

c["alert"](1); // intended output: Alert displaying "1"...
//c.alert(1); //works too.
//alert(1); //and yes the same exact thing but easier to obfuscate from the top one

A questo punto, non sta accadendo nulla di magico. Abbiamo l'oggetto globale. Attiriamo l'avviso da esso come una proprietà dell'oggetto globale.

    
risposta data 13.12.2013 - 04:26
fonte
0

Quindi la cosa a cui ho fatto riferimento nel mio commento sopra è il Javascript Garden , con la sua nota su EcmaScript 5 nella barra laterale. Da lì ho potuto effettivamente fare alcune ricerche e trovare riferimenti migliori.

In sostanza, this ha un paio di modi diversi che può essere impostato. Quello che conta qui, credo, è sotto "Common Trappole":

Foo.method = function() {
    function test() {
        // this is set to the global object
    }
    test();
}

e "Assegnazione di metodi":

var test = someObject.methodTest;
test();

Due to the first case, test now acts like a plain function call; therefore, this inside it will no longer refer to someObject.

Quindi, quando recuperi sort off dell'oggetto Array , lo trasformi in una funzione "alias", dove this non punta più sull'array. Quando la modalità rigorosa è disattivata / nelle versioni precedenti di browser / EcmaScript, era window , a causa dell'ambito globale. Tuttavia, quando sei in modalità rigorosa, ora è undefined :

Detto questo, la Developer Console di Chrome sta facendo qualcosa di strano, il che rende scorretto testare lì. Il tuo codice di esempio "succede" restituendo window , tuttavia, se lo copio in un file e lo eseguo (con o senza "use strict"; ), ottengo questo in Chrome:

Uncaught TypeError: Array.prototype.sort called on null or undefined

E questo viene da Firefox, da una pagina o da Firebug:

TypeError: can't convert undefined to object

Entrambi sono attesi se this non è definito, perché è essenzialmente lo stesso che fare:

Array.prototype.sort.call(undefined);

mentre a causa del contesto in "Common Trappole" sopra menzionato, era solito fare:

Array.prototype.sort.call(window);
    
risposta data 13.12.2013 - 05:16
fonte
0

Diamo un'occhiata alle specifiche ECMAScript 5 per Array.prototype.sort :

Let obj be the result of calling ToObject passing the this value as the argument.

E quando esaminiamo ToObject , vediamo una voce familiare nella tabella :

Argument Type    Result
=============    ======
Undefined        Throw a TypeError exception.
...
Object           The result is the input argument (no conversion).

Questo suggerisce che l'invocazione di b() di Chrome ha un valore this che non è undefined , ma altri fanno passano un this di undefined , risultando in% % co_de.

Per prima cosa dobbiamo esaminare come viene impostato TypeError quando eseguiamo una chiamata a una funzione (che a EMCAScript si riferisce come CallExpression ):

  • If Type(ref) is Reference, then
    • If IsPropertyReference(ref) is true, then
      • Let thisValue be GetBase(ref).
    • Else, the base of ref is an Environment Record
      • Let thisValue be the result of calling the ImplicitThisValue concrete method of GetBase(ref).
  • Else, Type(ref) is not Reference.
    • Let thisValue be undefined.

Poiché ImplicitThisValue del record ambiente di una funzione restituisce sempre this , l'unico caso in cui undefined è non this è durante l'accesso alla proprietà, ad esempio undefined . Pertanto, possiamo concludere che l'esecuzione di una invocazione di funzione "nuda" come foo.bar() utilizzerà sempre un valoreValore di b() .

Tuttavia, nella console di Chrome, undefined non è this per undefined . Per capire come questo potrebbe accadere (e come potrebbe differire tra i browser), dobbiamo esaminare il comportamento in modalità rigorosa in Sezione 10.4.3, Immissione del codice funzione :

The following steps are performed when control enters the execution context for function code contained in function object F, a caller provided thisArg, and a caller provided argumentsList:

  1. If the function code is strict code, set the ThisBinding to thisArg.

  2. Else if thisArg is null or undefined, set the ThisBinding to the global object.

dove " ThisBinding " è " Il valore associato al b() parola chiave all'interno del codice ECMAScript associato a questo contesto di esecuzione. "

Quindi, il codice non rigoroso sostituisce un this o null thisArg con l'oggetto globale, undefined . La modalità rigorosa, d'altra parte, non converte window o null nell'oggetto globale quando viene utilizzato per undefined . ( this restituisce l'oggetto sort ordinato, quindi this memorizza semplicemente l'oggetto globale restituito in c = b() .)

Pertanto , possiamo concludere che l'implementazione di Firefox della funzione c viene eseguita in modalità rigorosa, mentre l'implementazione di Chrome non lo fa.

Puoi vedere ulteriori prove di ciò in base a come Array.prototype.sort gestisce valori sort non oggetto. Se esegui this in vari browser, Chrome genererà typeof []["sort"].apply(5) , mentre Firefox emetterà "number" , dimostrando la modalità di autoboxing dell'oggetto che si verifica solo in modalità non rigida. La rigorosa funzione "object" di Firefox non boxa sort e restituisce la primitiva grezza.

    
risposta data 13.12.2013 - 16:14
fonte

Leggi altre domande sui tag