все заметки

Content type и disposition для XSS

2025.03.20

Прошло уж восемь лет, как я обнаружил символы , и (, которыми можно манипулировать типом контента mime в content-type. И вот стало интересно, а что-то изменилось вообще?

Достал свой старый недофаззер, Chrome (132), Firefox (136) и Safari (18). И погнал:

Content-type

Добавился новый тип application/xhtml+xml. А вот из Firefox выпилили text/xsl.

Вот такое:

content-typechromefirefoxsafari
text/html+++
text/xml+++
image/svg+xml+++
application/xml+++
application/xhtml+xml+++
text/xsl++
multipart/x-mixed-replace**
application/mathml+xml+
application/rdf+xml+

html в text/html и text/xsl, а во всех остальных это xml - куда запихивается svg.

Интереснее multipart/x-mixed-replace, это аналог multipart/mixed в письмах (eml).

То есть, нужный content-type указывается уже в блоке (не в headers), но в headers нужно иметь возможность указать boundary=section:

Content-type: multipart/x-mixed-replace; boundary=section

Тело:

--section\nContent-Type: text/html; charset="utf-8"\n\n<img src onerror="alert(origin)">

Это справедливо для Firefox (тело должно быть более одной строки) и Safari: multipart/x-mixed-replace

И только в Safari можно не указывать boundary - будет обычный html.

Extension

Все зависит от серверного софта который обрабатывает эти расширения. На примере Nginx mime.types видно, что не у всех есть расширения для наших mime, и тогда это будет application/octet-stream.
И вообще это не интересно:

content-typeextension
text/htmlhtml, htm, shtml
text/xmlxml
image/svg+xmlsvg, svgz
application/xml
application/xhtml+xmlxhtml
text/xsl
multipart/x-mixed-replace
application/mathml+xml
application/rdf+xml

Без content-type

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

Если встречается первый валидный html-тег, то рендерится html. В то же время <meta> для Chrome - непонятный тэг (именно первый).

А если <?xml, то пытается обработать XML. И в то же время для Firefox важно отсутствие пустых символов перед этим тегом [^\s].

Но Firefox идет еще дальше, и если не удалось идентифицировать контент [\s]+, то отталкивается от расширения файла из pathname. К известным добавляются эти (все это XML):

xslt, xsl, xht, wsdl, svc, resx, rdf, aspx, asmx, ashx, ascx, asax, asa

Магические символы

Здесь немного поменялось поведение, но запятая , рулит вне сомнения. Если есть запятая, то парсится валидный mime:

payloadchromefirefoxsafari
\timage/svg+xml\x09invalid++
\tinvalid\x09image/svg+xml
,image/svg+xml\x2Cinvalid+++
,invalid\x2Cimage/svg+xml+++
,invalid; charset=UTF-8\x2Cimage/svg+xml++
(image/svg+xml\x28invalid+
(invalid\x28image/svg+xml

Content-disposition

Ничего необычного, если стоит точка с запятой attachment;, то все пропало. Если ее нет, то через пробел подойдет почти любой символ: attachment @{Z-!. Но только для Chrome и Safari.

Firefox как будто строго сравнивает disposition !== inline, то все attachment.

еще по теме xss