Защита данных передаваемы посредством GET запроса
- Войдите на сайт для отправки комментариев
Вс, 02/03/2014 - 02:00
Доброй ночи, интересует вопрос защиты передаваемых данных средствами GET запроса, с arduino uno + ethernet shield на удаленный web server (apache на ос CentOS) . Какие могут быть варианты?
А в чем суть вопроса-то? Если вас смущает, что данные передаются в открытом виде, то обфусцируйте их, а на сервере раскодируйте обратно.
Либо используйте протокол https.
Боюсь, ардуина не потянет https.
ну может не совсем стандартный https, но вполне себе приличное кодирование сделать можно с декодированием на принимающей стороне
например https://github.com/DavyLandman/AESLib
axill, очень интересная вешь (вы уже не раз, и мне в том числе советовали эту библу). Однако, я, например, не нашел реализации декодирования AES для принимающей стороны (читай - php). Есть множество примеров (и матрицы перестановки вроде те же и алгоритм похож), однако при декодировании (да и при кодировании одного и того же сообщения одним и тем же ключем) выходные данные разнятся с этой библой. Может есть рабочий php-пример?
P.S. Мне принципиально php, т.к. в принимающей ардуине просто не хватило места под эту библу, а менять что-то уже нет времени (не успеет приехать, увы - к нам от китайцев идет месяца полтора-два все).
примера на php нет
у вас web сервер на какой стороне? если на сторону php, то может быть посомтреть на предмет готового решения декодировать на уровне web сервера? Сам не вникал насколькко AES применим для стандарта HTTPS, но ведь HTTPS это всего лишь контейнер для HTTP, возможно есть готовые решения.
поисковик с ходу находит что-то похожее http://objectmix.com/apache/668229-aes-ssl-apache2.html
как вариант
http://ru.wikipedia.org/wiki/RTEA
примеры на пхп найти просто в гугле написав php aes. Первые три ссылки посмотрел - полезные. Недавно нашёл реализацию aes'а на джава скрипте - вау. Тут https считаю неуместным.
>> выходные данные разнятся с этой библой.
и я немного проверял aeslib - aes128 - единственным блоком. Сравнивал с выводом в программе на c#, использовал две реализации AesCryptoServiceProvider и AesManaged. И пустой IV. Всё совпадает.
CityCat, есть успехи в теме ? ... http://arduino.ru/forum/programmirovanie/rfid-klyuchi-lan-set
примеры на пхп найти просто в гугле написав php aes. Первые три ссылки посмотрел - полезные. Недавно нашёл реализацию aes'а на джава скрипте - вау. Тут https считаю неуместным.
>> выходные данные разнятся с этой библой.
и я немного проверял aeslib - aes128 - единственным блоком. Сравнивал с выводом в программе на c#, использовал две реализации AesCryptoServiceProvider и AesManaged. И пустой IV. Всё совпадает.
CityCat, есть успехи в теме ? ... http://arduino.ru/forum/programmirovanie/rfid-klyuchi-lan-set
В том-то и беда, что лично я не нашел библы для php (конечно же гуглил и вариантов разных кучи видел и перепробовал), выходная строка которой после кодирования была бы = выходной строке после кодирования библой AESLib, ссылка на которую выше. Может я чего не так делаю? :)
toc, пни, пожалуйста на линк, если нашел таковой. Как раз по той теме все уперлось именно в это.
Остальное работает, но нет нормального кодирования. И все бы хорошо, но декодировать на принимающей стороне (читай - головной меге) не могу - нет места уже под эту либу, увы. Посему и надо декодировать уже серваком - лучше именно php-средствами.
CityCat, я пытался поставить php. Не осилил.
Пример на php: http://ru2.php.net/manual/ru/mcrypt.examples.php
Ещё пример: http://ru2.php.net/manual/ru/function.mcrypt-module-open.php
Официальные тестовые данные: http://en.wikipedia.org/wiki/Advanced_Encryption_Standard#Test_vectors
проверим это в ардуине
#include <AESLib.h> void printArr(uint8_t* arr, byte len) { int i; for (i=0; i<len; i++) { Serial.print("0123456789ABCDEF"[arr[i]>>4]); Serial.print("0123456789ABCDEF"[arr[i]&0xf]); Serial.print(" "); } Serial.println(); } void setup() { Serial.begin(57600); Serial.println("toc at arduino ru/myAes"); uint8_t key[] = { 0x10, 0xa5, 0x88, 0x69, 0xd7, 0x4b, 0xe5, 0xa3, 0x74, 0xcf, 0x86, 0x7c, 0xfb, 0x47, 0x38, 0x59 }; uint8_t data[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; Serial.print("key: "); printArr(key, sizeof(key)); Serial.print("data: "); printArr(data, sizeof(data)); aes128_enc_single(key, data); Serial.print("encrypted data: "); printArr(data, sizeof(data)); aes128_dec_single(key, data); Serial.print("decrypted data: "); printArr(data, sizeof(data)); } void loop() { }ага
Cчитаю, что совместимость библиотеки aeslib со стандартом aes доказана.
Попробуйте в php повторить. Режим ecb, 128 бит, пустой iv.
Кстати, aes и rijndael - одно и тоже. Похоже, в php (в mcrypt) используют второй вариант названия.
Если на php не получится, предлагаю попробовать java/томкат или c#/aspnet.
Не получалось потому что, как говорится сам дурак - не был запущен mcrypt.
Спасибо огромное - все получилось!
Тем кому онтересно (вдруг кто-то столкнется с этим):
Установка и активация mcrypt (ubuntu):
Ну и, собственно, код php:
<?php $cryptcipher = "rijndael-128"; $cryptmode = "ecb"; $text = "5432109876543210"; $key = "0123456789012345"; $str= AESCrypt($text, $key, $cryptcipher, $cryptmode, 0); echo "Crypt string: ". bin2hex($str). "<br>"; echo $str."<br>"; $str= AESCrypt($str, $key, $cryptcipher, $cryptmode, 1); echo "Decrypt string: ". bin2hex($str). "<br>"; echo $str."<br>"; /* Функция шифрования/расшифровки строки */ function AESCrypt($text, $key, $cipher, $mode, $encdec) { // Открываем модуль шифрования */ $td = mcrypt_module_open($cipher, '', $mode, ''); // Инициализация шифрования mcrypt_generic_init($td, $key, ''); // Шифрование (или расшифровка) $cr = ($encdec==0 ? mcrypt_generic($td, $text) : mdecrypt_generic($td, $text)); // Завершаем обработчик шифрования mcrypt_generic_deinit($td); // Закрываем модуль шифрования mcrypt_module_close($td); // Возвращаем результат return $cr; } ?>Подтверждаю - данные одинаковы с выходными данными вышеназванной библиотеки AESLib
а если нет необходимости скрывать данные, а есть лишь необходимость исключить ложные GET не с ардуины? Как вариант добавлять хеш в URL, который генериться из передаваемых параметров и ключа?
дело в том, что дання библиотека съедает 240байн динамической памяти, а в моем проекте ее и так остается притически мало. Пытаюсь найти решение создавать простой хеш на обеих сторона (ардуина и сервер) что бы в ардуине такая процедура отъедала как можно меньше памяти.
Возможно есть еще какие-то решения, позволяющие идентифицировать только лишь мое устройство и исключить ложные вызовы?
подниму старую тему, итак некое устройство на сервер через get запрос шлет на сервер (PHP Linux) некие данные,
и для идентификации отсылает в том числе и IMEI модема для идентификации, типа так:
http://......./sim800l/add.php?imei=123456789012345
стоит задача защитить это от попыток повторения кем либо.
Подумал зашить к скетч например 20 случайных кодов, при каждой отправке данные по XOR объединяются с кодом,
и уже отправляется, сервер перебирает обратную операцию с кодами и если IMEI находиться в базе, значит
данные корректны. Устройств много, поэтому подобрать повторяющиеся комбинации будет сложно.
Но данное решение мне не нравится - как то не красиво.........
Есть ли более рациональное/правильное решение ?
классика - это генерить хеш данные+ключ на стороне клиента и тоже на стороне сервера, передавать и сравнивать хеш.
но у меня не выходит уместить в мапять ардуинки и мой скетч и библиотеку хешей. пока ищу решение.
как топорный, временный метод можно чекать юзерагента (сим-модуль), что бы как минимум невозможно было повторить запрос в браузере.
если использовать AES, зашифрованная строка каждый раз будет разной, даже если исходные данные одни и те же. Однако от тупого копирования пакета так не защититься.
хм...AES мне нравиться мысль, но боюсь сам не реализую - сложновато,
Блочный не сложный алгоритм Speck я реализовывал, но там если исходные данные повторялись то и результат одинаковый был.
НИкому не встречался алгоритм со свойствами AES но попроще в реализации?
классика - это генерить хеш данные+ключ на стороне клиента и тоже на стороне сервера, передавать и сравнивать хеш.
но у меня не выходит уместить в мапять ардуинки и мой скетч и библиотеку хешей. пока ищу решение.
как топорный, временный метод можно чекать юзерагента (сим-модуль), что бы как минимум невозможно было повторить запрос в браузере.
PROGMEM не спасет?
проверять какой либо номер сим модуля - один фиг что и IMEI _ не вариант :(
НИкому не встречался алгоритм со свойствами AES но попроще в реализации?
для ардуины есть несколько готовых библиотек AES. Например, AESLib всего порядка 3К во флеш знамает. Там в исходниках и алгоритм можно посмотреть.
Подумал зашить к скетч например 20 случайных кодов, при каждой отправке данные по XOR объединяются с кодом,
и уже отправляется, сервер перебирает обратную операцию с кодами и если IMEI находиться в базе, значит
данные корректны.
Чтобы не перебирать при раскодировании 20 кодов, можно сделать так - кодировать ИМЕИ каждый раз уникальным случайным кодом и отсылать код вместе с сообщением, закодировав его в свою очередь статичным кодом, известным серверу.
Каждая посылка будет выглядеть разной, даже если все ланные одинаковы. В то же время затраты на раскодирование будут существенно ниже, чем в варианте с 20 кодами, а стойкость, ИМХО, не хуже.
Спасибо,
Щас на неделю в отпуск, потом
Попробую оба варианта, но думаю для
Современного самого примитивного сервера
Перебрать SQL запросом 20 кодов + раскодировка
Это доли секунды.
https://ru.wikipedia.org/wiki/RTEA
Вообще, моё такое мнение что симметрия - это всё баловство. При таких деньгах (шла речь о мускл сервере, о каких-то модемах, всмысле в ардуинах как я понимаю торчит usb host, который ну не бывает дешевле тысячи) - можно и малину напрячь, чтобы RSA шифровала. Реализаций до чёрта, хоть на C++, хоть на JS. Туда кстати gnupg от Debian встаёт и нормально пашет, так что можно без костылей типа JS.
подниму старую тему, итак некое устройство на сервер через get запрос шлет на сервер (PHP Linux) некие данные,
и для идентификации отсылает в том числе и IMEI модема для идентификации, типа так:
http://......./sim800l/add.php?imei=123456789012345
стоит задача защитить это от попыток повторения кем либо.
Задача защиты при передаче данных многогранна сама по себе и от количества векторов атаки зависит цена защиты. Поэтому нужно понять, в чем непосредственно заключается риск - в перехвате пакета, несанкционированном доступе к данным, в подделке информации.
Непосредственно в повторении пакета ничего страшнее DDOS-а нет (а от него и так шифрование не спасает), если передавать в его составе некую меняющуюсю метку, на основании которой сервер будет делать заключение - обрабатывать пакет или отбросить, как повторный.
В этом то и суть придумать меняющуюся метку, понятную серверу, но сложно понимаемую злоумышленнику, который например может попытаться передать фальшивые координаты авто с правильным imei. Как таковое шифрование не нужно.
Через неделю попробую сначала AES, если результат шифрования будет меняться, то добавлю несколько ключей и меня (и заказчика) это вполне устроит.
НИкому не встречался алгоритм со свойствами AES но попроще в реализации?
для ардуины есть несколько готовых библиотек AES. Например, AESLib всего порядка 3К во флеш знамает. Там в исходниках и алгоритм можно посмотреть.
да, но как писали выше нет смысла скрывать (кодировать) передаваемые данные, задача не повторить передачу, потому в AES вроде как не вижу смысла. Если я верно понимаю, по крайней мере меня бы это устроило полностью, важно иметь простенький метод создания ХЕШа данные+ключ, что бы этот метод повторить на сервере средствами PHP и сравнивая ХЕШ данные+ключ что бы исключить повторение запроса злоумышленником.
PROGMEM не спасет?
проверять какой либо номер сим модуля - один фиг что и IMEI _ не вариант :(
что-то у меня не вышло с PROGMEM или я не понимаю как его готовить :) когда подключаю библиотеки для шифрования код не влазит в ардуину выдавая ошибку не достаточно памяти.
да, но как писали выше нет смысла скрывать (кодировать) передаваемые данные, задача не повторить передачу, потому в AES вроде как не вижу смысла. Если я верно понимаю, по крайней мере меня бы это устроило полностью, важно иметь простенький метод создания ХЕШа данные+ключ, что бы этот метод повторить на сервере средствами PHP и сравнивая ХЕШ данные+ключ что бы исключить повторение запроса злоумышленником.
Покопайте в сторону "Генератора псевдослучайных чисел" (на википедии обзорная статья есть). Если придумаете, как синхронизировать на обоих концах ряд (т.е. при включении ардуина должна получить от сервера какое-то число из ряда и продолжить генерацию). Завершенная транзакция передачи данных - условие для взятия следующего числа обоими концами... А число - это как раз метка, которая будет "удостоверять" пакет (пока алгоритм не будет вскрыт). Видели, наверное, в банках скретч-карточки такие выдавали с числами типа одноразовых пин-кодов?
Ну или в пределах сессии можно получать каждый раз от сервера какой-то новый набор байт, трансформировать по известному обоим концам алгоритму и отсылать назад вместе с данными. Если сервер, проведя аналогичную операцию самостоятельно, получил эквивалентный трансформированный набор - всё ок, потенциально это "наш контроллер".
В принципе, можно особо не изобретать ничего:
- при коннекте клиент говорит, что я - система с таким-то IMEA;
- сервер отвечает - а докажи-ка. Вот тебе случайный набор байт, посоли-ка их и хэш (MD5, к примеру) покажи мне;
- клиент делает, что просят и возвращает соленный хэш вместе с координатами (например);
- сервер, зная IMEA, берет из справочника соль и тоже делает соленый хэш. Затем сравнивает. Сошлось - значит координаты принимаются.
Это так, простые способы защиты от спуфинга, которые можно на маломощных системах реализовать.
P.S. про хеш, я смотрю, уже написано было. Ну ничего, у меня более развернуто.
Не проще поставить пароль на папку (.htaccess), авторизовывать по паролю и после уже передавать что угодно в открытом виде? Возможно не правильно понял задачу
Не проще поставить пароль на папку (.htaccess), авторизовывать по паролю и после уже передавать что угодно в открытом виде? Возможно не правильно понял задачу
Есть пример как используя GSM модуль установить http соединение и предварительно авторизироваться командами из ардуинки?
https://forum.arduino.cc/index.php?topic=131722.0 вот первая же ссылка в гугле
От перехвата пароля Basic Authorization никак не защитит. Это нужно учитывать.
От перехвата пароля Basic Authorization никак не защитит. Это нужно учитывать.
так от нагретого паяльника в одном месте у программиста и rsa 2048 не защитит. Просто нужно понимать серьезность проекта - если контроль вечно пьяного дяди Васи который ворует солярку и катается по полям то и простой гет запрос сойдёт а если речь о большом проекте то конечно нужно что то мощнее атмеги 328. Ассиметричный алгоритм шифрования (rsa) и диалоговый обмен (на сервере свой приватный ключ а у клиента свой).
Холиварить я не собираюсь.
Был вопрос - как сделать так, чтобы снизить риск подделки пакета. Если расматривается атака сниффингом, то Basic Authorization дает ровно ту же вероятность взлома, как и никакой способ защиты - потому что все равно нужно знать 20 шт. IMEA из миллионов или миллиардов, имена полей в GET и пр. А раз уж подслушал IMEA, то подслушал и хеш пароля. А там уже подставляй его, да засылай фигню всякую.
Не думал, что так тема разростется...
Нет, авторизация не прокатит,
Представьте 30± устройств которые каждые несколько минут шлют данные в качестве своего идентификатора используют imei,
Задача защититься от умного студента, т е смесь 20 кодов с imei и AES вижу оптимальным вариантом. Протестирую - выложу результаты.
Это не нагрузка. Даже если каждую минуту втрое больше клиентов будут слать свои координаты и то сервер будет чай попивать.
Это не нагрузка. Даже если каждую минуту втрое больше клиентов будут слать свои координаты и то сервер будет чай попивать.
Никто и не спорит, главное чтоб сторонний человек со снифером не понял что шлют устройства.
Поддерживаю :) перехватить Basic не сложно. На всякий случай повторюсь: задача не защита от перехвата, а защита от генерации злоумышленником повторных запросов. Было бы интересно узнать как выйдет, потому как у меня получилось норм с md5 хешем, но к сожалению не влажу по памяти, потому искал более легкий алгоритм создания хеша.
если использовать AES, зашифрованная строка каждый раз будет разной, даже если исходные данные одни и те же.
не согласен
стоит задача защитить это от попыток повторения кем либо.
1. отправитель нумерует посылки (1,2,3,...) seq
2. получатель сохраняет номер предыдущей посылки, lastSeq
3. и при получении новой посылки проверяет:
if (seq > lastSeq) { // если канал связи допускает потери
// хорошая посылка
или
if (seq == lastSeq+1) { // если канал связи надёжный
// хорошая посылка
Если шифрования нет и последовательность легко угадывается, то это тоже не защита. Несколько перехваченных посылок и интрудер может имитировать сторону, которой доверяют. Да еще и выпихнуть эту сторону из процесса обмена. Такой принцип (последовательная нумерация) применяется в протоколе TCP для правильной сборки фрагментированных пакетов, шедших разными путями. Более он ни от чего не может защитить, увы.
Условий задачи реально мало. Я понял что нужно защитить от подделки. А нужно ли защитить от повторной отправки одинаковых данных. Т.е допустим n32, s40, имей 12345678912345 что означает что трактор дяди Васи в поле под селением бамут а должен быть в Москве на красной площади. Если на это пофиг то меняйте местами значения на своё усмотрение , на сервере обратную конвертацию, проверяйте имей по контрольной сумме и вносите данные в базу. Но в таком случае ничего не мешает сделать копию маршрута и из дома отправлять делая вид что работаешь. А как на счёт варианта статичного айпи адреса и авторизации по нему?
Условий задачи реально мало. Я понял что нужно защитить от подделки. А нужно ли защитить от повторной отправки одинаковых данных. Т.е допустим n32, s40, имей 12345678912345 что означает что трактор дяди Васи в поле под селением бамут а должен быть в Москве на красной площади. Если на это пофиг то меняйте местами значения на своё усмотрение , на сервере обратную конвертацию, проверяйте имей по контрольной сумме и вносите данные в базу. Но в таком случае ничего не мешает сделать копию маршрута и из дома отправлять делая вид что работаешь. А как на счёт варианта статичного айпи адреса и авторизации по нему?
И от подделки и от повторной отправки, что по сути и есть подделка :)
Условий задачи реально мало. Я понял что нужно защитить от подделки. А нужно ли защитить от повторной отправки одинаковых данных. Т.е допустим n32, s40, имей 12345678912345 что означает что трактор дяди Васи в поле под селением бамут а должен быть в Москве на красной площади. Если на это пофиг то меняйте местами значения на своё усмотрение , на сервере обратную конвертацию, проверяйте имей по контрольной сумме и вносите данные в базу. Но в таком случае ничего не мешает сделать копию маршрута и из дома отправлять делая вид что работаешь. А как на счёт варианта статичного айпи адреса и авторизации по нему?
И от подделки и от повторной отправки, что по сути и есть подделка :)
не совсем так. Точнее совсем не так. Абсолютно разные понятия. Вспоминаем сигнализации с динамичным кодом который подделать нельзя а послать второй раз ничего не мешает. Нужно больше информации.
От повторной отправки при одностороннем обмене сложно будет - даже если вы зашифруете тем же aes алгоритмом посылку то ничего не помешает отправить Ее второй раз. Можно в неё добавлять реальное время а на сервере сверять и если отличие существенное то отклонять
Да, сервер естественно будет анализировать правильность, корректность, опять же отправив одну команду повторно, злоумышленник ничего не добьётся, главное чтобы он общую картину не смог повторить.
Эмм, а реализовать handshake с генерацией сеансового ключа? https://habr.com/post/151599/
Вариант с Диффи-Хеллманом неплох.
Добавление таймштампа в пакет - это открытая дверь и оверхед в коде на операции со временем. Почему вы все время считаете, что добавление в пакет общеизвестных данных как-то его защищает?
Можно что-нибудь простое выдумать, если время будет синхронизировано на всех устройствах.
Самое простое - с сервера периодически слать случайное R, на клиенте формировать криптограмму из
R и GSM и IMEI и что еще там надо. К ней добавить MAC и отправлять. От перехвата и повтора защищено. Чуть сложней и защищенней добавить в криптограмму еще одно случайное сгенерированое на клиенте. Еще защищенней - криптограмму с 2-я случайными и MAC перетасовать, т.е перестановка байтов/битов известным клиенту и серверу способом. Пожалуй для даже очень умного студента это уже нерешаемо. А по серьезному вместо МАС шифровать конечно полюбому: DES/3DES/AES/RSA. Ресурсов должно хватить на все, кроме генерации ключей RSA, но оно и не требуется. В качестве источника криптовдохновения - либка Cryptolib.h. Она не ардуиновская, общесишная тассказать.
В принципе, можно особо не изобретать ничего:
- при коннекте клиент говорит, что я - система с таким-то IMEA;
- сервер отвечает - а докажи-ка. Вот тебе случайный набор байт, посоли-ка их и хэш (MD5, к примеру) покажи мне;
- клиент делает, что просят и возвращает соленный хэш вместе с координатами (например);
- сервер, зная IMEA, берет из справочника соль и тоже делает соленый хэш. Затем сравнивает. Сошлось - значит координаты принимаются.
Это так, простые способы защиты от спуфинга, которые можно на маломощных системах реализовать.
P.S. про хеш, я смотрю, уже написано было. Ну ничего, у меня более развернуто.
Да, только сервер ВСЕГДА, НА ЛЮБОЙ ЗАПРОС должен выдавать, что пакет принят и всё ОК )))
PS только в этом случае принимающая сторона не имеет обратной связи и возможности хакнуть канал
PPS какой-то процент потерянных пакетов вполне оправдан усилением защиты
Да, только сервер ВСЕГДА, НА ЛЮБОЙ ЗАПРОС должен выдавать, что пакет принят и всё ОК )))
На это можно смотреть двояко. Да, формально каждый запрос должен заканчиваться ACK/NACK. Но, с другой стороны, это облегчает атаку брутфорсом. Когда передающей стороне, вобщем-то, не особо требуется знать приняты кооррдинаты или нет - молчанка затрудняет хачинг. Интрудер никогда не узнает - правильно ли он подобрал пароль, хэш или CRC.
Боюсь если реализуют двухстороннюю связь с сервером с запросом / ответом и двухсторонним шифрованием - заказчик не поймёт :)
Проще надо смотреть на задачу, попробую сначала AES, а там посмотрим.