Первые несколько атак этого выпуска Easy Hack будут завязаны на формат SVG. Причем хочется взглянуть даже не на сами атаки, а на потенциальные возможности формата.
Итак, SVG — это Scalable Vector Graphics, язык разметки масштабируемой векторной графики, он входит в подмножество расширяемого языка разметки XML и предназначен для описания двумерной векторной и смешанной векторно-растровой графики в формате XML. То есть мы имеем возможность описать в XML то, что должно быть на рисунке, а также добавить динамику.
Вот так, к примеру, можно нарисовать красный круг.
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
Кроме того, SVG поддерживает CSS. Добавим после тега <svg>
стиль и получим синий круг:
<style>
circle {fill: blue}
</style>
А еще SVG поддерживает JavaScript — с его помощью делается анимация. Для этого можно использовать все тот же стандартный тег <script>
:
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
<script>alert(document.cookie)</script>
</svg>
SVG поддерживает и XLink (создание ссылок между документами XML), что дает возможность подгружать ресурсы из сторонних файлов. Тот же alert()
можно подгрузить из файла:
<script type="text/javascript" xlink:href="alert.js"></script>
Причем в некоторых браузерах можно подгружать ресурсы и со сторонних хостов.
Интересно, что в SVG можно встраивать код на HTML (тег foreignObject
) и картинки (<image>
). При этом SVG в той или иной мере поддерживается всеми основными браузерами.
Как видишь, хоть SVG и картинка, но из нее можно без проблем запускать код на JavaScript. Таким образом, если есть какой-то сайт, куда можно загружать картинки в SVG, то можно попытаться получить на этом сайте хранимую XSS’ку. Для этого нужно знать еще несколько тонкостей, связанных с тем, как браузер открывает SVG. Есть несколько вариантов вставить SVG:
- как картинку — через тег
<img>
или свойство CSSbackground-image
. Но в этом случае во всех современных браузерах JavaScript выполняться не будет; - как сторонний объект — с помощью тегов
<object>
,<embed>
,<iframe>
. JS в этом случае работает, но требуется помнить про то, что работают и стандартные Same Origin Policy; - встроить в саму страницу (inline). Примеры выше как раз такие, и JavaScript работает;
- с помощью тега canvas. По идее, JS в этом случае работать не должен, но подтверждения этому я не нашел.
Если мы загрузим на сервер-жертву файл SVG, то, возможно, он отобразится, но в нем не будет работать JavaScript — как раз из-за того, что он подгружается с помощью тега <img>
. Но мы спокойно можем воспользоваться вторым или третьим методом и использовать прямую ссылку на наш SVG на атакуемом сервере.
Интересный момент: к SVG применяются не все правила парсинга XML. Возможно, это связано лишь с известной гибкостью браузерных парсеров. Например, для корректного XML необходимо, чтобы значения атрибутов элементов были обрамлены двойными кавычками (см. пример выше). Но в SVG мы можем избавиться от них.
<circle cx=50 cy=50 r=40 stroke=black stroke-width=3 fill=red />
Кроме того, если где-то будет незакрытая кавычка, то в случае с XML документ не будет считаться корректным, а в SVG такие атрибуты просто пропускаются. То же самое относится и к тегам. Это дает дополнительное пространство для атак.
Еще одну лазейку открывает то, что в SVG можно встраивать другие документы или даже тот же самый документ. Это может быть использовано для обхода Content Security Policy — примеры можно увидеть в презентации с Black Hat 2014, один из них я разберу подробнее.
Ну и последнее, что нужно знать об SVG, — он является «официальным» XML и потому глубоко связан с остальным семейством форматов. SVG поддерживает Document Type Definition (DOCTYPE) с сущностями (entity), а потому есть потенциальная возможность для эксплуатации XXE. Также он поддерживает технологию XSLT. Можно, например, сделать такой файл SVG, который при открытии с помощью тега <img>
будет показывать картинку, а при открытии в <iframe>
будет с помощью XSLT-преобразования превращаться в HTML (должно работать в IE и FF).
<?xml version="1.0"?>
<?xml-stylesheet type="text/xml" href="#stylesheet"?>
<!DOCTYPE doc [ <!ATTLIST xsl:stylesheet id ID #REQUIRED>]>
<svg xmlns="http://www.w3.org/2000/svg">
<xsl:stylesheet id="stylesheet" version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
<xsl:template match="/">
<iframe xmlns="http://www.w3.org/1999/xhtml" src="javascript:alert(1)"></iframe>
</xsl:template>
</xsl:stylesheet>
<circle fill="red" r="40"></circle>
</svg>
Возможности SVG очень широки, а вот методы их применения для атак еще далеко не полностью изучены, так что можно ждать новостей на этом фронте или экспериментировать самостоятельно.