Глава 7. JavaScript без букв и цифр
Содержание
Все началось с того, что пользователи форума бездельников (slackers) заметили неожиданный новый пост Йосуке Хасэгавы, выдающегося японского
исследователя безопасности. В посте он подробно описал, как вы можете выполнять JavaScript не применяя буквенно-цифровые символы. Это стало
для всех нас откровением, и мы начали анализировать как это работает. Основная идея состояла в том, чтобы для создания строк использовать
квадратные скобки и выражения JavaScript, а затем для доступа к строкам и их объединения под создание допустимых имён свойств и, в
конечном итоге, написания произвольного JavaScript без буквенно-цифровых символов применять числовые индексы, также основанные на выражениях.
Это также стало известно как JSF*ck. Я скрыл букву "u", чтобы в этой книге не отображались нецензурные слова. С этого момента я буду
называть его подходящим для семьи названием "без букв и цифр" JavaScript, или не-альфа JS. Чтобы создать не-альфа JS, вам сначала нужен
способ генерации числа, а поскольку JavaScript обладает слабой типизацией, вы можете осуществить это при помощи инфиксного оператора
"+"
, данный оператор попытается преобразовать следующее выражение в число или
NaN
(Not a number - не число), когда нет возможности такого преобразования. Итак, первый шаг — получение
нуля:
1 +[]//0
Отлично, итак мы обладаем нулём, но это позволит нам получать лишь самый первый символ строки:
1 'abc'[+[]]//a
Но как мы можем получать "b"
? Ладно, вы можете сочетать метод доступа квадратных скобок
с неким массивом и получать ссылку на элемент в таком массиве, а JavaScript позволяет вам увеличивать/уменьшать на единицу это значение так же,
как будто это было идентификатором:
1 [+[]]//создаёт массив с 0 в нём
2
3 [+[]][+[]]//получает самый первый элемент в этом массиве
4
5 ++[+[]][+[]]//увеличивает на единицу самый первый элемент в этом массиве для создания 1
6
7 'abc'[++[+[]][+[]]]//сочетает все приведённое выше для получения b
Надеюсь, вы следите за ходом действий. Возможно, стоит попробовать каждый отдельный фрагмент кода и оценить его в консоли чтобы понять что происходит. Как только вы усвоите эту концепцию, вы сможете легко приступать к выработке строк и чисел. Вам просто необходимо просто вкладывать вырабатываемые массивы и продолжать увеличивать их и объединять буквы для формирования свойств JavaScript. Давайте сгенерируем число два, а я буду пользоваться пробелами чтобы различать числа:
1 ++[ ++[+[]][+[]] ] [+[]]//2
Обычно вы не пользуетесь пробелами. Я только что добавил их с тем, чтобы было проще отслеживать. Итак, из приведённого выше кода вы можете
наблюдать, что при помощи +[]
вы создаёте массив, в котором содержится ноль, затем вы получаете доступ
к самому первому элементу в этом массиве, снова применяя +[]
, а потом вы применяете оператор приращения
для увеличения числа, которое потом завёртываете в другой массив и следуете тем же самым процессом, причём становится трудно читать при
вложениях дальше и дальше, но как только вы освоите эту концепцию, вы будете способны её писать.
Из своего текста мы способны получить "c"
:
1 'abc'[++[ ++[+[]][+[]] ] [+[]]]
Ну, у нас имеются основы выработки чисел без буквенно- цифровых символов, но как вы сгенерируете строки? Мы снова воспользуемся преимуществами
слабой типизации JavaScript для преобразования различных типов в строки. Например, давайте посмотрим на логические значения, мы способны
извлечь символы "f"
, "a"
,
"l"
, "s"
"e"
из false
и мы можем выполнить аналогичный процесс,
который мы осуществляли для чисел, но на этот раз мы будем применять булев оператор not
,
данный оператор вернёт false
если его операнд можно преобразовать в
true
и наоборот. Это означает, что мы можем воспользоваться пустым массивом снова и преобразовать его в
булев:
1 ![]//false
Когда мы получаем булево значение, нам необходимо преобразовать его в строку чтобы мы были способны выделять необходимые символы. Для выполнения этого мы просто производим его конкатенацию с другим массивом, что оформляет строку с логическим значением и пустым массивом, который преобразуется в пустую строку:
1 ![]+[]//false (строка)
Великолепно, итак теперь у нас имеются символы, но как их выделить? Мы можем последовать тому же процессу что и ранее, мы можем поместить своё выражение вовнутрь массива и получить самый первый элемент в этом массиве (нашей строке), а затем воспользоваться индексом для получения отдельного символа:
1 [![]+[]]//добавляем строковое значение false в массив
2 [![]+[]][+[]]//получаем самый первый элемент своего массива
3 [![]+[]][+[]][+[]]//f - получаем самый первый символ из данной строки
Затем вы можете следовать этим же процессом для всех остающихся символов и просто увеличивать значение индекса, как мы это делали для инкрементации своих чисел. Самый простой способ выполнения этого заключается в выполнении этого для пометки вашего выражения комментария, как я это и сделали последующей комбинации их, таким образом, нам требуется значение следующего символа, стоящего в позиции один. Если мы вернёмся к фрагменту его кода для и скопируете это будет так, как приведено ниже:
1 ++[+[]][+[]]//1
Затем получим false
из другого примера:
1 [![]+[]][+[]]//false (строка)
Теперь соединим вместе строку false
и средство доступа к значению числа:
1 [ ![]+[]] [+[]] [ ++[+[]][+[]] ]//a
Для ясности я выше добавил пробелы. Когда вы собираете символы, целесообразно сохранять их в текстовом файле с комментариями, чтобы показывать
что они собой представляют, это упрощает создание новых строк. Надеюсь, вы теперь достаточно уверенно создаёте такие символы. Давайте
продолжим создавать оставшиеся символы для false
.
1 [ ![]+[]] [+[]] [ ++[++[+[]][+[]]][+[]] ]//l
Вам ясно что я сделал выше. Я просто изменил значение части доступа из своего предыдущего фрагмента кода вновь для увеличения значения числа. Я обернул его в массив, получил самый первый элемент этого массива и увеличил его на единицу. Вы можете проделать это с оставшимися символами:
1 [ ![]+[]] [+[]] [ ++[++[++[+[]][+[]]][+[]]][+[]] ]//s
2 [ ![]+[]] [+[]] [ ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]] ]//e
Как вы можете наблюдать в приводимом выше сопоставлении, при создании символов "s"
и
"e"
требуется лишь небольшое изменение. На самом деле, мы можем повторно применять
весь этот процесс для создания противоположности true
, которая выступает
false
. Итак, помните, когда мы обнаружили, что ![]
вырабатывает
false
? Если мы снова воспользуемся логическим оператором not
,
он преобразует это в true
:
1 !![]//true
Мы просто заменяем одиночный восклицательный знак в каждом из выработанных ранее примеров кода на двойной, скажем:
1 [![]+[]][+[]][+[]]//f
становится
1 [!![]+[]][+[]][+[]]//t
и так далее:
1 [ !![]+[]] [+[]] [ ++[+[]][+[]] ]//r
2 [ !![]+[]] [+[]] [ ++[++[+[]][+[]]][+[]] ]//u
У нас уже имеется "e"
, поэтому нам не нужно вырабатывать его снова. Теперь вы можете увидеть,
как довольно просто генерировать символы. Вы можете задуматься о том, как можно сгенерировать произвольный JavaScript. Ну, сначала вам нужно
получить доступ к функции, и для этого вам нужно сгенерировать некоторые символы, которые при использовании в качестве средства доступа получают
функцию, а затем вы можете применять эту функцию, чтобы получить её конструктор, который будет конструктором функции, Вы видите, куда это ведёт?
Получив доступ к конструктору Function
, вы можете вызывать его для генерации произвольного JavaScript, но об
этом мы поговорим позже. Самый первый шаг состоит в получении функции, и очень удобно, что имеется хорошая короткая функция, к которой мы уже можем
получить доступ при помощи выработанных нами символов. Функция at
позволяет вам получать один символ строки
или элемент массива в зависимости от того, для какого объекта вы её применяете. Мы собираемся применять это, потому как, очевидно, это длина
сортировки. Итак, сначала нам нужен пустой массив:
1 []
Затем мы добавляем средство доступа:
1 [] [ ]
Теперь мы добавляем строку "a"
и соединяем её с
"t"
:
1 [] [ [ ![]+[]] [+[]] [ ++[+[]][+[]] ] /*a* + [!![]+[]][+[]][+[]] \
2 /*t*/ ]//функция at
Раз мы обладаем доступом к функции, мы получаем возможность выработки гораздо большего числа символов. Это обусловлено тем, что функция способна преобразовываться в строку:
1 [].at+''//function at() { [естественный код] }
Если мы ищем выработанные нами ранее символы, единственными остающимися для производства нами символами выступают
"o"
, "c"
,
"n"
. Мы можем сгенерировать "n"
при помощи
undefined
, что мы и выполняем далее. Сначала мы создадим пустой массив и испытаем доступ к первому
undefined
символу:
1 [][+[]]//undefined
Затем мы преобразуем это в строку и выполним доступ ко второму символу с позицией один:
1 [[][+[]]+[]][+[]][++[+[]][+[]]]//n
Теперь мы можем выработать всё остальное для создания своего свойства конструктора. Для выработки остающихся символов мы можем повторно
воспользоваться функцией at
, преобразуя её в строку, выработать необходимое положение и, в конце
концов, выделить его.
Сначала мы создаём пустой массив и получаем доступ к его первому элементу:
1 [][+[]]
Затем мы помещаем свою функцию вовнутрь этого массива и выполняем конкатенацию с пустым массивом для создания строки:
1 [ [] [[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]] +[] ][+[]]
Мы можем повторно воспользоваться строкой выше для выработки "c"
:
1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[+[]][+[]]][+[]]][+[]]]//3
4 //совместно производят c
Самая первая приведённая выше строка вырабатывает функцию at
в виде строки, вторая строка выполняет
доступ к третьей позиции этой строки, которая производит "c"
.
Для выработки "o"
нам снова требуется следовать этим же процессом, но получить доступ к 6й
позиции строки:
1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]//6
4 //совместно производят o
В точности как с пазлом, мы можем совместить это вместе для получения доступа к самому свойству конструктора:
1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 [++[++[++[+[]][+[]]][+[]]][+[]]]
3 //c
4
5 +
6
7 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
8 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]
9 //o
10
11 +
12
13 [[][+[]]+[]][+[]][++[+[]][+[]]]//n
14
15 +
16
17 [ ![]+[]] [+[]] [ ++[++[++[+[]][+[]]][+[]]][+[]] ]//s
18
19 +
20
21 [!![]+[]][+[]][+[]]//t
22
23 +
24
25 [ !![]+[]] [+[]] [ ++[+[]][+[]] ]//r
26
27 +
28
29 [ !![]+[]] [+[]] [ ++[++[+[]][+[]]][+[]] ]//u
30
31 +
32
33 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
34 [++[++[++[+[]][+[]]][+[]]][+[]]]
35 //c
36
37 +
38
39 [!![]+[]][+[]][+[]]//t
40
41 +
42
43 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
44 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]
45 //o
46
47 +
48
49 [ !![]+[]] [+[]] [ ++[+[]][+[]] ]//r
Выше я отделил все буквы и поместил оператор конкатенации строк в каждый раздел, чтобы вы могли наблюдать как это работает. Когда всё
формируется воедино, это выстраивает строку "constructor"
. Для получения доступа к
реальной функции- конструктору, нам необходимо воспользоваться функцией at()
, к которой мы ранее в
этой главе уже получили доступ без её преобразования в строку:
1 [ [] [[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]] ][+[]]
2 //функция at()
3 [//добавили квадратные кавычки для формирования доступа к предыдущей функции
4
5 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
6 [++[++[++[+[]][+[]]][+[]]][+[]]]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]\
7 ]]+[]][+[]]
8 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[][+[]]+[]][+[]][++[+[]\
9 ][+[]]]+[ ![]+[]] [+[]] [ ++[++[++[+[]][+[]]][+[]]][+[]] ]+[!![]+[]][+[]
10 ][+[]]+[ !![]+[]] [+[]] [ ++[+[]][+[]] ]+[ !![]+[]] [+[]] [ ++[
11 ++[+[]][+[]]][+[]] ]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[
12 ]]
13 [++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][+[]]+[[] [[![]+[]][+[]][++[+[]][+[]]\
14 ]+[!![]+[]][+[]][+[]]]+[]][+[]]
15 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[ !![]+[]] [+[]] \
16 [ ++[+[]][+[]] ]
17
18 ]//добавили квадратные кавычки для формирования доступа к предыдущей функции
19
20 //всё это вместе создаёт конструктор Function
Мы получили доступ к конструктору Function
, соединив функцию at()
,
а добавляя []
после и внутри метода доступа мы разместили строку
"constructor"
, которая затем возвращает необходимый конструктор
Function
. Теперь мы можем исполнить произвольный JavaScript, передавая конструктору
Function
некую строку и вызывая её дважды.
Теперь нам просто нужно выработать строку для её отправки конструктору Function
. Мы собираемся вызвать
alert(1)
в качестве традиционной полезной нагрузки XSS. У нас уже есть буквы и цифра один:
1 [ ![]+[]] [+[]] [ ++[+[]][+[]] ]//a
2 [ ![]+[]] [+[]] [ ++[++[+[]][+[]]][+[]] ]//l
3 [ ![]+[]] [+[]] [ ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]] ]//e
4 [ !![]+[]] [+[]] [ ++[+[]][+[]] ]//r
5 [!![]+[]][+[]][+[]]//t
6 ++[+[]][+[]]//1
Нам остаётся сгенерировать открывающую и закрывающую скобки. Для этого мы можем повторно воспользоваться кодом, в котором мы выработали
свою функцию at()
и преобразовали это в строку и затем получить доступ к 6й позиции данной строки:
1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]//6
Нам всего лишь требуется увеличить значение шесть для получения одиннадцатой позиции:
1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]//function at() { [естест\
2 венный код] } в качестве строки
3 [++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]\
4 ]][+[]]][+[]]][+[]]]//11
5 //который производит (
И увеличить приведённое выше на единицу:
1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][\
4 +[]]][+[]]][+[]]][+[]]][+[]]]//12
5 //который производит )
Нам просто нужно расположить эти части в верном порядке и передать их ранее выработанному конструктору и это всё. Не забывайте добавлять
к каждой из строк оператор канкатенации "+"
.
1 [ [] [[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]] ][+[]]
2
3 [
4
5 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
6 [++[++[++[+[]][+[]]][+[]]][+[]]]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]\
7 ]]+[]][+[]]
8 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[][+[]]+[]][+[]][++[+[]\
9 ][+[]]]+[ ![]+[]] [+[]] [ ++[++[++[+[]][+[]]][+[]]][+[]] ]+[!![]+[]][+[]
10 ][+[]]+[ !![]+[]] [+[]] [ ++[+[]][+[]] ]+[ !![]+[]] [+[]] [ ++[
11 ++[+[]][+[]]][+[]] ]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[
12 ]]
13 [++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][+[]]+[[] [[![]+[]][+[]][++[+[]][+[]]\
14 ]+[!![]+[]][+[]][+[]]]+[]][+[]]
15 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[ !![]+[]] [+[]] \
16 [ ++[+[]][+[]] ]
17
18 ]
19 (
20 [ ![]+[]] [+[]] [ ++[+[]][+[]] ]+//a
21 [ ![]+[]] [+[]] [ ++[++[+[]][+[]]][+[]] ]+//l
22 [ ![]+[]] [+[]] [ ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]] ]+//e
23 [ !![]+[]] [+[]] [ ++[+[]][+[]] ]+//r
24 [!![]+[]][+[]][+[]]+//t
25 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
26 //function at() { [естественный код] } в качестве строки
27 [++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]\
28 ]][+[]]][+[]]][+[]]]+
29 //(
30
31 ++[+[]][+[]]+//1
32 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
33 //function at() { [естественный код] } в качестве строки
34 [++[++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][\
35 +[]]][+[]]][+[]]][+[]]][+[]]]//12
36 //)
37 )
Я надеюсь, вы следовали за нами и теперь способны создавать JS без альфа! С этим кодом вы можете осуществить некоторые оптимизации,
например, сократить [![]+[]][+[]]
до (![]+[])
, в этом коде
присутствует большое число мест для уменьшения. В качестве упражнения попробуйте сократить приведённый выше код до минимально возможного,
тем самым вы больше узнаете о JavaScript и вскоре будете способны писать JS без альфа как обычный код.
Теперь, когда вы уверенно пишите не-альфа код, мы можем воспользоваться полученные в предыдущих главах знаниями чтобы попытаться создать не-альфа код без круглых скобок. Для этой задачи мы будем применять ограниченный набор символов, а именно:
1 []`+!${}
Как вы уже знаете, шаблонные строки способны выполнять JavaScript через заполнители, причём их можно применять и для передачи аргументов
функциям. Мы намерены неверно воспользоваться этим фактом дабы создать некую не- альфа последовательность, которая вызывает конструктор
Function
с нашей строкой alert
.
Мы можем повторно воспользоваться кодом из предыдущего раздела данной главы, потому как нам требуется доступ к конструктору
Function
для передачи ему кода.
Мы намерены вызвать такой конструктор Function
воспользовавшись помеченной строкой шаблона,
что просто означает, что мы намерены поместить ``
после такой функции, а затем мы намерены
выработать свою строку для прохода к ней. Для представления аргумента конструктору Function
мы
воспользуемся символом $
, который мы не собираемся применять, но он необходим, поскольку мы не
можем контролировать первый отправляемый в нашу функцию аргумент. Чтобы разобраться с тем что происходит, попробуйте оценить данный
вызов функции чтобы увидеть возвращаемый результат:
1 Function`$${"x"}$`
2 /*
3 function anonymous($,$
4 ) {
5 x
6 }
7 */
Как мы наблюдаем выше, эта функция вызывается с двумя следующими друг за другом $
, а третий
аргумент применяется для выработки кода. Самый первый аргумент преобразуется из массива в строку, поэтому нам надлежит помещать символы
долларов до и после соответствующего заполнителя. Если бы мы не применяли эти доллары, конструктор Function
возбудил бы исключительную ситуацию из- за недопустимого JavaScript. Очень удобно, что доллар является допустимым идентификатором JavaScript
и разрешён в качестве имени параметра. Мы можем повторно воспользоваться кодом из предыдущей главы, причём мы сначала поместим код
конструктора Function
, затем доллар, потом наш заполнитель, который вырабатывает строку
alert
, а затем следует ещё один доллар. Данный код завершается ``
,
которая вызывает выработанную нами функцию:
1 [[][[![]+[]][+[]][++[+[]][+[]]]+ [!![]+[]][+[]][+[]]]][+[]][[[] [[![]+[]][+[]][++[+[\
2 ]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
3 [++[++[++[+[]][+[]]][+[]]][+[]]]+[[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]\
4 ]]+[]][+[]]
5 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[[][+[]]+[]][+[]][++[+[]\
6 ][+[]]]+[![]+[]][+[]][ ++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][+[]]+[!![]+[
7 ]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][++[++[+[]][+[]]][+[]]]+[[][[![]+[]][+[]][++[+[]
8 ][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]][++[++[++[+[]][+[]]][+[]]][+[]]]+[!![]+[]][+[]]
9 [+[]]+[[][[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]][++[++[++[++[++[+
10 +[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]+[!![]+[]][+[]][++[+[]][+[]]]]
11
12 `$${[ ![]+[]] [+[]] [ ++[+[]][+[]] ]+
13 [ ![]+[]] [+[]] [ ++[++[+[]][+[]]][+[]] ]+
14 [ ![]+[]] [+[]] [ ++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]] ]+
15 [ !![]+[]] [+[]] [ ++[+[]][+[]] ]+
16 [!![]+[]][+[]][+[]]+
17 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
18 [++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]\
19 ]][+[]]][+[]]][+[]]]+
20 ++[+[]][+[]]+
21 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
22 [++[++[++[++[++[++[++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]][\
23 +[]]][+[]]][+[]]][+[]]][+[]]]
24 }$` ``
После большого числа взломов на форуме бездельников, пытавшихся выяснить, что было возможно при помощи не-альфа кода, мы все пришли к выводу,
что минимальное ограничение, которым вы можете обладать для выполнения произвольного JavaScript, составляет шесть символов. Это стало известно
как великая стена символов. Предел обусловлен тем, что без !
вы не можете создавать логические значения,
а без +
вы не можете конвертировать в целые числа и объединять строки, не используя больше символов.
Наиболее вероятный способ сломать эту стену — использовать следующую кодировку +*
и найти способ
выработки логического значения. Это важно, потому что false
содержит
"s"
, а true
содержит
"r"
. Без этих символов вы не сможете построить свойство конструктора и, следовательно, не сможете
выработать требуемую строку, чтобы получить к нему доступ.
Если бы вы собрались попытаться сломать эту стену, вам необходимо было бы вырабатывать больше символов, потому как вы застряли бы с
"NaN"
и "undefined"
. Ну, только с помощью
+[]
можно выработать Infinity
! Давайте посмотрим, как это
делается. Сначала мы собираемся выработать, как и раньше, число один, затем вам нужно сгенерировать неопределённую строку, и нам требуется
из неё "е"
. После этого вы просто объединяете больше единиц в конце, чтобы сформировать строку
"1e1111"
, которая производит Бесконечность Infinity
.
1 [[] [[![]+[]][+[]][++[+[]][+[]]]+[!![]+[]][+[]][+[]]]+[]][+[]]
2 //function at() { [естественный код] } в качестве строки
3 [++[++[++[++[++[++[+[]][+[]]][+[]]][+[]]][+[]]][+[]]][+[]]]//6
Прежде всего вырабатываем 1:
1 ++[+[]][+[]]//1
Затем вырабатываем строку undefined
:
1 [][+[]]+[]//undefined в качестве строки
Из строки undefined
нам требуется получить доступ к из неё
"е"
:
1 [[][+[]]+[]][+[]][++[++[++[+[]][+[]]+[]][+[]]][+[]]]//e
Соединяем всё вместе для формирования 1e1111
:
1 [++[+[]][+[]]+[[][+[]]+[]][+[]][++[++[++[+[]][+[]]+[]][+[]]][+[]]]+[++[+[]][+[]]]+[+\
2 +[+[]][+[]]]+[++[+[]][+[]]]+[++[+[]][+[]]]]
Наконец, нам необходимо преобразовать массив/ строку в число при помощью инфиксного оператора +
и, в конечном счёте, обернуть его в массив и получить к нему доступ как к строке:
1 [[+[++[+[]][+[]]+[[][+[]]+[]][+[]][++[++[++[+[]][+[]]+[]][+[]]][+[]]]+[++[+[]][+[]]]\
2 +[++[+[]][+[]]]+[++[+[]][+[]]]+[++[+[]][+[]]]]]+[]][+[]]
3 //Infinity в качестве строки
Вы можете видеть, насколько это близко к разрушению нашей стены, хотя отсутствие логических значений имеет решающее значение для доступа к конструктору. Мы можем только надеяться, что браузеры представят новые функции или методы, которые позволят нам получить доступ к необходимым символам. На данный момент стена символов выглядит как состоящая из шести.
В этой главе мы рассмотрели, как вырабатывать числа с помощью безбуквенно-цифрового JavaScript, как использовать эти числа для получения строк,
комбинировать эти строки, для получения большего числа символов через доступ к свойствам и преобразования вывода в строку. Затем я показал, как вы
можете собрать это воедино для получения исполнения произвольного кода JavaScript. После этого я продемонстрировал, как вырабатывать не-альфа код
без применения круглых скобок. Наконец, я познакомил вас с великой стеной символов и показал метод создания Infinity
,
с применением только +[]
.