Федеральная Служба Опасности (malaya_zemlya) wrote,
Федеральная Служба Опасности
malaya_zemlya

Categories:

Джаваскриптовское

Вот вполне честная работающая программа на Джаваскрипте:

($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+($$=($_=!''+$)[_/_]+$_[+$])])()[__[_/_]+__[_+~$]+$_[_]+$$](_/_)


Можете запустить в браузере, если не верите (не бойтесь, не вирус). Должно вывалиться сообщение с текстом "1", всего-то.

Теперь собираем мозги обратно внутрь черепной коробки и разбираемся, как это работает по шагам. Итак:

$=[]

Все просто. Переменной под названием $ присваивается значение в виде пустого массива.

__=!$+$

__ как и $ - легальное название переменной. Чему она равна? !$ сначала превращает значение $ в булевский тип, потом делает отрицание. Массив (любой) всегда превращается в булевский true, значит, на выходе у нас false. Теперь пытаемся сложить false и [] . Джаваскрипт умеет складывать хоть яблоки с аэростатами, в таких случаях и те, и те сначала конвертятся в строчки, как правило. false становится "false", а [] - пустой строкой. Итого "false"

_=-~-~-~$

~ это побитовое отрицание, а _ это тоже легальное название переменной. Чтоб значение побитово отрицать, его сначала превращают в 32-битное число. Не можешь - научим. Сначала превратим в строку (пустую, как мы уже видели), потом распарсим строку как float (получается 0.0), потом float обрежем до целого, т.е просто 0. Браузеры поумнее обходятся без промежуточной стадии, но стандарт - в принципе - требует, чтоб численные значения представлялись в общем случае с плавающей точкой. Кроме, конечно, исключений, вроде битовых операций.

Да. Мы не еще закончили. ~$ у нас получилось побитовым отрицанием 0, т.е числом изо всех единичных битов, что, как известно, есть -1. -~$ это, стало быть, 1. В качестве несложного упражнения для читателя, оставляю убедиться, что -~x увеличивает любое число на единицу. Инкрементируем таким образом три раза, получаем _ = 3

Следующим шагом мы считаем
(__=!$+$)[_=-~-~-~$] или "false"[3]

Строчки в джаваскрипте ведут (почти) как массивы, поэтому мы берем элемент по индексу 3, и получаем букву "s".

({}+$)[_/_]

3 делим на 3, получаем 1 (обратите внимание, этот трюк используется несколько раз) {} - это пустой объект, + как и в прошлый раз, превращает его в строку. На сей раз строка будет "[object Object]" Так принято. Складываем с пустым-массивом-превращенным-в-пустую-строку, ничего не меняется. У нас получился метод перевода значений в строки. Можно было бы написать ({}).toString() или '' + {} То же самое. (зато {} + '' даст совсем другой результат. Ладно, не будем отвлекаться) Берем от "[object Object]" элемент с индексом 1, это "о"

($_=!''+$)[_/_]

Это уже элементарщина. ! как мы знаем, превращает значение в булевское и логически отрицает. Пустая строчка превращается (в отличие, от пустого массива) в false, а ее отрицание в true, сложение с $ опять превращает значение в строчку, то есть "true" (заодно его сохраняем в переменную $_) , а от строки берется элемент 1, то есть "r"

$$=(($_=!''+$)[_/_] + $_[+$])

Первое слагаемое только что разобрали. Во втором мы считаем +$ что эквивалентно превращению значения переменной $ в число. Как мы уже проходили, это просто 0 Чему равно $_ мы тоже знаем - это "true" нулевой элемент от "true" - это "t" . Складывем с результатом предыдущего шага, выходит "rt". Нам "rt" еще понадобится, поэтому сохраняем его в переменную с мнемоническим именем $$

Теперь мы складываем вместе результаты предыдущих шагов получаем... "s" + "о" + "rt" то есть "sort"

Следите еще? Теперь мы почти выяснили, чему равняется под-выражение

($=[$=[]][(__=!$+$)[_=-~-~-~$]+({}+$)[_/_]+($$=($_=!''+$)[_/_]+$_[+$])])

Это же тоже самое что и

[]["sort"]

Как известно каждому ребенку, все объекты в джаваскрипте - это хэш-мапы, индексированные строчками. В том числе и массивы. У массивов, кроме собственно элементов есть еще и методы, они тоже индексированы строчками. x["sort"] это тоже что и х.sort В случае массива, у нас получается ссылка на функцию сортировки (по-простому можно было бы написать Array.prototype.sort, но кто ж так пишет?). Ее мы пока сохраняем в переменную $, стирая предыдущее значение.

Теперь у нас есть функция sort, которую и исполняем. Это происходит, когда интерпретатор доходит до () посреди выражения. Но sort это функция-метод, она обычно вызывается так:

[2,1].sort()
[1,2]

А что если ее выполнить просто так? Просто так в Джаваскрипте не бывает. Все функции выполняются на каком-то объекте. Если он явно не указан, то им будет глобальный объект window. Что будет, если отсортировать window? Ничего с ним не будет, у него нет элементов с номерами (можно добавить, но в эту степь мы не пойдем) sort вернет объект в исходном виде. Таким образом мы получили себе ссылку на глобальный объект window. Наше выражение сократилось до

window[__[_/_]+__[_+~$]+$_[_]+$$](_/_)

Почти все под-выражения мы уже встречали, кроме

_+~$

_ у нас равно 3, а с ~$ поступаем обычно. Превращаем $, который у нас теперь функция sort, в строчку, выходит "function sort() {\n [native code]\n}" (или что-то в этом духе, в зависимости от браузера). Затем парсим в число. Вообще-то получается NaN (Not a Number), что обычно означает ошибку, но джаваскриптовские побитовые операции так просто не сдаются. Для них NaN это ноль. Отрицание 0, как мы видели, равно -1. Значит, имеем 3+(-1)=2.

Подставляем значения всех переменных:

window["false"[1]+"false"[2]+"true"[3]+"rt"](1)

или

window["alert"](1)

Как уже обсуждалось, это то же самое, что выполнить функцию alert на глобальном объекте window с параметром 1. Иными, неинтересными, словами:

alert(1)

Что и происходит. Вот, собственно, и все дела. Теперь можно шутить про Перл.


Источник: код взят отcюда , куда попал с конференции Blackhat DC 2010, но автор остался не указан. Возможно, кто-то со sla.ckers.org, где третий год растет длиннючий тред на тему обхода защиты от межсайтового скриптинга. Если кто хочет поразбираться в наворотах джаваскрипта и HTML итп, то вам туда. Попробуйте побиться головой об клавиатуру - результат будет удивительно похож на представленный в треде код.

Update: В коментах на реддите дают ссылку на конвертор любого джаваскрипта в эквивалентный скрипт, состоящий только из символов []()+! К примеру, тот же

alert(1)

превращается в

([][(![]+[])[!+[]+!+[]+!+[]]+(!![]+[][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]])[+!+[]+[+[]]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]][([][(![]+[])[+[]]+(![]+[]+[][[]])[+!+[]+[+[]]]+(![]+[])[!+[]+!+[]]+(!![]+[])[+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]]+[])[!+[]+!+[]+!+[]]+(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(![]+[])[!+[]+!+[]]]()[(![]+[])[+!+[]]+(![]+[])[!+[]+!+[]]+(!![]+[])[!+[]+!+[]+!+[]]+(!![]+[])[+!+[]]+(!![]+[])[+[]]])(+!+[])
Subscribe
  • Post a new comment

    Error

    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.
  • 23 comments