Я проводил некоторые эксперименты, как Googlebot разбирает и рендерит JavaScript, и наткнулся на несколько интересных вещей. Первое — то, что функция Math.random() в Googlebot выдаёт полностью детерминированные серии чисел. Я написал маленький скрипт, который использует этот баг для точной идентификации гуглобота:


Источник

При первом вызове Math.random() из гуглобота результат всегда будет 0,14881141134537756, второй вызов всегда вернёт 0,19426893815398216. Скрипт по ссылке выше просто использует эту информацию для идентификации бота Google, хотя немножко обфусцирует свои действия, чтобы они не выглядели слишком произвольными.

Краулинг в масштабе Google


Представьте объём работы, которую необходимо выполнить Google, чтобы обойти весь веб, да при этом ещё выполнить все скрипты. Здесь не обойтись без обильных оптимизаций, и я полагаю, что детерминированные случайные числа реализованы по следующим причинам::

  1. Скорость.
  2. Лучшая безопасность.
  3. Предсказуемость — гуглобот может быть уверен, что страница отобразится одинаково при каждом визите.

Ускорение времени…


Googlebot также запускает JavaScript с ускоренными часами, что вполне логично. Зачем реально ждать 5 секунд, если ты бот? Так что Google на самом деле запускает таймер в гораздо более быстром темпе. Если создать простой скрипт с тикером и запустить функцию Fetch & Render в консоли Google Search Console, то скрипт выполнится практически мгновенно, но результат будет выглядеть так:



Вторая дата — это дата из будущего! Марти Макфлай мог бы гордиться.

Когда это началось?


Мне стало интересно, обновляется ли генератор «случайных» чисел у Google, но поиск числа 0,14881141134537756 вернул более 18 000 результатов, так что константа кажется довольно стабильной. Обнаружив это, я погуглил ещё немного и нашёл старый комментарий на Hacker News от пользователя KMag:

В какой-то момент кто-то из SEO выяснил, что random() всегда возвращает 0,5. Не уверен, что кто-нибудь понял, что JavaScript всегда при этом видел какую-то дату из лета 2006 года, но предполагаю, что ситуация изменилась.

Похоже на то, что ситуация сохраняется в течение долгого времени, но раньше random() всегда возвращал 0,5, а сейчас выдаёт детерминированные серии чисел. Дата действительно вначале установлена точно, но затем может идти в будущее. KMag дальше сказал:

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

Кажется, этого не произошло. Но я не уверен, что таким образом можно сделать многое из того, что вы не можете сделать с помощью юзер-агента и IP. Но может быть такой способ позволит сделать нечто, правдоподобно отрицая свою вину!

Комментарии (18)


  1. altervision
    13.02.2018 09:54

    Странно, что до сих пор никто из «шибко активных» не предъявил Гуглу претензии за это случайное число, ведь 1488 в его начале выглядит очень подозрительно.


    1. ShamanR
      13.02.2018 10:07
      +3

      Пока вы на этом не сакцентировали внимание даже не заметил ничего необычного в числе.


      1. begemot_sun
        13.02.2018 12:14

        А для тех кто не в теме, можно расшифровать?


        1. Nord001
          13.02.2018 12:35

          Гугл думает что про это:
          ru.wikipedia.org/wiki/14/88


          1. TimsTims
            13.02.2018 15:25

            14/88 — кодовый лозунг (подчас также употребляющийся в качестве приветствия или подписи) у белых националистов.

            Кому лень открывать Википедию


      1. gearbox
        13.02.2018 13:37

        ок, теперь я тоже в курсе. Спасибо двум джентельменам в треде.


    1. hdfan2
      13.02.2018 15:01

      image


      1. david_mz
        13.02.2018 20:22

        При первом вызове Math.random() из гуглобота результат всегда будет 0, РОСКОМНАДЗОР1141134537756


    1. asmrnv777
      13.02.2018 17:04
      +3

      Рандом хардкодить мы не бросим!


  1. vilgeforce
    13.02.2018 10:18

    Осталось найти тот seed, который будет выдавать ту же последовательность и наконец объяснить происхождение «бага», который вовсе и не баг :-)


  1. AelDeyr
    13.02.2018 12:24

    Matt Kulukundis упоминал что они используют детерминированный рандом в продакшене и «честный» при отладке в своей SwissTable (замена google::dense_hash_map).
    По-видимому, это связано со скоростью (функция случайного числа выполняется в L1 кэше) и удобством отлова багов. Можно предположить, что такой подход работает для многих сервисов компании.
    youtu.be/ncHmEUmJZf4?t=2645


  1. sebres
    13.02.2018 14:59

    Я написал маленький скрипт, который использует этот баг для точной идентификации гуглобота

    На кой он это спрашивается делал, если гуглобот никогда и не скрывался, и по navigator.userAgent и кучей других разных способов однозначно определяется как бот.
    Точней уже некуда.


    И да, это не баг, это — фича...


    1. EvilFox
      13.02.2018 18:47

      Наверное потому что некоторые другие боты (да и не только боты) любят притворяться гуглоботом.


    1. reket
      14.02.2018 15:45

      Возможно ошибаюсь, но гугл бот может прикидываться обычным пользователем чтоб проверить одинаковый ли контент выдается пользователю и боту. Например, боту без навязчивой рекламмы.


      1. sebres
        14.02.2018 15:59

        Да запросто, но думаю в этом случае оно сделает это c другим юзер-агентом, с другого-IP,… и наверное другим движком (в котором ранд работает случайным образом).


        Эта фича у гугла, чтобы в том числе хотя бы из js-движка не переиндексировать страницы, зависящие от случайных составляющих (ака "Случайная страница").
        Хотя правильный сервер может или но-робот проставить или оборачивать "случайную" динамику конструктами типа if (!bot) {...};.


  1. miga
    13.02.2018 16:21

    Один четыре восемь восемь — сайты парсить мы не бросим!


  1. AVI-crak
    13.02.2018 20:17

    Индетерминированный ключ…
    Жители планеты Мелдж ищут этот ключ уже сотни лет.


  1. VladKamyshanov
    13.02.2018 20:48
    +1

    Напомнило
    image