Защита от спама в phpBB 3 без капчи

    Думаю, многие владельцы форумов на phpBB 3 уже знают, что стандартная капча, идущая в комплекте с форумом, особо не спасает.

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

    Защита на основе анализа действий пользователя


    В общем первым делом добавил к форуму скриптец, который писал все запросы как GET, так и POST в лог-файл, чтобы можно было их проанализировать.

    Сразу уточню, что форум русскоязычный (русский включен по умолчанию), но есть и английский.

    И так типичный запрос на регистрацию от бота выглядит так (выводятся метод, url, referrer, и потом инфа из POST-запроса, email я убрал):

    GET	/forum/index.php	/forum/index.php
    
    GET	/forum/ucp.php?mode=register	/forum/ucp.php?mode=register
    
    POST	/forum/ucp.php?mode=register	/forum/ucp.php?mode=register	
      'agreed' => 'Я согласен с этими условиями',
      'change_lang' => '',
      'creation_time' => '1320421149',
      'form_token' => '16d4c035a7de1680c4e19fe0addd242d7edf1822',
    
    POST	/forum/ucp.php?mode=register	/forum/ucp.php?mode=register
      'username' => 'Shemtrearve',
      'email' => 'deassepleadia@....com',
      'email_confirm' => 'deassepleadia@....com',
      'new_password' => 'q49uh3oYcN',
      'password_confirm' => 'q49uh3oYcN',
      'lang' => 'en',
      'tz' => '-12',
      'agreed' => 'true',
      'change_lang' => '0',
      'submit' => 'Отправить',
      'creation_time' => '1320421154',
      'form_token' => '97471b3af621c1a60f825e50d2b61b3346b48025',
    
    GET	/forum/ucp.php?mode=login	/forum/ucp.php?mode=login


    Также я убрал sid из URL, боты их зачастую добавляют, хотя они отключены у меня в форуме. Все запросы сделаны с интервалом 4-5 секунд.

    Теперь ищем странности в запросе:
    1. Естественно сразу видно, что бот заходит на страницу с этой же страницы (referrer совпадает со страницей).
    2. Во втором POST запросе, обращаем внимание на то, что бот выбрал английский язык, при том в предыдущем запросе он язык не менял, и типа спокойно прочитал правила форума на русском, а потом выбрал английский.
    3. Далее мы выдим, что выбрана временная зона -12, хотя эта зона чисто условна и там никто не живет. А всё дело в том, что phpBB эту дату высталяет JavaScript-ом, а у ботов она остается по умолчанию.
    4. Далее change_lang = 0 при том, что в phpBB не может быть такого значения, там должен быть код языка.
    5. Ну и напоследок submit на русском языке, при выбранном английском языке. Есть еще тупые боты которые не понимают кириллицы, и в это поле вставляются вопросительные знаки.

    В общем, вывод достаточно простой, но основе пунктов 2-5, делаем небольшой скрипт, который будет препятствовать регистрации ботов.

    Код выглядит примерно так
    if (isset($_POST['password_confirm']) && isset($_POST['tz'])){ // Пришел запрос на регистрацию 
        if(
            $_POST['tz'] == -12 || // Нереальная временная зона
            ($_POST['lang'] == 'en' && $_POST['change_lang'] != 'en') || // Изменен основной язык, но change_lang при это не изменен
            ($_POST['lang'] == 'en' && $_POST['submit'] == 'Отправить') // Язык вроде английский, а кнопка почему-то русская
        ){
            header("HTTP/1.1 404 Not Found");
            exit;
        }
    }


    Проще всего добавить этот код в конце config.php, чтобы не долго ковыряться, не снести его при обновлении форума, да и сразу посылать ботов лесом. Можно упростить условие по желанию, просто для наглядности расписал. Благодаря такому простому коду я отсеял практически всех спаммеров, при том, что даже выключил капчу.

    Понятное дело, что со временем боты научатся это обходить, но тогда и мы, что-нибудь новое придумаем.

    UPD. Подправил код примера, а то там было пару опечаток.
    Share post

    Comments 73

      +10
      Я добился такого же эффекта просто переименовав поле confirm_code во что-о другое, а confirm_code, для совместимости, остался как hidden поле.
      Ну и ессно в самом ucp.php тоже нужно поменять имя переменной, на соответствующее.
      Это, конечно, не спасет если боты целенаправленно пришли на сайт, там и проверить можно, что нужно передавать, а от 99,99% гуляющих по сети, такая схема вполне прокатывает.
        +3
        Это в принципе первое, что приходит в голову, но не хотелось ковыряться в скриптах форума, и не забывать их править при обновлениях.
        В последнее время перешел на поведенческие фильтр, их сложнее ботам вычислить, чем простое переименование полей.
          0
          Согласен, но в моем случае обновление на лету, все равно не вариант, т.к. форум значительно модифицирован и слишком далек от базовой версии.
        –13
        Смена дислокации форума тоже помогает
          +6
          Его закрытие и уход владельца в монастырь — тоже. :) Самый верный способ избавления от спама :))
            0
            зачем так уж?

            есть другой экстремальный, но 100% надежный способ — премодерация.
              0
              Это просто ваш форум еще активно не спамили, задолбаетесь разгребать.
              К примеру на форуме одного из клиентов, даже просмотр закрыт для гостей, тем не менее когда там оказалось на пару сотен нормальных сообщений 14 тысяч спамерских — премодерация им перестала нравиться, и чистил я их напрямую в базе, так как, так значительно проще, чем форумными инструментами.
                0
                Можно программно спам отличать от нормальных сообщений?
                На ум приходит только шерстить сообщения с веб-ссылками…
                  0
                  Ссылки, бб-коды и html-теги, английский язык на русскоязычном форуме, плюс анкеты юзеров (боты любят подписи сразу заполнять, и сайт прописывать). В самом phpBB какие-то очень массовые действия сложнее делать (ну по крайней мере для меня). А так слил дамп форума на локалку, и уже HeidiSQL в руки + немного php — поудалял всё лишнее, а потом в форуме сделал пересчет статистики.
                    0
                    На самом деле, учитывая, что спам — это не вредоносы сами по себе (не эксплойты), а реклама либо ссылки на вредоносы, то не обязательно искоренять спам сам по себе, достаточно запретить ссылки, и смысл спама пропадает

                    Далее, можно даже обьединять похожие (используя расстояние левенштейна или другие алгоритмы) сообщения в один, считая правкой.
                    Либо составляя самообучающуюся систему…

                    Премодерация тоже годится, если не планируется много сообщений
                      0
                      А Вы думаете, кто-то планирует много спама? В упоминавшемся выше форуме, всего-то пару десятков юзеров было, тем более сайт не настолько раскручен, чтобы ожидать наплыва спама (те же PR и ТИЦ у него были нулевые, месяц-два как открылся). Но по сути автоматических ботов это мало волнует, они себе лазят по нету в поисках форумов и спамят их.
                      Также некоторые боты не оставляют сообщений, а просто регятся и ссылки вставляют в профиль пользователя.
                      Премодерация, естественно, не даст показать спам, но она добавляет кучу головной боли админам или модераторам, нужно же этот мусор чистить, причем чистить придется каждый день и много.
          +5
          мне например удалось отбиться от ботов путем добавления еще одного обязательного поля в профиль пользователя.
            0
            Меня всегда убивало, то что все пытаются делать капчи и прочее говно, когда нужно убрать возможность боту находить поля.

            Любой форум или регистрация, да все что угодно лечится так:
              +11
              а ну понятно… мы так и думали))
                +3
                рано нажал на энтр )
                +5
                В форме
                form name="megaForm"
                input name="rand()"
                input name="rand()" type="hidden" value="это поле для проверки" //Проверочное поле
                /form

                В скрипте регистрации просто работать с массивом формы, где все поля обезличены(имена полей рандомные, ботам ухватиться негде), а проверочное поле мы всегда видим 12 в массиве и просто проверяем его наличие с заданым текстом.

                Как итог это отсекло ботов вообще, они не видят формы, а написание скриптов не проходит, т.к структура формы изменена и я не жду данных имени к примеру в первом элементе формы.

                Вот как-то так. Мой способ не панацея, но про ботов я не слышал вообще, равно как и не мучаю пользователей капчей. Нельзя насиловать пользователей капчей.
                  +5
                  каптча введена неправильно, спасибо, Вы не бот
                    +4
                    Рандомные имена полей, конечно, хороший вариант от неспециализированных ботов.
                    Одно плохо: автокомплит перестаёт работать.
                      +4
                      От специализированных ботов ничего не спасет, если пишут бота специально под рессурс, анализируют сперва обычные запросы и тупо их копируют один в один.
                        +2
                        Ну так можно все к пессимизму свести — мол, и каптчи ломают индусочасами
                          +1
                          Я к тому что не стоит обращать внимание на спец. по, имеется ввиду защита от стандартных «ломалох» которые типа универсальны.
                            +1
                            > «ломалох»
                            удачная описка = )
                            –1
                            Блин, >.< я не так прочитал Ваш коментарий, извеняюсь =)
                        0
                        а мой «бот» ваш метод пробьет?:
                        примеру, можно распознать тип форума и заполнять поля не по их именам, а по их расположению в верстке шаблона.
                          +1
                          Интересно! В первый раз слышу про такой способ.
                          1. А у Вас нет статьи на эту тему, где можно почитать? А $_POST Вы после представляете в виде массива $_POST[0], $_POST[1],… (не ассоциативного, но скалаярного) ???
                          2. Как в таком случае делать проверку правильной заполненности полей используя JavaScript? Ведь нам имя поля неизвестно. Обрабатывать входные данный сервером, не клиентом?
                            0
                            Можете мне тоже в ПМ скинуть инфу про этот способ, достаточно интересный подход. А то уже не знаю как в блоге отбиваться от ботов, на последок снёс встроенные комментарии и прикрутил facebook комменты, пока работает.
                          0
                          интриига…
                          –3
                          не понимают кириллицы
                          очепятка, букву потеряли
                            +3
                            Написали бы в личные сообщения.
                            +2
                            Если не ошибаюсь в phpBB3 есть возможность сделать текстовой подтверждение, где указать свой уникальный вопрос или вопросы, а также набор ответов на них. Достаточно придумать что-то свое, что относится к теме форума и боты заглядывают все реже. =)
                              0
                              Вроде бы это для ботов даже легче?
                                +1
                                Если кто-то составит конкретно для твоего форума набор ответов на вопросы. На маленьком форуме текстовое подтверждение неплохо решает проблемы с ботами.
                                  0
                                  Составить автору и проблема — надо же чтобы посетители знали ответ… В общем, ориентация на конкретную аудиторию получается.
                                    0
                                    Ну например сходу «Как называется наша планета?». И набор ответов «Земля», «Earth» и какие-то дополнительные ответы для особо одаренных. Если не смогут на такой вопрос ответить, нужны ли такие посетители? =)
                                      0
                                      А, ну такой антиспам проверен асечкой…
                                        0
                                        Это был пример легкого вопроса. На своих форумах я решал проблему вопросами из серии, «какого цвета неба» или «чему посвящен форум» или «сколько будет 22 прибавить 35». Главное составить правильный набор ответов.
                                          +1
                                          Мне нравится набор с загадками, типа «С яйцами и луком, но не пирожок» — но это надо и смекалку иметь, и некоторые знания (уже, наверное, забытые) и для иностранцев не подходит…
                                            0
                                            Можно составлять вопросы для каждого языка. Если сделать вопросы хоть немножко нестандартными, это сразу отрежет всех неспециализированных ботов.
                                              0
                                              Всё, я бы не зарегистрировался к своему стыду :)
                                                0
                                                Робин Гуд, в Вашу копилку знаний.
                                                  0
                                                  Позор на мои седины! :) Спасибо!
                                    0
                                    Легче, но точить бота под конкретный форум нецелесообразно.
                                      –1
                                      потому у хабра нет форума — нецелесообразно)
                                  0
                                  >>>Ну и напоследок submit на русском языке, при выбранном русском языке.

                                  Вроде бот выбирал английский язык?
                                    0
                                    Да, пасиб, поправил.
                                    +1
                                    в моем случае в phpbb3, когда ломали капчи, я поменял на текстовую с супер тупыми вопросами — настала удивительная тишина от сверх умных ботов.
                                      +4
                                      В части «isset($_POST['password_confirm'] &&» ошибка — функция не закрыта.
                                        –7
                                        КО: код писался для статьи как пример, и не тестировался.

                                        Что Вы хотели сказать этим комментарием? Подколоть автора?
                                          +2
                                          Спасибо, поправил.
                                          +3
                                          года 3 назад делал для своего форума на punBB, ботов остановило на полтора года. Правда, я не подавал вида, что рега не прошла. Проверка была ровно перед INSERT в базу. Так что, и письмо с регистрацией, и все данные и отображение уходили как должны. Это, вероятно, немного затрудняло перенастройку бота.
                                          0
                                          HINT для SMF:
                                          Большинство ботов в обязательном порядке указывают Skype login хотя он и необязателен. Но указывают его в виде 4 символьного набора [0-9a-zA-Z]{4} (зарегистрировать 4 символьный логин в скайпе нельзя).
                                            +8
                                            Лично я решал проблему еще топорнее: поле [input type=«hidden» name=«js_test»], заполняется на страницу с помощью JS. Когда возник вопрос о людях с отключенным JS, мой руководитель сказал а-а-атличную фразу: «Я готов пожертвовать этими пятью долбоебами»
                                              0
                                              в моем случае это остановило только на пару месяцев. Дальше снова посыпались.
                                                0
                                                Пока хватает статичного $_POST['js_test'] == 'passed', но если опять нахлынут паразиты, можно сделать какой-то простенький CSRFToken, базирующийся, ну скажем, на sid
                                              +1
                                              Первый человек в космосе:
                                              1) Симпсон
                                              2) Фарнсворт
                                              3) Гагарин

                                              И все в таком же духе. Для phpbb2 есть плагин, кажется, Antibot question. Наверное и для 3-его тоже должен быть. Помогает феноменально.
                                                0
                                                Помогает конечно, но это лишние вопросы юзерам, а в предлагаемом способе, вообще ничего лишнего вводить не нужно.
                                                +2
                                                Я еще вместо 404 возвращаю левую страницу с подтверждением регистрации. Это ставит в тупик многих ботов.
                                                  0
                                                  Судя по логам, боты вообще редко реагируют на страницу которая выдается после регистрации. Они делают POST-запрос на регистрацию, а потом сразу же идут логиниться. Т.е. даже 404 ошибка после регистрации их не смущает.
                                                  0
                                                  1) 'creation_time' => '1320421149'
                                                  2) 'creation_time' => '1320421154'
                                                  разница 5мс?
                                                  разве можно за такое время заполнить все поля? или я что то неправильно понял?
                                                    +1
                                                    Это секунды
                                                      0
                                                      5 секунд все равно мало, но уже по крайней мере реально, спасибо за разъяснение :)
                                                    –1
                                                    А я отключил стандартную регистрацию и прикрутил Логинзу
                                                      0
                                                      «Во втором POST запросе, обращаем внимание на то, что бот выбрал английский язык, при том в предыдущем запросе он язык не менял, и типа спокойно прочитал правила форума на русском, а потом выбрал английский.»

                                                      Меня ни чуть не смутят правила/лицензионные соглашения etc. даже на вирите, и не помешает попробовать зарегистрироваться.

                                                      Но ваш подход шикарен. Бороться надо, как раз, не усложняя жизнь пользователям капчами, премодерациями и прочим анальным джихадом.
                                                        0
                                                        Дело в том, что в phpBB 3 на странице с правилами есть переключение языка, более того, если сменить язык на второй странице (где вводится логин, пароль и т.п.), то phpBB сразу же возвращает на страницу с теми же правилами, но уже на английском. Плюс ставится пометка, что язык был изменен с дефолтного.

                                                        Т.е. если приходит, что язык английский, то кнопка никак не может быть на русском.
                                                        0
                                                        А зачем отдавать 404? У бота в логах тогда будет видно что появилась защита, которую начнут изучать и обходить. Может лучше эмулировать что сообщение добавлено?
                                                          0
                                                          Ну по желанию можно отдавать что угодно, это уже по желанию. В статье основная задача — показать, как распознать бота.
                                                          0
                                                          Ага, только поменяйте в примере $_POST['change_lang'] на request_var('change_lang', '') и так далее.
                                                          А то неакуратненько.
                                                            0
                                                            Зачем эти костыли? Тем более, что request_var не работают в config.php, специально же делается отсев на ранней стадии, чтобы не запускать кучу кода.
                                                            0
                                                            У меня на форуме была текстовая каптча с несколькими вопросами вроде «Сколько будет дважды два?». Ни один спамбот её сломать не смог, а пользователям это было куда проще чем разглядывать кривые циферки и буковки.
                                                              0
                                                              В данном случае пользователю вообще ни капчи вводить, ни на дополнительные вопросы отвечать не нужно.
                                                              0
                                                              Где разместить приведенный код, чтобы он вызывался при регистрации пользователя phpbb?
                                                                0
                                                                Первое правило защиты от спама на phpbb3: никому не рассказывать, как ты это делаешь.
                                                                Спамеры же бдят! Так ведь? :)

                                                                Only users with full accounts can post comments. Log in, please.