Подтвердить что ты не робот

JSON unparseable cruft: Почему так серьезно?

После прочтения этого вопроса о том, почему google/facebook и т.д. добавляют unparseable cruft, например:

  • while(1);
  • for(;;);
  • &&&START&&& ... &&&END&&&
  • 1 и 3 вместе

к их ответам JSON, я понял мотивацию. Но я до сих пор неясно, почему такие относительно сложные механизмы используются, когда подобные эффекты могут быть достигнуты с помощью таких вещей, как

  • добавление дополнительного ) в начале для рендеринга всей строки с ошибкой синтаксиса
  • упаковка JSON в комментариях

Теперь кажется, что эта добавленная защита бесконечного цикла и (странная) синтаксическая ошибка заключалась бы в том, чтобы обойти старые и разрешающие парсители javascript, но я не могу найти ссылок, указывающих, что это так. Существует еще один вопрос qaru.site/info/121285/..., который продолжается даже в случае обходного пути while(1); (указывающего, что 1 может быть сбито) и отклонить другое обходное решение формы {}&&, но не объясняет, почему или ссылаются на любые источники.

Другие ссылки:

4b9b3361

Ответ 1

Я думаю, что есть несколько подробностей, относящихся к формам неповторимого рывка:

  • Префикс
  • {}&& относится к JSON Parsers (по-видимому и, например, Dojo в более старых версиях), не проверяя строку JSON как действительный синтаксис JSON. Все библиотеки parser JSON, которые я знаю о проверке в настоящее время, но это сообщение в блоге с 2008 года говорят о том, что указанные версии Dojo разрешите JSON.parse json нормально, а eval просто провалится, что даст вам удобную защиту от угона JSON.

  • while(1) можно сделать неэффективным с использованием прототипа Number, присвоив 0 как 1 значение.

  • for(;;) и while(1) оба из них приводят к сбою захваченного сайта, что делает его более сложным, поскольку каждое последующее выполнение любого script эффективно прекращается без ошибок. Это важно, потому что ошибка по определению не помещает конец выполнения script в javascript, а for(;;) гарантирует, что после него не будет script. Это необходимо для предотвращения (гипотетических гипотетических ситуаций) ситуаций, когда злоумышленник успешно перехватывает ошибки script, используя недостатки в window.onerror, перезаписывая eval или проксирование объекта объекта ошибки (например, перезаписывая constructor of Error.prototype).

    UPDATE

    Существует также этот вопрос в security.stackexchange, предлагающий не использовать for(;;) или while(1), поскольку это может означать, что ваш сайт DoS-атакует клиентов CPU или запуск вредоносных сканеров. Я не вижу серьезной проблемы с DoS с современными браузерами, поскольку они работают изолированно и на основе вкладок. Но это, безусловно, проблема со старыми браузерами. Сканеры вредоносных программ являются реальной проблемой и могут сообщать о вашем сайте как атаке.

  • &&&START&&& (и соответствующий тег &&&END&&&) делают парсинг на стороне клиента, получая json проще, чем просто используя ) или комментарии, которые могут быть закрыты непреднамеренно, и могут улучшить читаемость и видимость для программист. Обтекание комментариями является лишь вариантом этого, так как он обеспечивает начало /* и тег */. По-моему, четкая и ясная отметка в начале и в конце помогает заметить смысл крути. Использование комментариев на самом деле не обеспечивает этого.

Ответ 2

О "1 можно сбивать":

если вы выполните следующее (в webkit):

var test = 1;
console.log(test.constructor == window.Number); //true is logged

в теории может быть возможность, что есть способ изменить window.Number или его прототип, чтобы значение 1 не было 1:

window.Number.prototype.toString = function() { return 0 };
window.Number.prototype.valueOf = function() { return 0 }; 

это, к счастью, не работает. но я думаю, что автор пытается сказать.

ИЗМЕНИТЬ обычно я бы также использовал подход, в котором вы помещаете содержимое в комментарий (но тогда должно быть обеспечено, чтобы ваш объект json не содержал что-то вроде этого {"test":"*/"}, потому что тогда это создаст синтаксическую ошибку и даже бросит ошибка может быть проблемой, если она уловима и, вероятно, раскрывает некоторые сведения о линии, где произошла ошибка, или если сам объект Error может быть изменен.