javascript - tag - Frame Buster Buster... código de buster necesario
string with html tags javascript (19)
¿Qué hay de llamar al destructor también repetidamente? Esto creará una condición de carrera, pero uno puede esperar que el destructor quede en la cima:
(function() {
if(top !== self) {
top.location.href = self.location.href;
setTimeout(arguments.callee, 0);
}
})();
Digamos que no desea que otros sitios "enmarquen" su sitio en un <iframe>
:
<iframe src="http://example.org"></iframe>
Por lo tanto, inserta JavaScript en cualquier página:
/* break us out of any containing iframes */
if (top != self) { top.location.replace(self.location.href); }
¡Excelente! Ahora usted "quiebra" o rompe cualquier iframe que lo contiene automáticamente. Excepto por un pequeño problema.
Como resultado, su código de eliminación de marcos puede ser eliminado , como se muestra aquí :
<script type="text/javascript">
var prevent_bust = 0
window.onbeforeunload = function() { prevent_bust++ }
setInterval(function() {
if (prevent_bust > 0) {
prevent_bust -= 2
window.top.location = ''http://example.org/page-which-responds-with-204''
}
}, 1)
</script>
Este código hace lo siguiente:
- incrementa un contador cada vez que el navegador intenta alejarse de la página actual, a través del controlador de eventos
window.onbeforeunload
- configura un temporizador que dispara cada milisegundo a través de
setInterval()
, y si ve incrementado el contador, cambia la ubicación actual a un servidor de control del atacante - ese servidor sirve una página con el código de estado HTTP 204 , que no hace que el navegador navegue a ninguna parte
Mi pregunta es, y esto es más un rompecabezas de JavaScript que un problema real, ¿cómo puedes derrotar al destructor de marcos?
Tuve algunos pensamientos, pero nada funcionó en mis pruebas:
- intentar borrar el evento
onbeforeunload = null
través deonbeforeunload = null
no tuvo ningún efecto - agregar una
alert()
detuvo el proceso, le hizo saber al usuario que estaba sucediendo, pero no interfirió con el código de ninguna manera; Al hacer clic en Aceptar, el reventar continúa de la forma habitual - No se me ocurre ninguna forma de borrar el temporizador
setInterval()
No soy un gran programador de JavaScript, así que este es mi desafío: hola, ¿puedes acabar con el destructor de marcos?
A partir de 2015, debe usar la directiva de frame-ancestors
de frame-ancestors
de CSP2 para esto. Esto se implementa a través de un encabezado de respuesta HTTP.
p.ej
Content-Security-Policy: frame-ancestors ''none''
Por supuesto, no muchos navegadores son compatibles con CSP2, por lo que es aconsejable incluir el antiguo encabezado de X-Frame-Options
:
X-Frame-Options: DENY
Recomendaría incluir ambos de todos modos, de lo contrario, su sitio continuaría siendo vulnerable a los ataques de Clickjacking en los navegadores antiguos y, por supuesto, obtendría marcos no deseados incluso sin intenciones maliciosas. La mayoría de los navegadores se actualizan automáticamente en estos días, sin embargo, todavía se tiende a atascar a los usuarios corporativos con versiones antiguas de Internet Explorer por razones de compatibilidad de aplicaciones heredadas.
Bueno, puedes modificar el valor del contador, pero eso es obviamente una solución frágil. Puede cargar su contenido a través de AJAX después de haber determinado que el sitio no está dentro de un marco, tampoco es una gran solución, pero es de esperar que evite la activación del evento antes de la descarga (supongo).
Edit: Otra idea. Si detecta que está en un marco, pídale al usuario que deshabilite javascript, antes de hacer clic en un enlace que lo lleve a la URL deseada (pasando una cadena de consulta que le avise a su página para decirle al usuario que puede volver a habilitar javascript una vez que lo haga). hay).
Edit 2: Go nuclear: si detectas que estás en un marco, simplemente elimina el contenido del cuerpo de tu documento e imprime un mensaje desagradable.
Edición 3: ¿Se puede enumerar el documento superior y establecer todas las funciones en nulo (incluso las anónimas)?
Creo que ya casi estabas allí. Has probado:
window.parent.onbeforeunload = null;
window.parent.location.replace(self.location.href);
o alternativamente:
window.parent.prevent_bust = 0;
Nota: en realidad no probé esto.
Después de reflexionar sobre esto por un momento, creo que esto les mostrará quién es el jefe ...
if(top != self) {
window.open(location.href, ''_top'');
}
El uso de _top
como parámetro de destino para window.open()
lo iniciará en la misma ventana.
Es posible que acabe de encontrar una forma de romper el javascript del destructor de cuadros. Al usar getElementsByName en mi función javascript, he establecido un bucle entre el destructor de cuadros y la secuencia de comandos del destructor de marcos. Revisa esta publicación. http://www.phcityonweb.com/frame-buster-buster-buster-2426
FWIW, la mayoría de los navegadores actuales son compatibles con la directiva X-Frame-Options: deny , que funciona incluso cuando el script está deshabilitado.
IE8:
http://blogs.msdn.com/ie/archive/2009/01/27/ie8-security-part-vii-clickjacking-defenses.aspx
Firefox (3.6.9)
https://bugzilla.mozilla.org/show_bug.cgi?id=475530
https://developer.mozilla.org/en/The_X-FRAME-OPTIONS_response_header
Chrome / Webkit
http://blog.chromium.org/2010/01/security-in-depth-new-security-features.html
http://trac.webkit.org/changeset/42333
Hemos utilizado el siguiente enfoque en uno de nuestros sitios web de http://seclab.stanford.edu/websec/framebusting/framebust.pdf
<style>
body {
display : none
}
</style>
<script>
if(self == top) {
document.getElementsByTagName("body")[0].style.display = ''block'';
}
else{
top.location = self.location;
}
</script>
Llegó con esto, y parece funcionar al menos en Firefox y en el navegador Opera.
if(top != self) {
top.onbeforeunload = function() {};
top.location.replace(self.location.href);
}
No estoy seguro de si esto es viable o no, pero si no puedes romper el marco, ¿por qué no mostrar una advertencia? Por ejemplo, si su página no es la "página principal", cree un método setInterval que intente romper el marco. Si después de 3 o 4 intentos, su página aún no es la página principal, cree un elemento div que cubra toda la página (cuadro modal) con un mensaje y un enlace como ...
Estás viendo esta página en una ventana de marco no autorizada - (Blah blah ... problema de seguridad potencial)
haga clic en este enlace para solucionar este problema
No es el mejor, pero no veo ninguna forma de que puedan salir de eso con un script.
Ok, entonces sabemos que estaban en un marco. Así que ubicamos a otra página especial con la ruta como una variable GET. Ahora explicamos al usuario lo que está sucediendo y proporcionamos un enlace con una opción target = "_ TOP". Es simple y probablemente funcionaría (no lo he probado), pero requiere cierta interacción del usuario. Tal vez usted podría señalar el sitio ofensivo al usuario y crear un lugar de vergüenza para los usuarios que hacen clic en su sitio en algún lugar ... Solo una idea, pero funciona de noche ...
Si agrega una alerta justo después del código del destructor, la alerta detendrá el hilo de javascript y permitirá que la página se cargue. Esto es lo que hace , y se quita de mis iframes, incluso cuando uso el destructor de marcos. También funcionó con mi página de prueba simple. Esto solo se ha probado en Firefox 3.5 e IE7 en Windows.
Código:
<script type="text/javascript">
if (top != self){
top.location.replace(self.location.href);
alert("for security reasons bla bla bla");
}
</script>
Si observa los valores devueltos por setInterval()
, generalmente son dígitos únicos, por lo que generalmente puede desactivar todas estas interrupciones con una sola línea de código:
for (var j = 0 ; j < 256 ; ++j) clearInterval(j)
Teniendo en cuenta el estándar HTML5 actual que introdujo la zona de pruebas para iframe, todos los códigos que destruyen los marcos que se proporcionan en esta página se pueden desactivar cuando el atacante utiliza la zona de pruebas porque restringe el iframe de lo siguiente:
allow-forms: Allow form submissions.
allow-popups: Allow opening popup windows.
allow-pointer-lock: Allow access to pointer movement and pointer lock.
allow-same-origin: Allow access to DOM objects when the iframe loaded form same origin
allow-scripts: Allow executing scripts inside iframe
allow-top-navigation: Allow navigation to top level window
Ahora, considere que el atacante usó el siguiente código para alojar su sitio en iframe:
<iframe src="URI" sandbox></iframe>
Entonces, todo el código de JavaScript que rompe el marco fallará.
Después de verificar todo el código de bus de cuadros, solo esta defensa funciona en todos los casos:
<style id="antiClickjack">body{display:none !important;}</style>
<script type="text/javascript">
if (self === top) {
var antiClickjack = document.getElementById("antiClickjack");
antiClickjack.parentNode.removeChild(antiClickjack);
} else {
top.location = self.location;
}
</script>
la propuesta originalmente por http://seclab.stanford.edu/websec/framebusting/framebust.pdf
Todas las soluciones propuestas forzan directamente un cambio en la ubicación de la ventana superior. ¿Qué pasa si un usuario quiere que el marco esté allí? Por ejemplo, el cuadro superior en los resultados de imagen de los motores de búsqueda.
Escribí un prototipo donde, de forma predeterminada, todas las entradas (enlaces, formularios y elementos de entrada) están deshabilitadas y / o no hacen nada cuando se activan.
Si se detecta un marco que contiene, las entradas se dejan deshabilitadas y se muestra un mensaje de advertencia en la parte superior de la página. El mensaje de advertencia contiene un enlace que abrirá una versión segura de la página en una nueva ventana. Esto evita que la página se use para clickjacking, mientras que permite que el usuario vea el contenido en otras situaciones.
Si no se detecta ningún marco que contenga, las entradas están habilitadas.
Aquí está el código. Debe establecer los atributos HTML estándar en valores seguros y agregar atributos adicionales que contengan los valores reales. Probablemente esté incompleto y para una seguridad total, los atributos adicionales (estoy pensando en los manejadores de eventos) probablemente tendrán que ser tratados de la misma manera:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN">
<html>
<head>
<title></title>
<script><!--
function replaceAttributeValuesWithActualOnes( array, attributeName, actualValueAttributeName, additionalProcessor ) {
for ( var elementIndex = 0; elementIndex < array.length; elementIndex += 1 ) {
var element = array[ elementIndex ];
var actualValue = element.getAttribute( actualValueAttributeName );
if ( actualValue != null ) {
element[ attributeName ] = actualValue;
}
if ( additionalProcessor != null ) {
additionalProcessor( element );
}
}
}
function detectFraming() {
if ( top != self ) {
document.getElementById( "framingWarning" ).style.display = "block";
} else {
replaceAttributeValuesWithActualOnes( document.links, "href", "acme:href" );
replaceAttributeValuesWithActualOnes( document.forms, "action", "acme:action", function ( form ) {
replaceAttributeValuesWithActualOnes( form.elements, "disabled", "acme:disabled" );
});
}
}
// -->
</script>
</head>
<body onload="detectFraming()">
<div id="framingWarning" style="display: none; border-style: solid; border-width: 4px; border-color: #F00; padding: 6px; background-color: #FFF; color: #F00;">
<div>
<b>SECURITY WARNING</b>: Acme App is displayed inside another page.
To make sure your data is safe this page has been disabled.<br>
<a href="framing-detection.html" target="_blank" style="color: #090">Continue working safely in a new tab/window</a>
</div>
</div>
<p>
Content. <a href="#" acme:href="javascript:window.alert( ''Action performed'' );">Do something</a>
</p>
<form name="acmeForm" action="#" acme:action="real-action.html">
<p>Name: <input type="text" name="name" value="" disabled="disabled" acme:disabled=""></p>
<p><input type="submit" name="save" value="Save" disabled="disabled" acme:disabled=""></p>
</form>
</body>
</html>
Use htaccess para evitar el conjunto de marcos de alto jacking, iframe y cualquier contenido como imágenes.
RewriteEngine on
RewriteCond %{HTTP_REFERER} !^http://www/.yoursite/.com/ [NC]
RewriteCond %{HTTP_REFERER} !^$
RewriteRule ^(.*)$ /copyrights.html [L]
Esto mostrará una página de derechos de autor en lugar de la esperada.
Voy a ser valiente y arrojar mi sombrero en el anillo de este (antiguo como es), ver cuántos votos a la baja puedo recopilar.
Aquí está mi intento, que parece funcionar en todos los lugares donde lo he probado (Chrome20, IE8 y FF14):
(function() {
if (top == self) {
return;
}
setInterval(function() {
top.location.replace(document.location);
setTimeout(function() {
var xhr = new XMLHttpRequest();
xhr.open(
''get'',
''http://mysite.tld/page-that-takes-a-while-to-load'',
false
);
xhr.send(null);
}, 0);
}, 1);
}());
Coloqué este código en el <head>
y lo llamé desde el final del <body>
para asegurar que mi página se procesa antes de que comience a discutir con el código malicioso, no sé si este es el mejor enfoque, YMMV.
¿Como funciona?
... te oigo preguntar - bueno, la respuesta honesta es, realmente no lo sé. Tomé muchas precauciones para que funcionara en todos los lugares que estaba probando, y el efecto exacto que varía varía según el lugar donde lo ejecutes.
Aquí está el pensamiento detrás de esto:
- Establecer una función para ejecutar en el intervalo más bajo posible. El concepto básico detrás de cualquiera de las soluciones realistas que he visto es llenar el programador con más eventos de los que tiene el destructor de marcos.
- Cada vez que se activa la función, intente cambiar la ubicación del marco superior. Requisito bastante obvio.
- También programe una función para que se ejecute inmediatamente, lo que llevará mucho tiempo en completarse (lo que impedirá que el destructor de tramas interfiera con el cambio de ubicación). Elegí un XMLHttpRequest síncrono porque es el único mecanismo que se me ocurre que no requiere (o al menos pedir) la interacción del usuario y no reduce el tiempo de CPU del usuario.
Para mi http://mysite.tld/page-that-takes-a-while-to-load
(el objetivo del XHR) usé un script PHP que se parece a esto:
<?php sleep(5);
¿Lo que pasa?
- Chrome y Firefox esperan 5 segundos mientras se completa el XHR, luego se redirigen con éxito a la URL de la página enmarcada.
- IE redirige casi de inmediato
¿No puedes evitar el tiempo de espera en Chrome y Firefox?
Aparentemente no. Al principio, señalé el XHR a una URL que devolvería un 404, esto no funcionó en Firefox. Entonces probé el sleep(5);
Enfoque al que finalmente llegué para esta respuesta, luego comencé a jugar con la duración del sueño de varias maneras. No pude encontrar un patrón real para el comportamiento, pero sí encontré que si es demasiado corto, específicamente Firefox no jugará a la pelota (Chrome e IE parecen tener un comportamiento bastante bueno). No sé cuál es la definición de "demasiado corto" en términos reales, pero 5 segundos parece funcionar siempre.
Si alguno de los ninjas que usan Javascript quiere explicar un poco mejor lo que está pasando, por qué esto (probablemente) es incorrecto, no es confiable, es el peor código que han visto, etc. Lo escucharé con mucho gusto.
setInterval y setTimeout crean un intervalo de incremento automático. Cada vez que se llama a setTimeout o setInterval, este número aumenta en uno, de modo que si llama a setTimeout, obtendrá el valor actual más alto.
var currentInterval = 10000;
currentInterval += setTimeout( gotoHREF, 100 );
for( var i = 0; i < currentInterval; i++ ) top.clearInterval( i );
// Include setTimeout to avoid recursive functions.
for( i = 0; i < currentInterval; i++ ) top.clearTimeout( i );
function gotoHREF(){
top.location.href = "http://your.url.here";
}
Ya que es casi inaudito que haya 10000 setIntervals y setTimeouts simultáneos funcionando, y puesto que setTimeout devuelve "último intervalo o tiempo de espera creado + 1", y dado que top.clearInterval sigue siendo accesible, esto anulará los ataques de sombrero negro al marco sitios web que se describen anteriormente.
if (top != self) {
top.location.replace(location);
location.replace("about:blank"); // want me framed? no way!
}