Red de conocimiento informático - Material del sitio web - Cómo incrustar js de terceros de forma segura

Cómo incrustar js de terceros de forma segura

XSS es un problema que se encuentra con frecuencia en el front-end, porque el js en la página se ejecuta en el mismo contexto, lo que significa que una vez que ocurre una vulnerabilidad xss, el atacante podrá disfrutar de los mismos permisos que el js en otras partes de la página y puede hacer cualquier cosa

Por lo tanto, generalmente filtraremos la entrada del usuario y prohibiremos la ejecución de cualquier js. Pero a veces es necesario incrustar js de terceros, como Google Adsense. En este momento, solo se puede confiar completamente en él y no existe ningún mecanismo para evitar su comportamiento malicioso. Otra forma es incrustar a través de iframe, pero esto se encontrará. muchos problemas. Por ejemplo, ajuste de altura, etc., y además es imposible evitar comportamientos maliciosos de terceros, como el uso de ActiveX

¿Existen otros métodos? Este artículo ha recopilado las soluciones a este problema de Facebook, Google, Microsoft y Yahoo. Espero que pueda inspirar a todos.

FBML

FBML permite que Facebook permita a terceros. para convertir html y js La tecnología de incrustar css en páginas de Facebook es actualmente muy popular en SNS, como space, Renren, 51, etc., todos la están usando

Principio básico

La siguiente imagen es la representación de la página de Facebook. El proceso, la imagen proviene de /blog/?p=10

Primero, Facebook inicia una solicitud al tercero, el servicio del tercero devuelve una página FBML. a facebook, y luego facebook lo convierte a html y lo coloca en la página de facebook. FBML es un lenguaje de marcado similar a xhtml. Permite el uso de una gran cantidad de etiquetas html y proporciona una gran cantidad de etiquetas específicas de Facebook. lo que proporciona comodidad a los desarrolladores externos

En FBML En el proceso de escribir HTML, habrá muchas comprobaciones de seguridad, como variables en etiquetas de script, como agregar prefijos a nombres de variables y funciones. etiquetas de script, como el siguiente código

function $(str) {

return document.getElementById(str);

}

$("hello");

se convertirá al siguiente formato: se supone que la identificación de la aplicación de terceros es 1 y todos los nombres de variables comienzan con a1_

función a1_$(a1_str) {

return a1_document.getElementById(a1_str);

}

a12_$("hola");

La ventaja de esto es que el js de terceros no afectará a otros js en la página, solo puede llamar a su propio js interno. Para que las variables y funciones creadas tengan ciertas funciones, puedes proporcionarle algunas objetos globales antes de ejecutarse, como el objeto global del documento utilizado anteriormente Después de convertir a a1_document, siempre que el tiempo de ejecución esté en a1_document.getElementById (a1_str) antes de poder usar estos objetos globales. getElementById(a1_str);

De esta manera, los js de terceros no afectarán a otros js de la página.

Siempre que este objeto se asigne antes de ejecutar el js de terceros, el js de terceros puede usarlo

var a1_document = new fbjs.main ('1');

De esta manera, fbjs.main El objeto reemplaza el objeto de documento en js de terceros, donde puede realizar varias comprobaciones para garantizar que el js de terceros no utilice el objeto de documento. Se pueden realizar varias comprobaciones para garantizar que los js de terceros no afecten al resto de la página y se puede implementar un mecanismo de lista blanca. Los terceros solo pueden llamar a algunas API específicas, pero no pueden leer ni escribir cookies, como esta. implementado por fbjs_main Ejemplo simple

función fbjs_main(appid) {}

fbjs_main.prototype.getElementById = función(id) {

return fbjs_dom.get_instance(document .getElementById( id));

}

Puede ver que, de hecho, una llamada de un tercero a document.getElementById devuelve el valor de document.getElementById. getElementById devuelve un objeto interno en lugar del nodo dom real. La ventaja de esto es que limita los programas de terceros. La desventaja es que no se puede acceder directamente a muchos atributos del nodo dom (como tagName) y solo pueden leerse. llamar al método correspondiente escribirlos es algo similar a jQuery

Métodos

La biblioteca de conversión FBML es de código abierto. Los estudiantes interesados ​​pueden consultar libfbml, que utiliza el código fuente de Firefox 2.0. .0.4. js

A continuación estudiaremos en detalle cómo FBML garantiza la seguridad

Conversión html/css

Primero, los identificadores de las etiquetas en FBML se agregan con prefijo, por ejemplo id="a", el id de la etiqueta tiene el prefijo. "a "div se convierte a

lt;div id="app_1_a"gt;lt;/divgt;

Todos los atributos de HTML también se verifican estrictamente para evitar el siguiente tipo de código

lt;a href="javascript:alert()"gt;clicklt;/agt;

lt;img src="xxx" onerror="alert()" /gt ;

La conversión de CSS es relativamente simple: principalmente agrega prefijos a los selectores y limita los estilos a contenedores js de terceros.

Por ejemplo,

#app_content_1 .my_class

y filtre algunos atributos CSS peligrosos, como expresión, comportamiento y enlace de moz

para evitar pasar el div de posición se movió fuera de su contenedor, la página de Facebook se ha convertido a "alert()" /gt;

Para evitar mover el div fuera de su contenedor por posición, la página de Facebook ha agregado desbordamiento: oculto para aplicaciones de terceros

La conversión de JS en el div en el contenedor superior

Garantizar la seguridad de js se divide principalmente en dos aspectos: uno es el análisis estático, como la prohibición. agregar prefijos a ciertas funciones y nombres de variables, el otro es realizar comprobaciones en tiempo de ejecución, como esta referencia

esta referencia

esto puede apuntar fácilmente a Windows, por ejemplo, escribir. menos nuevo al crear un nuevo objeto

function Car() {

this.xx = 'yyyyy

}

var; car = Car();

alert (xx)

Por lo tanto, es necesario volver a empaquetarlo para verificarlo en tiempo de ejecución, convirtiendo así el código anterior en

función. a1_Car() {

ref(this ).xx = 'yyyyy';

}

var a1_car = a1_ Car()

De esta manera se puede verificar en tiempo de ejecución para evitar apuntar a la ventana, la implementación de la función ref es

función ref(that) {

if (that == ventana) {

return null;

} else if (that.ownerDocument == documento) {

fbjs_console.error('¡llamado con un objeto DOM!') ;

devolver fbjs_dom.get_instance(ese );

} else {

devolver eso

}

}

with

with no se puede analizar estáticamente porque inserta temporalmente un contexto, que necesita ser conocido en tiempo de ejecución para saber qué variable se está obteniendo, por lo que FBML prohíbe el uso de En este contexto, muchos programas posteriores también desactivan la declaración with

Atributos peligrosos

Algunos atributos en js son peligrosos, por ejemplo, el constructor del objeto generado se puede obtener a través del constructor. , como el siguiente código para modificar la función Objeto

var o = {};

o.constructor.prototype .xx = 'xx';

Reemplace todos los atributos siguientes con __unknown__ en FBML

__proto___

__parent__

caller

watch

constructor

__ defineGetter__

__defineSetter__

Sin embargo, debido a la naturaleza dinámica de js, también puede utilizar la sintaxis de corchetes para obtener estas propiedades. El código anterior puede ser equivalente. a

>

var o = {};

o['constr' 'uctor'].prototype.xx = 'xx';

El análisis estático no puede detectar este tipo de problemas, por lo que necesita agregar una capa de verificación en tiempo de ejecución de las propiedades dentro de los corchetes, algo así como

function idx(b) {

return (bstanceof Object || fbjs _blacklist_props[b ] ) ?'__unknown__': b;

}

Pero la lista anterior sigue siendo riesgosa, y las siguientes cajas, ADsafe, etc. han desactivado directamente los atributos con el sufijo. _. Para evitar vulnerabilidades causadas por actualizaciones posteriores del navegador

argumentos

En versiones anteriores de Firefox e IE, el objeto de argumentos puede llamar a la función de la función actual a través del llamador. lo que traerá muchos riesgos de seguridad, por ejemplo, cuando ajax devuelve una llamada a una función de terceros, quedará expuesta a la biblioteca ajax, por lo que FBML la encapsula y la convierte en arg (argumentos), convirtiendo la función arg en un matriz normal

function arg (args) {

var new_args = []

for (var i = 0; i lt; args.length; i ) {

new_args. push(args[i]);

}

return new_args;

}

eval

Debido a que eval no se puede analizar, solo se puede deshabilitar. Para js de terceros que necesitan obtener datos json, fbjs proporciona una biblioteca Ajax para convertirlos en un objeto json, pero desde el punto de vista del código, no tiene los controles de seguridad correspondientes, lo que puede causar riesgos de seguridad.

Para garantizar que se pueda analizar eval json de terceros, fbjs proporciona una biblioteca Ajax para convertirlo en un objeto json. Para garantizar la seguridad del json de terceros de evaluación, puede utilizar el enfoque json2.js para verificar si es un json legal antes de eval

if (!/^[/], :{} /s ]*$/.test(data.replace(///(? :["////bfnrt]|u[0-9a-fA-F]{4})/g,"@")

.replace(/"[^"///n/r]*"|true|false|null|-?/d (? :/. /d*)?(? :[eE] [ / -]? /d )?/g, "]")

.replace(/(? :^|:|,)(? :/s*/[) /g, "" )) ){

Devuelve nulo

}

Eliminar comentarios

Sin embargo, eliminar comentarios parece reducir el tamaño del archivo. a IE El mecanismo de compilación condicional hará que JS arbitrario aún se ejecute en los comentarios, por lo que los comentarios deben eliminarse, por ejemplo

/*@cc_on @* / /*@if (1) alert(document. cookie) @end @* /

Además, el análisis incorrecto de -- por parte de Firefox también puede generar problemas de seguridad

Muchos métodos en matrices

En algunos navegadores , en matrices Muchos de los métodos devuelven una ventana cuando se llama mediante call y apply.

la llamada devolverá el objeto de ventana El siguiente método de escritura utilizará el objeto de ventana en Firefox, Chrome y otros navegadores

alert(window === ([]).sort.call());

Por lo tanto, estos métodos se anulan en fbjs para evitar apuntar a la ventana en tiempo de ejecución

Array.prototype.sort = (function(sort) { return function(callback) {

return (esta == ventana) ?null: (devolución de llamada? sort.call(this, function(a,b) {

return callback(a,b)}): sort.call(this) );

}})(Array.prototype.sort);

Incluso reducir, reducirDerecha directamente

Array.prototype.reduce = null;

Incluso reducir, reducirDerecha directamente

Array.prototype.reduce = null;

p>

Array.prototype.reduceRight = null;

dom

Para permitir que js de terceros controlen los elementos de la página, fbjs encapsula muchos métodos de dom y ejecuta operaciones en ellos. Verifique cuándo

getElementById

Dado que la identificación es con prefijo, la API proporcionada por fbjs para js de terceros también necesita un prefijo para obtener

fbjs_main.getElementById = function (id) {

var appid = fbjs_private.get( this).appid;

return fbjs_dom.get_instance(document.getElementById('app' appid '_' id), appid

}

getParentNode);

Para evitar que los js de terceros afecten el resto de la página, es necesario verificar el nodo dom cuando se mueve, como obtener parentNode, debe restringirse al contenedor al que pertenece la aplicación de terceros y no se pueden obtener otros elementos superiores a este nodo

createElement, internalHTML

fbjs proporciona la interfaz createElement, lo que permite que los js de terceros creen elementos y verifiquen si solo se permite la creación de elementos seguros

Con internalHTML, que a muchos desarrolladores les gusta usar, no es fácil realizar comprobaciones de seguridad porque es necesario analizar el html en tiempo de ejecución.

Actualmente, fbjs solo proporciona dos métodos, uno es setInnerFBML, que se implementa mediante la etiqueta personalizada lt; fb.js-stringgt;: js-stringgt en FBML, deje que FBML lo analice, la desventaja es que no se puede ejecutar. setInnerXHTML, que requiere que la cadena pasada sea la forma legal de xml y utiliza directamente el analizador XML del navegador para analizar

ubicación, src, href

Existe el riesgo de que pueda dinámicamente cree una etiqueta y establezca su href, generando así xlt;/agt>, por lo que necesita agregar un juicio de capa

fbjs_dom.href_regex = /^( ? :https?|mailto|ftp|aim|irc|itms|gopher|//|#)/;

fbjs_dom.prototype .setHref = función(href) {

href = fbjs_sandbox.safe_ string(href);

if (fbjs_dom.href_regex.test(href)) {

fbjs_dom.get_obj(this).href = href;

devuelve esto;

} else {

fbjs_console.error(href 'no es un hipervínculo válido '); p>}

Excepto por el rc y la ubicación de img. href

setTimeout, setInterval

setTimeout y setInterval se pueden ejecutar pasando una cadena. Al igual que eval, no se pueden analizar estáticamente, por ejemplo:

var a. = 'ale';

var b = 'rt()';

setTimeout(a b, 10);

Por lo tanto, fbjs encapsula estas dos funciones. , restringiéndolos a permitir que solo se pasen tipos de funciones

fbjs_sandbox.set_timeout = function(js, timeout) {

if (typeof js ! = 'function') {

fbjs_console.error('es posible que setTimeout no funcione con cadenas. Envuelva su evento en una función anónima.

');

} else {

return setTimeout(js, tiempo de espera

}

}

Ejecutar código js

El js analizado desde fbml no se volverá a colocar directamente en la etiqueta