Пользователь
0,0
рейтинг
10 октября 2013 в 07:55

Разработка → Картинки с внешних ресурсов — добро или зло? из песочницы

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

Большой брат следит за тобой

Вы хотите узнать больше информации о самых действенных методах? Вам интересно, как с помощью маленькой картинки определить разрешение экрана, локальное время и сменить парочку паролей? Добро пожаловать под кат!
Содержание:


Что мы будем использовать

  • Пассивные методы — прозрачная для пользователя запись поступающей информации
  • Активные методы — отдача уникального контента на каждый запрос

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

Статистика

Пассивные методы


Нам нужно получить всю информацию, которая позволяет отделить каждого пользователя от основной массы, и затем начинать следить за ними. На наиболее-низком уровне это IP протокол, затем TCP, возможно SSL/TLS, и уже потом HTTP.

Традиционно в этой сфере используется анализ трафика.
Mozilla Firefox (EN) Google Chrome (RU)
GET /image.png HTTP/1.1
Host: habrahabr.ru
User-Agent: Mozilla/5.0
Accept: image/png,image/*;q=0.8,*/*;q=0.5
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate
Referer: http://habrahabr.ru/
Connection: keep-alive


Перенос: \r\n

GET /image.png HTTP/1.1
Host: habrahabr.ru
Connection: keep-alive
User-Agent: Mozilla/5.0
Accept: */*
Referer: http://habrahabr.ru/
Accept-Encoding: gzip,deflate,sdch
Accept-Language: ru-RU,ru;q=0.8,en-US;q=0.6,en;q=0.4
Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.3

Перенос: \r\n

Это два запроса, с одной и той-же страницы, на одну и ту-же картинку, однако с разных браузеров. Как видим, различается не только содержимое заголовков, но и их порядок. У разных версий браузеров так-же будут возникать различия, тем сам мы можем предположить о локализации и умышленном изменении User-Agent.

В случае с большим файлом читая временные метки можно определить скорость передачи информации. По скорости и IP-адресу можно будет узнать провайдера и тариф что поможет применить социальную инженерию к человеку.

Боты
Большинство ботов эмулирующих просмотр сайта и не основанных на браузерных движках не приводят нижнему регистру заголовок host — быстро обнаружить злодеев без помощи администрации поможет такой тег:

<img src="http://HABRAhabr.ru/image.png" alt="На главную страницу">

Активные методы


Теперь мы уже переходим к самому интересному, почему бы нам не выжать все максимально-возможное из этой техники?

Cookie

Должно быть вы слышали о этой технологии передачи данных между сервером и клиентом, её стал поддерживать еще IE 2-й версии. Недавно подошел Mozilla Firefox 22, в котором по умолчанию была заблокированна установка куков со сторонних доменов, но а всех кто использует другие браузеры ожидает большой сюрприз. Векторы использования:

  • Сопоставление выходов клиента с разных IP
  • Отслеживание разных сессий браузера
  • Определение браузера исходя из лимитов на данные
  • Определение локального времени с точностью до секунды

С первым пунктом все ясно — мы устанавливаем куку с большим сроком действия, записываем в неё уникальный идентификатор, и в дальнейшем все считываем.

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

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

Для осуществления четвертого пункта требуются некоторые усилия:

Set-Cookie: name=VALUE[; expires=DATE][; path=PATH][; domain=DOMAIN_NAME][; secure][; HttpOnly];

Cookie: name=VALUE;

Сервер устанавливает куку с помощью Set-Cookie, устанавливает нужные параметры и передает все в браузер. Браузер сохраняет параметры и обратно придут только данные — элегантно и просто.

Самое интересное здесь в поле даты, она задается в формате Wdy, DD Mon YYYY HH:MM:SS GMT, то есть едина вне зависимости от местоположения, однако если системное время не синхронизировано или проставлен другой часовой пояс возникнут различия.

Примечание: это все будет работать только тогда, когда сервер не передал заголовок Date с своим временем — браузеру надо-же как-то выкручиваться.



Зададим контрольную и еще 12 разных версий куки с разницей в 2 часа и посмотрим следующий ответ пользователя осуществляя перенаправления через Location. Потом сужая или расширяя(Если время изменено больше чем на день) при надобности диапазон доходим до секундных отметок, после чего можно определить зависимость между серверным и клиентским временем и опознать человека в следующий раз.

Cache


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

Etag
При отдаче картинки отдается заголовок Etag с уникальной хэш-строкой:
Etag: 1aa69b6c6273a8

Последующий запрос к серверу будет выглядеть так:
If-None-Match: 1aa69b6c6273a8

Теперь сервер вправе отдать статус 304 Not Modified без передачи самой картинки — браузер возьмет её из кэша.

Last-Modified
Более-старый аналог Etag, так-же может использоваться для отслеживания. Указывает дату последнего изменения документа.
Server => Last-Modified: Fri, 02 Jan 1970 10:17:36 GMT

Client => If-Modified-Since: Fri, 02 Jan 1970 10:17:36 GMT
Server => HTTP/1.1 304 Not Modified

Expires
Указывает на дату возможного истечения актуальности документа. Более-долгий аналог определения времени.

Expires: Fri, 02 Jan 1970 10:17:36 GMT
Cache-Control: must-revalidate

Подробно о заголовке расписано здесь.

Заголовок Link


HTTP-Заголовок Link эквивалентен тегу <link>. Можно указать ссылку на rss-ленту, таблицу стилей и прочее прямо в заголовках — это шанс, ведь HTML включить в картинку не получится(За исключением старых версий Internet Explorer).

Link: <./style.css>; rel=stylesheet

Используя современные возможности CSS 3медиа-запросы — можно подгружать данные через условия, например по разрешению экрана:
@media all and (device-width: 1024px) { 
	html {
		background: url("./w1024.jpg");
	}
}
@media all and (device-height: 768px) { 
	body {
		background: url("./h768.jpg");
	}
}

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

Бесконечный gif


Идея в том, что в формате анимированного GIF'а не указывается количество фреймов, так что после отображения картинки браузер ждёт новых фреймов с сервера до тех пор, пока не получит сигнальные биты о конце файла. Другими словами, сервер может пушить в браузер сообщения по открытому каналу в GIF.

(с) alizar

См. habrahabr.ru/post/151538 и habrahabr.ru/post/180877

Кроме того бесконечный gif можно применять для отслеживания времени проведения пользователя на странице — сокет будет закрыт в момент закрытия вкладки или повиснет после изменения настроек сети, переключения прокси-серверов, VPN-серверов…

Заголовок Refresh


Этот заголовок(в отличии от Link) не задан стандартами, однако, поддерживается почти везде.

Refresh: 15; url=http://habrahabr.ru/images/bg-multilogo.png

Он позволяет осуществлять перенаправление через определенный промежуток времени — если юзер загрузит страницу, а затем не закрывая вкладок отключит VPN и прокси — его IP будет у нас в кармане.

Basic-authentication


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

Материалы: habrahabr.ru/post/140054

CSRF атаки


CSRF — вид атак на посетителей веб-сайтов, использующий недостатки протокола HTTP. Если жертва заходит на сайт, созданный злоумышленником, от её лица тайно отправляется запрос на другой сервер (например, на сервер платёжной системы), осуществляющий некую вредоносную операцию (например, перевод денег на счёт злоумышленника). Для осуществления данной атаки, жертва должна быть авторизована на том сервере, на который отправляется запрос, и этот запрос не должен требовать какого-либо подтверждения со стороны пользователя, который не может быть проигнорирован или подделан атакующим скриптом.

https://ru.wikipedia.org/wiki/Подделка_межсайтовых_запросов


Если URL жестко фильтруется еще не значит, что провести подобную атаку невозможно. Через тот-же заголовок Location можно передать вредоносную ссылку на изменение паролей, отправку сообщений или на что то еще:

Location: http://www.ru/panel/password?newpass=qwerty&newpass2=qwerty&submit=ok


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

Низкоуровневые, ошибочные и прочие методы



Определение серого IP (Внутренней сети)


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

Способ быстро был опровергнут — путь к ресурсу и от ресурса может не совпадать(материал) и метод будет давать больше сбоев, чем правильных ответов.

Однако применение все-же есть, по умолчанию TTL в Linux равен 64, в Windows — 128. Такие большие различия помогут определить OS удаленного хоста в некоторых случаях.

Определение использования фаервола (Для Win)


Метод очень простой, однако подходит только для Win систем где широко используются продукты наподобие Kaspersky Internet Security. Размещая код вируса в картинке отследить её блокировку не сложно — ресурс может быть заблокирован надолго, в кэш картинка никогда не ляжет.

Сканирование хоста


Это может потребоваться, но здесь надо быть максимально-осторожным — при обнаружении подобной активности ничего хорошего не светит.

Заключение


Если у вас есть свой сайт, подумайте, а вам надо столько проблем из-за одной фичи?

UPD1:
baadf00d в комментариях напомнил о утечках DNS(позволяют определить используемый DNS-сервер, иногда бывает провайдерским).

Публичные сервера от Google:
8.8.8.8 8.8.4.4
Настройка Firefox(about:config):
network.proxy.socks_remote_dns = 1
@Veratam
карма
9,0
рейтинг 0,0
Реклама помогает поддерживать и развивать наши сервисы

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

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

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

  • +42
    Определение использования брандмаузера (Для Win)

    На мой взгляд брандмаузер должен выглядеть как то так: image
    Извините за оффтоп.
    • 0
      А зачем пистолету такой приклад?
      • +2
        Во-первых, это кобура.
        Во-вторых, лёгким движением пистолет превращается в карабин (которым, по существу, и является).
        В-третьих, маузер C96 — тяжёлый и мощный, прицельно стрелять с рук проблематично.
      • 0
        Это же маузер. С его убойностью без такого приклада стрелять чистый мазохизм и показуха.
        • +1
          Отдача у C96 как раз небольшая. Патрон как у ТТ, вес больше, следовательно отдача — меньше.
  • +14
    Даже, если не затрагивать вопросов безопасности, картинки с внешних ресурсов — зло хотя бы потому, что:
    1. Они имеют обыкновение удаляться с внешних ресурсов и на вашем ресурсе будут дыры в этом случае.
    2. Через некоторое время картинка няшного котика может быть подменена внешним ресурсом на картинку с рекламой, например, наркоты. В этой ситуации вы, во-первых, понесете репутационные потери, а, во-вторых, можете нарваться на блокировку.
    • +5
      Именно. Например большинство старых статей на хабре с мертвыми картинками. И на известном трекере в любой раздече старше полугода нет скриншотов.
  • 0
    а затем не закрывая вкладок отключит VPN и прокси его IP будет у нас в кармане.

    Это при условии, что после отключения VPN у него произойдёт замена шлюза по-умолчанию на шлюз его провайдера. Этим грешат некоторые VPN-сервисы, предоставляя соответствующие скрипты восстановления шлюза по-умолчанию при исчезновении tun.
    Если же чел грамотный, то при исчезновении tun шлюз по-умолчанию у него так и останется VPN-овский. Т.е. никакого «его IP будет у нас в кармане» не произойдёт — у него тупо не будет инета и он не сможет подгрузить ваш ресурс. Так что «не так страшен чёрт», как тут написано
    • 0
      Верно, но ключевое слово здесь отключит, а не отвалится. Например скачать длинный ролик с ютуба.

      Если говорить про CSRF, от части атак проводимых способом картинок можно защитится создавая несколько профилей в браузере — в этом случае не в соц. сетях, ни на том-же ютубе авторизации не будет.
      • 0
        Не всегда можно отделять эти понятия. В конфиге некоего VPN-провайдера есть скрипт, который отрабатывает в случае «if down interface». И в этом случае восстанавливает шлюз по-умолчанию на реальный шлюз провайдера. Типа, на тот случай, если пользователь сам отрубился от VPN.
        Но штука в том, что «if down interface» происходит также при потере коннекта к VPN-сервису, что уже раскрывает анонимность. Именно в этом случае Ваш способ срабатывает.

        Но всё равно спасибо за уточнение.
      • 0
        немного не по теме, но может вы знаете какой нибудь браузер с несколькими профилями с которыми можно работать параллельно? На манер того как в хроме есть обычный режим и инкогнито. Вот было бы неплохо несколько обычных режимов держать параллельно. Запуск хрома с разными параметрами из консоли а) не слишком удобен б) как то не слишком стабилен, по непонятным причинам.

        А касательно защиты профилями от CSRF это тоже самое что и разлогиниваться на сайте перед тем как заходить на другие, или же держать все развлекательные сайты в отдельном браузере. Не является защитой. Сложно провесит CSRF против сервиса, если ты на нем не авторизован.
        • 0
          Так Firefox же, может держать несколько профилей и режим инкогнито одновременно. Очень удобно:
          firefox -p  -no-remote
          
  • +3
    Статья в целом интересная, кое-что новое почерпнул. Но название статьи и её содержимое не соответствуют друг другу.

    Название статьи: «Картинки с внешних ресурсов — добро или зло?»

    Часть содержимого: " по умолчанию TTL в Linux равен 64, в Windows — 128. Такие большие различия помогут определить OS удаленного хоста в некоторых случаях. "

    Может, стоит мух отдельно, а котлеты — отдельно? Или я чего не знаю, и есть способ выяснить TTL приходящего от клиента пакета на уровне веб с помощью картинки, подгружаемой на веб-сервер со стороннего веб-ресурса?
    • 0
      Вы имеете ввиду использование скриптовых языков за веб-сервером, например PHP?

      Для этого используются самописные сервера — это заметно удобнее, можно использовать любой уровень OSI, управлять несколькими соединениями из одного приложения и тратится меньше системных ресурсов.
  • +1
    есть еще одна полезная штука, которую вы не упомянули — утечки ДНС
    хорошо отлавливать прокси, т.к. на практике люди их использующие очень часто делают резолв доменов напрямую (в FF, например, по дефолту резолв доменов через прокси отключен)
    • 0
      Точно, спасибо. По этой теме наверное надо писать отдельно и тестировать возможные ситуации на нескольких хостах — DNS не такая простая вещь, запросы посылаются не напрямую и кэшируются на промежутке.
      • 0
        С кешированием нет проблем.
        Тема очень широкая, но в случае картинок при проходе через цепочку редиректов на первом редиректе можно собрать основные данные и присвоить ид запросу, далее средиректить на уникальный субдомен 1234.example.com (1234 — ид запроса)

        Из недостатков метода — сравнительно сложная реализация т.к. надо допиливать ДНС сервер и связывать его с основным сборщиком данных. Не так чтоб очень сложно, но заметно труднее, чем собирать хидеры и куки.
    • 0
      Интересно, а как работает whoer.net? Каким образом он определяет DNS?
      • 0
        Примерно так и работает.

        <!-- DNS unique domain -->
        <tr>
        <td align="left" class="wtl_z"><strong>DNS</strong></td>
        <td colspan="3" class="wtr_z"><span id="dns_unique_domain"><span class="disabled">N/A</span></span></td>
        </tr> 
        

        <script language="javascript">
        flash_ajax_request( "dns_unique_domain", "/dns?domain=oowia4181853.br" );
        </script>
        <link rel="stylesheet" type="text/css" media="all" href="HTTP://oowia4181853.br.whoer.net/css/null.css"> 
        


        DNS при резолве отдаёт «No such name», но это неважно, запрос ведь уже прошёл. Оканчивается на ns55.dnlayer2.com/ns77.dnlayer2.com. Затем по GET-запросу на whoer.net/dns?domain=oowia4181853.br отдаётся IP.
        • 0
          И да, «уникальный домен» приходит прямо в HTML-e.

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