Ejecuta código JavaScript almacenado como una cadena

173

¿Cómo ejecuto un JavaScript que es una cadena?

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    // how do I get a browser to alert('hello')?
}
divinci
fuente

Respuestas:

227

Con eval("my script here")funcion.

Lennart Koopmann
fuente
12
Ten cuidado ! Esto ejecutará el código, por lo tanto, tenga cuidado de dónde / cómo obtuvo esta cadena. Tenga en cuenta que cualquiera puede intentar insertar código malicioso dentro de su cadena.
Jon
1
@divinci Esto se llama "Cross Site Scripting". Ver aquí: en.wikipedia.org/wiki/Cross-site_scripting .
Brendon Shaw
134

Puedes ejecutarlo usando una función. Ejemplo:

var theInstructions = "alert('Hello World'); var x = 100";

var F=new Function (theInstructions);

return(F());
stefan
fuente
3
pero al final, ¿no es lo mismo que llamar var F=function(){eval(theInstructions);};?
Jörn Berkefeld
14
sí y no: con el código eval también se ejecutará, mientras que con el código Function () no se ejecuta hasta F () (caso de uso? compruebe si hay un error de sintaxis pero no desea ejecutar el código)
G3z
2
@stefan Es hermoso ...new Function("alert('Hello World');")()
Andrés Morales
Intenté esto dentro de un bloque try / catch, y funciona perfectamente. Ahora puedo tomar cualquier código JavaScript escrito en un bloque de texto, pasarlo a mi función y ejecutarlo. El bloque catch puede insertar mensajes de error del motor de JavaScript en un elemento DOM y mostrar cualquier error en el código. Si alguien quiere la función que escribí, una vez que la haya ordenado, puedo publicarla aquí.
David Edwards
@DavidEdwards Sería genial si todavía lo tienes y lo publicas.
Anoop
60

La evalfunción evaluará una cadena que se le pasa.

Pero el uso de evalpuede ser peligroso , así que úselo con precaución.

Editar: annakata tiene un buen punto: no solo es eval peligroso , es lento . Esto se debe a que el código a evaluar debe analizarse en el acto, por lo que se necesitarán algunos recursos informáticos.

Coobird
fuente
34
súper peligroso Y lento: debe ser negrita, cursiva, subrayado y h1 eso
annakata
55
Dudo que sea más lento que cargar JavaScript en cualquier otro lugar de la página, eso también debe analizarse. Si es más lento, es porque se hace en un alcance diferente, lo que podría forzar la creación de recursos para ese alcance.
cgp
66
Si lo dices eval()es peligroso. ¿Hay alguna alternativa?
white_gecko
44
@coobird Sé que es un poco tarde, pero ¿por qué es peligroso? El usuario puede ejecutar fácilmente el código JavaScript en su sitio web utilizando la consola.
jkd
8
si su seguridad depende en absoluto del javascript del lado del cliente, la ha fastidiado mucho y no tiene nada que ver con eval.
Mateo
20

Usa eval ().

Visita a las escuelas W3 de eval . El sitio tiene algunos ejemplos utilizables de eval. La documentación de Mozilla cubre esto en detalle.

Probablemente recibirá muchas advertencias sobre el uso seguro de esto. NO permita que los usuarios inyecten NADA en eval () ya que es un gran problema de seguridad.

También querrá saber que eval () tiene un alcance diferente .

cgp
fuente
11
w3fools.com . El W3C ni siquiera tiene nada que decir sobre eval. Si desea vincular a algo oficial, diríjase
Bergi
77
No quería "vincularme a nada oficial, quería vincularme a algo legible - Mirando lo que vinculaste, no da una explicación de cómo se usa, no hay ejemplos, no hay forma de jugar, y describe el método de forma aislada Para un principiante, es un enlace completamente inapropiado. Oye, no serías @bjorninge, ¿verdad?
CGP
1
La especificación me describe evalmejor que ese artículo de W3Schools. Algo legible con una buena explicación y ejemplos sería developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/… . Y no, no estoy bjorninge
Bergi
Estaré de acuerdo en que no es documentación, y estaré de acuerdo en que la página de Mozilla es una mejor imagen general de la misma. Ligeramente modifiqué mi respuesta en función de los comentarios
cgp
1
Con respecto a ese enlace ecma-international.org, lo describiría como legible y apreciable por todos con más de 15 minutos de experiencia con JS. Es muy bonito.
i336_
16

Prueba esto:

  var script = "<script type='text/javascript'> content </script>";
  //using jquery next
  $('body').append(script);//incorporates and executes inmediatelly

Personalmente, no lo probé pero parece funcionar.

Yanko
fuente
1
Olvidó escapar del cierre> en el script: var script = "<script type = \" text / javascript \ "> content </ script \>";
rlib
1
¿Por qué necesitas escapar del cierre>?
Jools
11

Un poco como lo que dijo @Hossein Hajizadeh alerady, aunque con más detalle:

Hay una alternativa a eval().

La función setTimeout()está diseñada para ejecutar algo después de un intervalo de milisegundos, y el código que se ejecutará está formateado como una cadena.

Funcionaría así:

ExecuteJavascriptString(); //Just for running it

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    setTimeout(s, 1);
}

1 significa que esperará 1 milisegundo antes de ejecutar la cadena.

Puede que no sea la forma más correcta de hacerlo, pero funciona.

Anton Juul-Naber
fuente
¿Por qué perder un milisegundo cuando puede pasar 0 (cero) a setTimeout? Tenga en cuenta que en cualquier caso hará que la ejecución sea asíncrona. Significa que todo el código que sigue a la setTimeoutllamada se invocará antes de que el código pase setTimeout(incluso si se llama con 0 (cero)).
jox
🤷‍♀️ solo pensé que explicaba mejor cómo funciona setTimeout
Anton Juul-Naber
8
new Function('alert("Hello")')();

Creo que esta es la mejor manera.

MyMeMo
fuente
7

Use eval como a continuación. Eval debe usarse con precaución, una simple búsqueda sobre " eval is evil " debería arrojar algunos indicadores.

function ExecuteJavascriptString()
{
    var s = "alert('hello')";
    eval(s);
}
xk0der
fuente
2
Un buen consejo: una simple búsqueda sobre "eval is evil" ¡Gracias!
Taptronic el
5

Comprueba esto en muchos scripts complejos y ofuscados:

var js = "alert('Hello, World!');" // put your JS code here
var oScript = document.createElement("script");
var oScriptText = document.createTextNode(js);
oScript.appendChild(oScriptText);
document.body.appendChild(oScript);
rlib
fuente
5

Si desea ejecutar un comando específico (que es una cadena) después de un tiempo específico - cmd = su código - InterVal = retraso para ejecutar

 function ExecStr(cmd, InterVal) {
    try {
        setTimeout(function () {
            var F = new Function(cmd);
            return (F());
        }, InterVal);
    } catch (e) { }
}
//sample
ExecStr("alert(20)",500);
Hossein Hajizadeh
fuente
@SteelBrain agrega una muestra ejecutada por ExecStr ("alert (20)", 500);
Hossein Hajizadeh
1
¿Por qué está Valen InterValmayúscula?
Programas Redwolf
4

Para los usuarios que usan node y que están preocupados por las implicaciones de contexto de las eval()ofertas de nodejs vm. Crea una máquina virtual V8 que puede aislar la ejecución de su código en un contexto separado.

Llevar las cosas un paso más allá es lo vm2que endurece vmpermitiendo que el vm ejecute código no confiable.

const vm = require('vm');

const x = 1;

const sandbox = { x: 2 };
vm.createContext(sandbox); // Contextify the sandbox.

const code = 'x += 40; var y = 17;';
// `x` and `y` are global variables in the sandboxed environment.
// Initially, x has the value 2 because that is the value of sandbox.x.
vm.runInContext(code, sandbox);

console.log(sandbox.x); // 42
console.log(sandbox.y); // 17

console.log(x); // 1; y is not defined.
Eric Kigathi
fuente
2
En lugar de decir "evaluar es malo" y no dar contexto o solución, en realidad trata de resolver el problema. +1 para ti
Programas Redwolf
3
eval(s);

Pero esto puede ser peligroso si está tomando datos de los usuarios, aunque supongo que si ellos bloquean su propio navegador ese es su problema.

UnkwnTech
fuente
1
exactamente. Eval es peligroso en el lado del servidor. En el cliente ... no tanto. El usuario podría simplemente escribir javascript: someevilcode en la dirección del navegador y boom. Evalúe allí mismo.
Esben Skov Pedersen
@EsbenSkovPedersen Eso se evita en Chrome al menos, y requiere la acción del usuario, a diferencia de un sitio que evales el código de los usuarios, lo que podría, por ejemplo, permitir a los usuarios robar las cuentas de otros usuarios sin que lo sepan simplemente cargando la página.
1j01
1
@ 1j01 Para ser justos, mi comentario tiene cinco años.
Esben Skov Pedersen
@EsbenSkovPedersen Eso es cierto :)
1j01
2

No estoy seguro si esto es trampa o no:

window.say = function(a) { alert(a); };

var a = "say('hello')";

var p = /^([^(]*)\('([^']*)'\).*$/;                 // ["say('hello')","say","hello"]

var fn = window[p.exec(a)[1]];                      // get function reference by name

if( typeof(fn) === "function") 
    fn.apply(null, [p.exec(a)[2]]);                 // call it with params
Zachary Scott
fuente
2

Estaba respondiendo una pregunta similar y tuve otra idea de cómo lograr esto sin usar eval():

const source = "alert('test')";
const el = document.createElement("script");
el.src = URL.createObjectURL(new Blob([source], { type: 'text/javascript' }));
document.head.appendChild(el);

En el código anterior, básicamente crea Blob, que contiene su script, para crear la URL del objeto (representación del objeto File u Blob en la memoria del navegador). Como tiene una srcpropiedad en la <script>etiqueta, el script se ejecutará de la misma manera que si se cargara desde cualquier otra URL.

akrn
fuente
2
function executeScript(source) {
    var script = document.createElement("script");
    script.onload = script.onerror = function(){ this.remove(); };
    script.src = "data:text/plain;base64," + btoa(source);
    document.body.appendChild(script);
}

executeScript("alert('Hello, World!');");
Oleg
fuente
1

eval debería hacerlo.

eval(s);
Vincent Ramdhanie
fuente
0
eval(s);

Sin embargo, recuerde que eval es muy poderoso y bastante inseguro. Será mejor que esté seguro de que el script que está ejecutando es seguro e inmutable para los usuarios.

PatrikAkerstrand
fuente
1
En JS todo puede ser cambiado por el usuario simplemente escriba "javascript: document.write (" Hello World ");" en casi cualquier barra de direcciones del navegador.
UnkwnTech
1
Sí, pero puede hacerlo más difícil para él al no utilizar variables globales, ocultar sus funciones en cierres, etc. Además, evitando evaluar como la peste =)
PatrikAkerstrand
0

Uno puede usar mathjs

Fragmento del enlace anterior:

// evaluate expressions
math.evaluate('sqrt(3^2 + 4^2)')        // 5
math.evaluate('sqrt(-4)')               // 2i
math.evaluate('2 inch to cm')           // 5.08 cm
math.evaluate('cos(45 deg)')            // 0.7071067811865476

// provide a scope
let scope = {
    a: 3,
    b: 4
}
math.evaluate('a * b', scope)           // 12
math.evaluate('c = 2.3 + 4.5', scope)   // 6.8
scope.c                                

scopeEs cualquier objeto. Entonces, si pasa el alcance global a la función de evaluación, es posible que pueda ejecutar alert () dinámicamente.

También mathjs es una opción mucho mejor que eval () porque se ejecuta en un sandbox.

Un usuario podría intentar inyectar código JavaScript malicioso a través del analizador de expresiones. El analizador de expresiones de mathjs ofrece un entorno de espacio aislado para ejecutar expresiones que deberían hacer esto imposible. Sin embargo, es posible que existan vulnerabilidades de seguridad desconocidas, por lo que es importante tener cuidado, especialmente cuando se permite la ejecución de expresiones arbitrarias en el servidor.

Las versiones más recientes de mathjs no usan eval () o Function ().

El analizador impide activamente el acceso a la evaluación interna de JavaScripts y a la nueva función, que son la causa principal de los ataques de seguridad. Mathjs versiones 4 y posteriores no utilizan la evaluación de JavaScript bajo el capó. La versión 3 y anteriores usaban eval para el paso de compilación. Esto no es directamente un problema de seguridad, pero da como resultado una mayor superficie de ataque posible.

sziraqui
fuente
0

Usar tanto evaluar como crear una nueva Función para ejecutar javascript conlleva muchos riesgos de seguridad.

const script = document.createElement("script");
const stringJquery = '$("#button").on("click", function() {console.log("hit")})';
script.text = stringJquery;
document.body.appendChild(script);

Prefiero este método para ejecutar el Javascript que recibo como una cadena.

MapMyMind
fuente