ФорумПрограммированиеПыхнуть хотите?F.A.Q. → Что можно узнать о клиенте

Что можно узнать о клиенте

  • vasa_c

    Сообщения: 3127 Репутация: N Группа: в ухо

    Spritz 8 марта 2008 г. 1:51

    Часто спрашивают подобное.
    Сделал наброски, нужно дорабатывать.

    [size=15]Что можно узнать о клиенте[/size]

    Вопрос: что я могу узнать о пользователях посещяющих мой сайт? Меня интересуют технические вещи типа их MAC-адреса, модели браузера, поддерживают ли они куки и т.п. Я не могу заставить их загрузить себе и выполнить какие-либо приложения. Я ограничен только стандартными средствами PHP и JavaScript.

    Ответ: вы можете узнать о них много чего интересного. Другое дело, что со стопроцентной вероятностью вы не можете узнать о них ничего.

    Главный вопрос — зачем вам нужно узнавать эти данные и как вы хотите их использовать.

    Итак, откуда можно получить данные о клиенте?


    [size=13]HTTP-заголовки[/size]

    Браузер общается с сервером по протоколу HTTP. Для получения страницы, он посылает на сервер HTTP-запрос. Именно из заголовков этого запроса и можно получить основную информацию о клиенте.

    В PHP установленном, как модуль Apache, заголовки запроса можно получить с помощью функции getAllHeaders().
    В PHP установленном, как CGI, напрямую получить их нельзя, однако сервер многие из них устанавливает в качестве переменных окружения.
    Распечатайте массив $_SERVER:
    print '<pre>'.print_r($_SERVER, 1).'</pre>';

    Все элементы с индексами, начинающимися на "HTTP_", это HTTP-заголовки. Например, $_SERVER['HTTP_USER_AGENT'] - заголовок 'User-Agent'.

    Рассмотрим пример запроса:

    Host: pyha.ru
    User-Agent: Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.8.1.12) Gecko/20080201 Firefox/2.0.0.12
    Accept: text/xml,application/xml,application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5
    Accept-Language: ru-ru,ru;q=0.8,en-us;q=0.5,en;q=0.3
    Accept-Encoding: gzip,deflate
    Accept-Charset: windows-1251,utf-8;q=0.7,*;q=0.7
    Keep-Alive: 300
    Connection: keep-alive
    Referer: http://pyha.ru/
    Cookie: PHPSESSID=98766253484857394596039172698712
    If-Modified-Since: Sat, 08 Mar 2008 07:36:04 GMT


    Разберемся с каждым заголовком и тем, чем он может нам помочь:

    [size=12]Host[/size]
    По нему сервер определяет запрашиваемый виртуальных хост. Нам этот заголовок ничем не поможет.

    [size=12]User-Agent[/size]
    Наиболее интересный заголовок, описывающий программу-клиент. В нашем случае по нему можно узнать марку и версию браузера (Firefox/2.0.0.12), операционку (Windows NT 5.1 = Windows XP), язык - "ru".
    Для чего он может быть использован:
    1. Для сбора статистики.
    2. Для выдачи различного контента различным браузерам (обычно верстки, подогнанной под особенности конкретного браузера). Правда, сейчас это считается прошлым веком и рекомендуется делать всё один раз и кроссбраузерно.
    3. Для выявления поисковых роботов. Основные поисковые роботы (Google, Yandex …) обычно имеют свои собственные User-Agent.
    Полный список User-Agent можно найти здесь — http://www.user-agents.org/index.shtml (да, да, нифиговенький).

    [size=12]Accept[/size]
    Поддерживаемые клиентом типы документов. По идее может использоваться для выдачи другого документа, если клиент не поддерживает основной тип. Например, не поддерживает text/html, но поддерживает text/plain - и мы вместо html подсовываем ему простой текст. Однако, подобной чепухой, обычно не занимаются, а браузеры часто устанавливают данный заголовок в */* (типа, поддерживаю всё подряд).

    [size=12]Accept-Language[/size]
    Поддерживаемые языки. Может использоваться для определения языка клиента и выдачи ему различных языковых версий сайта (или переадресации на них). Но в большинстве случаев используется только для сбора статистики.

    [size=12]Accept-Encoding[/size]
    Указывает, что клиент понимает контент сжатый gzip. В этом случае мы можем сжимать выдаваемый документ для уменьшения времени передачи. С помощью, например, ob_start('ob_gzhandler').

    [size=12]Accept-Charset[/size]
    Поддерживаемые кодировки. По крайней мере с начала 2000-х годов на них обычно забивают. Все современные браузеры поддерживают все основные кодировки.

    [size=12]Keep-Alive, Connection[/size]
    Всё, что мы можем отсюда узнать, это то, что клиент поддерживает постоянные соединения. Хотя вряд ли это нам сильно интересно.

    [size=12]Referer[/size]
    Страница, с которой пользователь попал на нашу. Может использоваться для определения пути по сайту или выявления сайтов, с которых пришли на наш. Так же может быть использована в качестве дополнительной защиты при отправки формы (на странице-обработчике смотрим, действительно ли пользователь пришел со страницы с формой). Почему такая защита не является сколько-нибудь сильной, написано ниже.

    [size=12]Cookie[/size]
    Переданные клиентом куки (те самые, которые можно найти в массиве $_COOKIE). С точки зрения сбора данных о клиенте, это говорит хотя бы о том, что он поддерживает куки).

    [size=12]If-Modified-Since[/size]
    Говорит серверу, что не нужно выдавать целиком страницу, если она не была изменена после указанного времени (скорее всего она есть у клиента в кэше). Всё, что это говорит нам, это то, что клиент скорее всего поддерживает кэш.


    [size=13]Насколько можно доверять HTTP-заголовкам[/size]

    Нинасколько!

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

    Для чего можно использовать данные из http-заголовков?

    1. Для сбора статистики. Подавляющее большинство пользователей сайта не будет изменять заголовки и усредненная статистика скорее всего будет близка к верным значениям.
    2. Для формирования различного вывода. Собственно, это и есть первоначальная задача http-заголовков - предоставить серверу информацию о возможностях клиента.

    Для идентификации пользователя и решения других вопросов безопасности использовать http-заголовки нельзя.
    Вернее можно, но как дополнительную защиту. Например, вышеописанный трюк с referer или привязка сессии к user-agent, сможет помочь против большинства малолетних хакеров.


    [size=13]IP-адрес[/size]

    Переменная $_SERVER['REMOTE_ADDR'] содержит IP-адрес машины, которая произвела соединение с нашим сервером.
    В отличии от HTTP-заголовков этой переменной можно более-менее доверять.

    Другое дело, нужно понимать, что это вообще такое и где это можно использовать.
    Данный адрес нельзя использовать для точной и длительной идентификации компьютера за которым сидит пользователь, ходящий по нашему сайту:
    1. IP-адрес может быть динамическим и меняться при каждом подключении.
    2. Пользователь может находиться в локальной сети (а сейчас таких большинство) и мы будем видеть только IP этой сети - один на все компьютеры внутри неё.
    3. Пользователь может зайти к нам через прокси-сервер или цепочку прокси. В этом случае REMOTE_ADDR будет указывать на последний прокси в этой цепи.

    Где можно использовать?
    1. В простых случаях - защита от накрутки голосования, бан по IP. На сто процентов это не спасет, а так же забанятся все пользователи локальной сети, но, в принципе, в таких случаях этим можно пользоваться.
    2. Как дополнительное средство защиты. Например, привязка сессии к IP.

    Вообще, есть возможность попытаться определить реальный адрес пользователя. Прокси-серверы и роутеры локальных сетей, могут передавать информацию о нём в http-заголовках. Например, в "HTTP_X_FORWARDED_FOR", "X_REAL_IP" и других. Попытки определить реальный IP, а так же список подобных заголовком можно в больших количествах найти на форумах.

    Однако:
    1. Это те же http-заголовки, которым, как мы поняли, доверять никак нельзя. Кто-то может ставить их правильно, кто-то может поставить в них что-нибудь другое, а кто-то вообще не будет их устанавливать.
    2. Даже если верить конечному "реальному IP", он всё равно вряд ли подойдет для идентификации конкретного пользователя. Если пользователь находится в локальной сети, то этим самым реальным IP будет его адрес в этой сети. Может быть неограниченное количество пользователей других сетей, у которых в них будет тот же самый IP.

    Использовать эти дополнительные заголовки можно только так же, как и остальные - для сбора статистики и небольшой добавки к защите (привязываем сессию не к одному IP, а к всему набору).


    [size=13]get_browser[/size]
    Многие любят использовать для определения возможностей клиента функцию get_browser.

    Функция, конечно, забавная, но нужно помнить следующие вещи:
    1. Определяет она эти возможности ни каким-то волшебным методом, а с помощью разбора всё-того же User-Agent, которому доверять, как мы помним, никак нельзя.
    2. Работает она только для тех User-Agent, которые перечислены в её конфигурационном файле.
    3. Индексы получившегося массива, типа, "javascript", указывают на то, что данная версия браузера в принципе поддерживает JavaScript, куки и т.п. Включены или нет они у конкретного пользователя в данный момент, она сказать не может.


    [size=13]Включены ли куки?[/size]
    Как узнать, включены ли у пользователя куки? Это часто нужно при организации сессий (где передавать идентификатор?) и в других вещях.
    К сожалению, понапихав в HTTP-стандарт заголовков, типа, "Accept-Charser", туда забыли добавить "Accept-Cookie", поэтому всё достаточно сложно.

    1. Если в запросе пришли какие-то куки (массив $_COOKIE не пуст), то можно с определенной увереностью говорить, что клиент эти куки поддерживает. Можно на каждой странице ставить проверочную куку, чтобы на следующей она пришла.
    2. Если пользователь перешел со страницы нашего сайта (воспользуемся заголовком Referer), а проверочной куки у него нет, то скорее всего, они у него выключены.
    3. Если на страницу пришли не с нашего сайта и кук нету, то тут еще сложнее. Можно по User-Agent определить бот это или браузер. Боты скорее всего не поддерживают куки, а браузеры обычно поддерживают.

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


    [size=13]Что можно узнать через JavaScript[/size]

    С помощью JavaScript можно собрать дополнительную информацию о клиенте (разрешение экрана, количество цветов и т.п).

    Обычно делается так (большинство счетчиков работают по этому принципу): с помощью JS в документ вставляется тег <IMG> с SRC указывающим на php-сценарий и в GET-параметры ему с помощью JS добавляются данные, которые можно получить на клиенте. Так же в <noscript> можно добавить изображение без параметров.

    - После вставки IMG в документ, браузер посылает запрос сценарию, указанному в SRC, который и обрабатывает данные параметры.
    - Если JavaScript отключен, то отправляется запрос на картинку из <noscript> без параметров.
    - Если отключены картинки или это поисковик, то никакого запроса не будет.
    - Получить эту информацию можно только после первого обращения к сайту. При формировании первой страницы, мы её использовать не можем.
    - Всё это идет через клиента, поэтому опять-таки стопроцентно доверять полученной информации нельзя.
  • kendo

    Сообщения: 446 Репутация: N Группа: Адекваты

    Spritz 8 марта 2008 г. 8:12, спустя 6 часов 21 минуту 15 секунд

    Хочу добавить, что WAP-кодерам иногда может быть полезна строка "Accept", поскольку если передается строка вида "Accept: */*", то это не означает, что поддерживаются wap-wml страницы. Если передается именно "text/vnd.wap.wml", то значит, мы имеем дело с мобильным телефоном.
    Кстати, в таком случае в параметр "User-Agent" обычно помещается марка и модель телефона (во всяком случае, если используется встроенный браузер).
  • adw0rd

    Сообщения: 22905 Репутация: N Группа: в ухо

    Spritz 10 марта 2008 г. 11:40, спустя 2 дня 2 часа 27 минут

    Для изменения заголовков рекомендую программку Proxomitron, она также умеет сниффить заголовки.

    P.S. В статье под словом "хакер" понимается "кракер".
    adw/0
  • phpdude

    Сообщения: 26624 Репутация: N Группа: в ухо

    Spritz 18 октября 2009 г. 4:55, спустя 586 дней 17 часов 14 минут

    шрифты пиздец … )))))
    Сапожник без сапог

Пожалуйста, авторизуйтесь, чтобы написать комментарий!