Vladimir Kolesnikov Меня зовут Владимир, я программист-фрилансер (PHP, Node.js, C/C++, Qt). Ещё занимаюсь администрированием серверов и техническим переводом. Крестиком вышивать не умею.
Дек 262011
 

Не так страшен , как его малюют…

WP Hashcash — очередной для борьбы со спамом. Принцип работы основывается на том, что -боты не умеют исполнять JavaScript. Идея в том, что если пользователь открыл сайт из браузера, браузер выполнит некоторый хитрый код JavaScript, и реузльтат работы этого скрипта будет передан назад на сервер в качестве доказательства «человечности» комментатора.

Недостаток этого подхода заключается в том, что используемый JavaScript является довольно-таки простым; как следствие, его можно «понять» даже из -скрипта.

Пример кода JavaScript, генерируемого плагином:

[-]
View Code Javascript
function wphc(){
        var wphc_data = [1850500665,1666021931,1699898495,1648446524,2035770162,1980447546,2018932269,956464429,890644332,956447103,890644332,973224063,890579818,761213796,1850368808,1615687680,1750492719,756628087];

        for (var i=0; i<wphc_data.length; i++){
                wphc_data[i]=wphc_data[i]^220336991;
        }

        var a = new Array(wphc_data.length);
        for (var i=0; i<wphc_data.length; i++) {
                a[i] = String.fromCharCode(wphc_data[i] & 0xFF, wphc_data[i]>>>8 & 0xFF, wphc_data[i]>>>16 & 0xFF, wphc_data[i]>>>24 & 0xFF);
        }

        return eval(a.join(''));
}

Такой JavaScript весьма похож на PHP :-) Как следствие, идея обхода плагина заключается в том, чтобы преобразовать JavaScript в PHP и выполнить получившийся PHP-код.

Итак:

  1. В PHP нет ключевого слова var (строго говоря, оно там есть, только имеет другое назначение).
  2. В PHP несколько другой синтаксис объявления массива
  3. Идентификаторы в PHP начинаются с доллара
  4. Операция сдвига выглядит как >>, а не >>>.
  5. В PHP нет классов Array, String, но никто не мешает их написать :-)

Наша задача состоит в преобразовании кода, приведённого выше, в нечто подобное:

[-]
View Code PHP
function wphc(){
        $wphc_data = array(1850500665,1666021931,1699898495,1648446524,2035770162,1980447546,2018932269,956464429,890644332,956447103,890644332,973224063,890579818,761213796,1850368808,1615687680,1750492719,756628087);

        for ($i=0; $i<count($wphc_data); $i++){
                $wphc_data[$i]=$wphc_data[$i]^220336991;
        }

        $a = array();
        for ($i=0; $i<count($wphc_data); $i++) {
                $a[$i] = fromCharCode($wphc_data[$i] & 0xFF, $wphc_data[$i]>>8 & 0xFF, $wphc_data[$i]>>16 & 0xFF, $wphc_data[$i]>>24 & 0xFF);
        }

        return (join("", $a));
}

Это достигается таким набором правил str_replace():

[-]
View Code PHP
$x = array(
    'wphc_data'  => '$wphc_data',
    'var $'      => '$',
    'var '       => '$',
    '];'         => ');',
    '= ['        => '= array(',
    'new Array($wphc_data.length)' => 'array()',
    '$wphc_data.length'            => 'count($wphc_data)',
    ' i<'        => ' $i<',
    '[i]'        => '[$i]',
    'i++'        => '$i++',
    '>>>'        => '>>',
    'a[$i] ='    => '$a[$i] =',
    'String.'    => '',
    'eval'       => '',
    "a.join('')" => 'join("", $a)',
);

$s = str_replace(
    array_keys($x),
    array_values($x),
    $s
);

При желании правила можно попытаться оптимизировать, но мне было лень — скрипт ломался на коленке за 10 минут.

Реализация функции fromCharCode:

[-]
View Code PHP
function fromCharCode($a, $b, $c, $d)
{
    return chr($a) . chr($b) . chr($c) . chr($d);
}

После замены результат нужно вычислить при помощи eval(). После чего получим такой результат:

[-]
View Code Javascript
function wphc_compute(){return 43448 * 43448 + 75878; } wphc_compute();

Как можно заметить, этот код является одновременно и PHP-кодом, и JavaScript-кодом.

Следующий шаг —

[-]
View Code PHP
$s = str_replace('wphc_compute();', '', $s);
eval($s);
echo wphc_compute(), "\n";

Результатом выполнения будет число 1887804582.

Как видим, для обхода такой простой защиты не нужен даже интерпретатор JavaScript :-)

  11 Ответов в “Обход плагина WP Hashcash”

Comments (11)
  1. V8 и JavascriptCore — opensourse проекты так же есть интерпретаторы JS на PHP. JS код можно сурово обфусцировать так что человек его попросту не разберет и не перепишет. Но для JS «интерпретатора» (движка) это даже не проблема.

  2. Я раньше какие только плагины WordPress для борьбы со спамом не ставил, толку было не много. А потом узнал про подмену полей — и проблема разрешилась сама собой. Правда этот метод работал изначально наверняка, и пришлось дополнить контактную форму простейшей капчей на сложение двух чисел. И спам комменты практически исчезли. Из чего я сделал вывод, что 99,9% спаммеров «гадят» при помощи программ. В ручную редкие «красавцы» это делают. Но на одном из проектов недавно заметил новый тренд (как это модно говорить): спам-комменты через трекбеки. Правда пока эта напасть не приняла массовый характер, и я даже не стал заморачиваться и ставить специальный плагин.

    • Капча отлично помогает против ботов, но «редких красавцев», поверьте, тоже предостаточно ;) Так что приходится иногда и вручную удалять спам.

      • >Капча отлично помогает против ботов

        И против юзеров :)

        Наличие капчи говорит о лени или отсутствии мозгов у её поставившего.

    • Трекбэки пользовались популярностью давно, пока это была новинка. Сейчас чаще их отключают, что бы не создавать лишнюю нагрузку на блог.

    • Точно, подмена полей — отличный метод. У меня до его внедрения несколько десятков спамных комментов в сутки, после — 1-2 в неделю.

  3. Большое спасибо автору за полезную статью!
    Могу добавить только то, что на самом деле тут показан самый простой пример функции вычисления (function wphc_compute(){return 43448 * 43448 + 75878; } wphc_compute();), на самом деле их 4 вида, из которых только 2 являются одновременно кодом и php, и js, для двух других нужно сделать дополнительное преобразование из js в php. Все 4 вида функций можно посмотреть в исходнике плагина.

  4. Интересное наблюдение и полезная информация! Защита-защитой, а премодерацию и ручное одобрение комментов никто не отменял, так что никакие скрипты не заменят человеку его мозга ))

  5. 2 года пользуюсь этим методом, доволен как слон, все автоботы отсеиваются.
    А делать такие вещи мало кто будет, т.к. такой метод защиты мало распространен.

  6. Отличная статья! Попробую данный плагин! Подправьте пожалуйста текст : » и реузльтат работы этого «!

  7. Ну хоть убейте — не доверяю плагинам от спама. Только ручной прогон комментов. Правда мой проект еще не настолько раскручен.

Leave a comment below if you dare

If by accident you see this form, please do not use it; use the form below this instead.

 Оставить комментарий

(обязательно)

(обязательно)

Вы можете использовать эти HTML теги и атрибуты: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

Оставляя комментарий, вы выражаете своё согласие с Правилами комментирования.