уязвимости postmessage и $.post()

  • Автор темы Автор темы todd
  • Дата начала Дата начала
Переварил всё ) Способ очень интересный, но в этом случае разработчикам других сайтов придется делать такую проверку каждый раз, когда они попытаются достать данные с моего сервера. Хочется облегчить им труд.

У меня появилась одна мысль:
что если написать так?

PHP:
function getmessage (login){
     Storage.put("login", login);
}
window.addEventListener("message", getmessage,false);

Злоумышленник сможет влезть внутрь функции getmessage и изменить локальную переменную login каким нибудь образом?
да, сможет. То что ты хочешь сделать - называется открытое API. Чтобы сделать его приятным - посмотри на уже существующие:
http://vk.com/page-1_2369497
http://api.yandex.ru/yaru/doc/ref/concepts/yaru-api-intro.xml
http://habrahabr.ru/post/38730/
ну и тд
 
GusakovNick
PHP:
function getmessage (login){
     Storage.put("login", login.data);
}
window.addEventListener("message", getmessage,false);
Код был написан не совсем верно. Скорее всего вопрос глупый, но все таки хочу удостовериться. А так?

То что ты хочешь сделать - называется открытое API. Чтобы сделать его приятным - посмотри на уже существующие:
Ок, посмотрел. +Попытался найти что нибудь по запросу Открытое API ничего, что помогло бы на данном этапе пока не нашел
 
Проверил всё, попытался хакнуть через адресную строку, но ничего не вышло. Я, конечно не знаю всех методов, но, вроде как, доступа к login.data у злоумышленника нет
 
todd
дело не в js, браузер с сервером общается на http протоколе, к примеру в телнете можно так написать
Код:
$ telnet phpclub.ru 80
Trying 176.9.111.107...
Connected to phpclub.ru.
Escape character is '^]'.
GET /talk/threads/%D1%83%D1%8F%D0%B7%D0%B2%D0%B8%D0%BC%D0%BE%D1%81%D1%82%D0%B8-postmessage-%D0%B8-post.75593/page-2 HTTP/1.1
Host: phpclub.ru

HTTP/1.1 200 OK
Server: nginx/1.0.15
Date: Fri, 12 Apr 2013 17:59:10 GMT
Content-Type: text/html; charset=UTF-8
Connection: keep-alive
X-Powered-By: PHP/5.4.13
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Cache-control: private, max-age=0
Set-Cookie: xf_session=6d2bbdfc5bce512ad6ab9d397bdfb863; path=/; httponly
Last-Modified: Fri, 12 Apr 2013 17:59:10 GMT
Content-Length: 45089

<!DOCTYPE html>
<html id="XenForo" lang="ru-RU" class="Public LoggedOut" xmlns:fb="http://www.facebook.com/2008/fbml">
<head>

	<meta charset="utf-8" />
	<base href="http://phpclub.ru/talk/" />
	
	<title>уязвимости postmessage и $.post() | Страница 2 | PHPClub - клуб разработчиков PHP</title>
....
таким образом я подделаю любую переменную
 
Переварил всё ) Способ очень интересный, но в этом случае разработчикам других сайтов придется делать такую проверку каждый раз, когда они попытаются достать данные с моего сервера. Хочется облегчить им труд.

Чтобы облегчить труд, пишется библиотека для работы с API.

Если хочется авторизовывать без сервер-сервер кода, выдавай api key на домен.
Посмотри как это сделано у других, например, на яндекс-картах.
 
fixxxer
Клиентская часть:

PHP:
<iframe id="iframe" onload="post('message');"></iframe>
<script>
function post(data){
        var win = document.getElementById('iframe').contentWindow;
        win.postMessage(data,'*');
}
function listener(server){
     if (тут проверка, пришло ли что то похожее на ключ){
          server.source.postMessage(server.data, '*');
     }elseif(тут проверка, есть ли что то похожее на логин, ну например){
          document.cookie = 'login = server.data';
     }
}
if (window.addEventListener){
	window.addEventListener("message", listener,false);
} else {
	window.attachEvent("onmessage", listener);
}
</script>

Серверная часть:

PHP:
<?$key = ...generate key...; $login = 'login'?>
<script>
function listener(mes){    
    if (mes.data == 'message'){
          mes.source.postMessage('<?=$key?>', '*');
    }
    if (mes.data == '<?=$key?>'){
          mes.source.postMessage('<?=$login?>', '*');
    }
}
if (window.addEventListener){
	window.addEventListener("message", listener,false);
} else {
	window.attachEvent("onmessage", listener);
}
</script>

Написал на скорую руку, не протестил. может где что недодумал. Но суть, вроде ясна - тоесть такой код с отправкой и проверкой ключа не получится взломать?
 
todd
Iframe - не нужен. Через него только видео что и хорошо встраивать, и то побыстрее бы умер этот способ.
http://touchdev.ru/documents/3037 - вот почитай про то как можно сделать авторизацию c API вк. Или погугли еще инфу по этой теме.
Хотя мне кажется тебе нужно то что описано под заголовком Способ рекомендуемый
 
GusakovNick
Просто iframe в моем случае - идеальное решение интерактивности, простоты обработки входных данных (есть лишь один канал, через который могут передаваться сообщения, поставить на него фильтр довольно просто, С Ифреймами знаком каждый начинающий веб разработчик. И он легко разберется с тем, что именно ифрейм вставляет плагин на его сайт, без чтения лишней документации. Самый большой минус апи библиотек, которые видел я - отсутствие возможности интерактивного общения в реальном времени клиента с сервером. Вконтакте, фейсбук обходят это маской реального времени - просто открывают страницу подтверждения входа. Но это очень мозолит глаза. Только ифрейм может позволить создавать прозрачные, легко интегрируемые интерактивные приложения, на мой взгляд.

Ну а что насчет кода наверху? :)

Безопасный? Или я снова что то упустил?
 
GusakovNick
Просто iframe в моем случае - идеальное решение интерактивности, простоты обработки входных данных (есть лишь один канал, через который могут передаваться сообщения, поставить на него фильтр довольно просто, С Ифреймами знаком каждый начинающий веб разработчик. И он легко разберется с тем, что именно ифрейм вставляет плагин на его сайт, без чтения лишней документации. Самый большой минус апи библиотек, которые видел я - отсутствие возможности интерактивного общения в реальном времени клиента с сервером. Вконтакте, фейсбук обходят это маской реального времени - просто открывают страницу подтверждения входа. Но это очень мозолит глаза. Только ифрейм может позволить создавать прозрачные, легко интегрируемые интерактивные приложения, на мой взгляд.
Ага, только любой не начинающий разработчик не согласится просто так юзать ифрейм. Вы сегодня предоставляете авторизацию, а завтра там будет реклама. Вы еще хотите чтобы разработчики из вашего iframe тащили данные. Я не знаю кому такое нужно. Если хотите чтобы работа с вашим АПИ была удобной - напишите библиотеку.
 
Вконтакте, кстати, тоже предоставляет возможность встривания своих апи посредством ифреймов ) Не знаю, как остальные сайты, конечно.

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

Но вопрос не в этом. Для меня главное сейчас - защитить данные. Способ с ключом хороший. Но я не знаю, все ли я правильно сделал, для обеспечания безопасности кода наверху
Да ты еще ничгео вообще не сделал))) ты код норм покажи, а не псевдо-недо-код))
 
Ну принцип того, как я буду это реализовывать то понятен )
Видно, как передается, возвращается и сверяется ключ.
Ну, разве что, все условия и вывод на сервере переведу из js на php, для безопасности
 
PHP:
<iframe id="iframe" onload="post('message');"></iframe>
<script>
function post(data){
        var win = document.getElementById('iframe').contentWindow;
        win.postMessage(data,'*');
}
function listener(server){
     if (тут проверка, пришло ли что то похожее на ключ){
          server.source.postMessage(server.data, '*');
     }elseif(тут проверка, есть ли что то похожее на логин, ну например){
          document.cookie = 'login = server.data';
     }
}
if (window.addEventListener){
	window.addEventListener("message", listener,false);
} else {
	window.attachEvent("onmessage", listener);
}
</script>

Серверная часть:

PHP:
<?$key = ...generate key...; $login = 'login'?>
<script>
function listener(mes){    
    if (mes.data == 'message'){
          mes.source.postMessage('<?=$key?>', '*');
    }
    if (mes.data == '<?=$key?>'){
          mes.source.postMessage('<?=$login?>', '*');
    }
}
if (window.addEventListener){
	window.addEventListener("message", listener,false);
} else {
	window.attachEvent("onmessage", listener);
}
</script>

Скину еще раз, что с безопасностью?
 
todd
Мне лично ничо не понятно. В тч зачем задавать вопросы и игнорить ответы:)
 
Ну а если так? )

На клиентской части стоит блок ифрейма. (1 строка)
Как только ифрейм полностью загружен, функция post отправляет запрос message на центральный сервер. (Клиентская часть 1 - 6 строки)
Далее сервер слушает входящие сообщения. Если в них есть message, то он генерирует ключ, запоминает его и отправляет клиенту (Серверная часть 1 - 6 строки)
Клиент так же слушает входящие сообщения. Если приходит что нибудь, похожее на ключ, то он отправляет его обратно (Клиентская часть 7 - 9 строки)
Сервер вновь обрабатывает входящие сообщения, сверяет если входящее сообщение такое же, как ключ, то отправляет клиенту логин (Сервер 7 - 9 строки)
Ну а клиент в свою очередь проверяет, если сообщение похоже на логин и не похоже на ключ - заносит логин в куки (Клиент 10 - 12 строки)
 
GusakovNick
Проверил код на практике, всё работает, все написано верно. Что не так?
 
todd
я правильно понял, что ты хочешь хранить пользователя и пароль в браузере, при надобности использовать их, если нужно, к примеру, зарегиться в том или ином содержимом фрейма.
при этом боишся о том что можно прочесть переменную извне.
мне кажется что любой банер написаный на js и показаный на странице во frame может считать любую переменную в _top.
PHP:
var myVar = parent.document.anotherVar;
ну или запустить функцию :), кстати это касается flash к примеру видео с ютуба
 
fixxxer
Ок. Но это обеспечание защиты клиента ) А как защитить себя?
Я использовал твою идею с ключом. То, что я написал безопасно?
WMix
Да, всё правильно ) Ну, фиксер только что сказал, как это обойти )
 
Сверху