Наскільки легко зламати JavaScript (у браузері)?


37

Моє запитання стосується безпеки JavaScript.

Уявіть систему аутентифікації, де ви використовуєте рамку JavaScript, як Backbone або AngularJS , і вам потрібні захищені кінцеві точки. Це не проблема, оскільки сервер завжди має останнє слово і перевірить, чи маєте ви право робити те, що хочете.

Але що робити, якщо вам потрібно трохи безпеки, не залучаючи сервер? Це можливо?

Наприклад, скажіть, що у вас є система маршрутизації на стороні клієнта, і ви хочете, щоб конкретний маршрут був захищений для користувачів, які ввійшли в систему. Тож ви пінг-сервер запитуєте, чи вам дозволяється відвідувати захищені маршрути, і ви продовжуєте рух. Проблема полягає в тому, що під час пінг-сервера ви зберігаєте відповідь у змінній, тому наступного разу, коли ви переходите до приватного маршруту, він перевірить, чи ви вже ввійшли (немає пінг-сервера), і залежно на відповідь він піде чи ні.

Наскільки легко користувачеві змінити цю змінну та отримати доступ?

Мої знання про безпеку (та JavaScript) не великі. Але якщо змінна не знаходиться в глобальному масштабі і знаходиться в приватній частині шаблону модуля, в якому є лише геттери, але не сеттери, навіть у такому випадку ви можете зламати річ?


29
На всі ці довгі відповіді. Коротше кажучи, щоб відповісти на ваш заголовок, "дуже зламаний". Щоб відповісти на перші два запитання, вбудовані один у одного, "без сервера, ви втратили безпеку" && "Ні". Щоб відповісти на 3-ту, "Дуже легко" і, нарешті, "Так, з легкістю". Ось так. На всі запитання відповіли. : P
SpYk3HH

Основний приклад, дивіться мою публікацію в блозі про додавання jQuery до будь-якої веб-сторінки. spyk3lc.blogspot.com/2013/05/… Тепер, молодий падаван, вийди і спробуй. Подивіться, як легко додавати jQuery на будь-який сайт, у якого його ще немає, а потім використовуйте jquery, щоб дуже легко маніпулювати будь-якою частиною зору без довгих рядків JavaScript. Бум!
SpYk3HH

7
Колись під час реєстрації доменного імені номер телефону був обов'язковим полем, але це було застосовано лише в javascript - не на стороні сервера. Отже, я відключив її, переглянувши функцію (використовуючи Firebug) та voilà! У мене немає мого номера телефону.
Ізката

8
manipulate any part of the sight without long lines site vs sight
mplungjan

8
Професійні веб-програмісти повинні виправити таке. Будь ласка. Це збентеження більше, ніж граматична штука) :) plus.google.com/u/0/+MonaNomura/posts/h9ywDhfEYxT
mplungjan

Відповіді:


26

Прочитайте відповідь Йоахіма, перш ніж прочитати цю. Він висвітлює загальні причини, що стоять перед вразливістю на стороні клієнта. Тепер для пропозиції, як ви могли подолати цю проблему ...

Безпечна схема зв'язку клієнт-сервер без необхідності автентифікації з сервером вручну на кожен запит:

Ви все ще даєте останньому слову сервер, і сервер все ще повинен перевірити все, що говорить клієнт, але це відбувається прозоро.

Припустимо протокол HTTPS для запобігання нападів "людина-посеред" (MITMA).

  • Клієнт вперше вручається з сервером, а сервер генерує для клієнта відкритий ключ і зберігає приватний, використовуючи асиметричну схему шифрування. Клієнт зберігає "відкритий" ключ сервера у локальній пам’яті, зашифрований захищеним паролем, який ви ніде не зберігаєте.

  • Клієнт зараз офлайн. Клієнт хоче виконати довірені дії. Клієнт вводить свій пароль і хапає відкритий ключ сервера.

  • Тепер клієнт виконує дії, засновані на його знаннях цих даних, і клієнт шифрує всі дії, які він виконує, відкритим ключем сервера для цього клієнта .

  • Коли клієнт в Інтернеті, клієнт надсилає свій ідентифікатор клієнта, а всі дії, які виконує клієнт, надсилаються на сервер, зашифрований відкритим ключем сервера.

  • Сервер розшифровує дії, і якщо вони мають правильний формат, він вважає, що вони виникли у клієнта.

Примітка:

  • Ви не можете зберігати пароль клієнта ніде, інакше зловмисник зможе отримати ключ і підписати дії як власні. Захищеність цієї схеми покладається виключно на цілісність ключа, який сервер створює для клієнта. Клієнту все-таки потрібно буде аутентифікуватись із сервером, коли він запитує цей ключ.

  • Ви все ще фактично покладаєтесь на сервер для безпеки, а не клієнта. Кожну дію, яку виконує клієнт, ви повинні підтвердити на сервері.

  • Можливо запуск зовнішніх скриптів у веб-працівників . Майте на увазі, що кожен ваш запит JSONP - це набагато більша проблема безпеки. Вам потрібно захистити ключ за будь-яку ціну. Після того як ви його втратите, зловмисник може представити себе за себе.

  • Це відповідає вашій вимозі, що "не виконується пінг на сервер". Зловмисник не може просто імітувати HTTP-запит із підробленими даними, якщо вони не знають ключ.

  • Відповідь Йоахіма досі правильна . Ви все ще фактично виконуєте всю автентифікацію на сервері . Єдине, що ви зберегли тут, - це необхідність перевірки паролів із сервером кожного разу. Тепер вам потрібно залучати сервер лише тоді, коли ви хочете виконати або витягнути оновлені дані. Все, що ми тут зробили, - це зберегти надійний ключ на стороні клієнта і змусити клієнта повторно його підтвердити.

  • Це досить поширена схема для програм на одній сторінці (наприклад, для AngularJS).

  • Я називаю відкритий ключ сервера "загальнодоступним" через те, що це означає в таких схемах, як RSA , але він насправді є конфіденційною інформацією в схемі і повинен бути захищеним.

  • Я б ніде не зберігав пароль у пам’яті. Я б змусив користувача вводити свій "офлайн" пароль кожен раз, коли він / вона починає працювати в автономному коді.

  • Не котуйте власну криптографію - використовуйте відому бібліотеку на зразок Стенфорда для аутентифікації.

  • Прийміть цю пораду як є . Перш ніж розпочати цю аутентифікацію в реальному світовому бізнесі, зверніться до експерта з питань безпеки . Це серйозне питання, яке боляче і легко помилитися.

Це критично , що ніякі інші сценарії не мають доступу до цієї сторінки. Це означає, що ви дозволяєте лише зовнішні скрипти з веб-працівниками. Ви не можете довіряти будь-яким іншим зовнішнім скриптам, які можуть перехопити ваш пароль, коли користувач вводить його.

Використовуйте a promptі ні поле, вбудований пароль, якщо ви не впевнені в собі і не відкладаєте його виконання (тобто воно не повинно жити до того моменту, коли події мають доступ до нього, але лише в коді синхронізації). І фактично не зберігайте пароль у змінній - знову ж таки, це працює лише в тому випадку, якщо ви довіряєте, що комп'ютер користувача не порушений (хоча це все справедливо і для перевірки на сервері).

Я хочу ще раз додати, що ми все ще не довіряємо клієнту . Ви не можете довіряти клієнту самотужки, і я думаю, що відповідь Йоахіма це відчуває. Ми лише отримали зручність не потребувати пінг-сервера перед початком роботи.

Схожі матеріали:


3
"Не котуйте власну криптовалюту" застосовується так само до протоколів, як і до примітивів, якщо навіть не більше, тому що, хоча люди зазвичай не досить дурні, щоб зробити свої власні примітиви, вони думають, що вони можуть створити протокол, це добре . Я також не бачу, для чого потрібна RSA. Оскільки ви використовуєте HTTPS, чому б не просто генерувати загальний секрет розміром 16-32 байтів і вимагати надсилання з майбутніми запитами? Звичайно, якщо ви це зробите, не забудьте використати перевірку рівності інваріантності за часом ...
Reid

2
+1 @Reid Так, я недавно нещодавно обговорював це питання з дещо експертом. Я приблизно грунтував тут примітивну схему на протоколі, про який я дізнався (за Рабіном IIRC), але принаймні, поки не зможу знайти специфіку (і обґрунтувати, наприклад, для чого потрібне асиметричне шифрування в цьому випадку). Не використовуйте запропоновану в цій відповіді схему, попередньо не порадившись із експертом з питань безпеки . Я бачив, як цей підхід використовується в декількох місцях, але на практиці це означає дуже мало, якщо що. Я також відредагував відповідь, щоб покращити це.
Бенджамін Груенбаум

Використання підказки додає мало безпеки. Зловмисник може змінити window.promptметод, щоб перехопити фразу пропуску або запустити власну підказку (можливо, в межах рамки!). Поле пароля має ще одну додаткову перевагу: символи не відображаються.
Rob W

@RobW Звичайно, вся ця схема марна, якщо сторінка була порушена. Якщо зловмисник має доступ до запуску JavaScript на сторінці, яку ми накрутили. Ідея підказки полягала в тому, що вона блокується, але ви маєте рацію, будь-які переваги безпеки, які вона надає, є сумнівними. Дивіться останнє посилання у списку.
Бенджамін Груенбаум

1
Поперше. Дивовижна відповідь, я думаю, що більше нічого не можу просити. З іншого боку, я хотів зробити для мене проекти домашніх тварин (і, звичайно, для тих, хто хоче ним користуватися), і, можливо, це надмірно (а може і ні). Я маю на увазі, я не хочу робити нічого серйозного, і я боюся, що я не можу розгорнути такого роду автор, який ви пояснили, відсутність знань. Я думаю, що я прокачу просту перевірку 401 або якщо у мене немає запиту, я просто підпилюю сервер кожного разу, коли я отримую доступ до таких маршрутів. Auth token - це теж варіант (і, можливо, найближче, пов’язане з тим, що ви тут пояснили AFAIK). Дякую :)
Ісус Родрігес

89

Це просто: будь-який механізм захисту, який покладається на клієнта, щоб він робив лише те, що ви йому сказали, може бути порушений, коли зловмисник має контроль над клієнтом.

Ви можете проводити перевірку безпеки клієнта, але лише для того, щоб ефективно діяти як "кеш" (щоб уникнути дорогого зворотного шляху до сервера, якщо клієнт вже знає, що відповідь буде "ні").

Якщо ви хочете зберегти інформацію від набору користувачів, переконайтеся, що клієнт цих користувачів ніколи не отримує цю інформацію. Якщо ви надсилаєте ці "секретні дані" разом з інструкціями ", але не показуйте їх", це стане дрібницею, щоб вимкнути код, який перевіряє цей запит.

Як бачите, ця відповідь насправді не згадує жодної специфіки JavaScript / браузера. Це тому, що ця концепція однакова, незалежно від того, який ваш клієнт. Це не дуже важливо, що це товстий клієнт (традиційний додаток для клієнтів / серверів), веб-додаток для старої школи або односторінковий додаток з широким JavaScript на стороні клієнта.

Після того, як ваші дані залишають сервер, ви повинні припустити, що зловмисник має повний доступ до нього.


Дякую. Було б чудово, якщо ви можете пояснити це трохи більше, мої знання з безпеки не так добре, і я розумію, що я лише помиляюся: P. Коли ви говорите про кешування, це кешувати лише тоді, коли сервер каже "ні"? Я маю на увазі, якщо сервер сказав "так" один раз, ви не можете це кешувати, правда?
Ісус Родрігес

3
Я просто хотів би додати , що це можливо закриває доступ до змінним в браузері (наприклад , в шаблоні модуля ваших згаданий), особливо за допомогою відладчика :)
Бенджамін Gruenbaum

2
@BenjaminGruenbaum: не соромтеся розширити це у відповідь, який зосереджується на стороні JS. Я лише дав тут високий, технологічно-агностичний огляд. Відповідь, зосереджена на самому JS, була б непоганою також!
Йоахім Зауер

1
Отже, коротко, якщо якась інформація / маршрут / все, що є доступним залежно від змінної javascript, це ні в якому разі не буде безпечним, оскільки ви можете легко змінити цю змінну, щоб сказати, що вам потрібно для доступу до цього приватного матеріалу.
Ісус Родрігес

4
@JoachimSauer Я думаю, що це пропустить точку цього питання, яку ти гарно прибив. Незалежно від того, які заходи безпеки вживає клієнт, можна компрометувати спілкування . Ви можете створити дуже надійні системи аутентифікації в JavaScript, але все нічого не варто, коли ви вставляєте спілкування на сервер, який інші клієнти теж вважають джерелом істини. Усі вихідні коди надсилаються клієнтській стороні, розумний зловмисник може просто прочитати його та імітувати HTTP-запит на сервер. Потрібно трактувати все, що походить від клієнта, як недовірене, якщо не перевірено на сервері.
Бенджамін Груенбаум

10

У ігровій спільноті є приказка: « Клієнт перебуває в руках ворога". Будь-який код, який працює за межами захищеної області, як-от сервер, є вразливим. У самому базовому сценарії, вразливий, щоб не запускатись в першу чергу. Це рішення клієнта фактично запустити ваш" код безпеки ", і користувач може просто "відмовтеся". У той час як з нативним кодом у вас є принаймні автоматична обтурація на збірку та додатковий рівень захисту через те, що зловмиснику потрібно бути хорошим програмістом, щоб маніпулювати цим, JS звичайно є безперешкодним і як звичайний текст. Все, що потрібно для того, щоб здійснити атаку, - це примітивні інструменти, такі як проксі-сервер та текстовий редактор. Зловмиснику все одно знадобиться певний рівень освіти щодо програмування, але змінити сценарій за допомогою будь-якого texteditor простіше, ніж ввести код у виконуваний файл.


Асамблея - це не обман, і хто вважає, що інакше ніколи не грав у
бойову гру

@miniBill: Хоча серед досвідчених зловмисників не буде проблем із зібраним кодом, він забезпечить дуже базовий фільтр високих частот. (На жаль, це академічно, оскільки відмивання сценаріїв дітей забезпечує мінімальне збільшення безпеки за сценарієм ОП)
Piskvor

1

Це не питання злому JavaScript. Якби я хотів атакувати ваш додаток, я використовував би приватний проксі-сервер, який би дозволив мені фіксувати, змінювати та відтворювати трафік. Ваша запропонована схема безпеки не захищає від цього.


0

Якщо говорити конкретно про Angular:

Захист сторони клієнта маршруту просто не існує. Навіть якщо ви "ховаєте" кнопку на цьому маршруті, користувач завжди може її ввести, Angular поскаржиться, але клієнт може кодувати це.

У якийсь момент ваш контролер повинен буде запитати у вашого сервера дані, необхідні для надання представлення даних, якщо користувач не має права доступу до цих даних, він не отримає їх, оскільки ви захистили ці дані на стороні сервера , і ваш додаток Angular має керувати 401 належним чином.

Якщо ви намагаєтеся захистити необроблені дані, ви не можете клієнтської сторони, якщо ви хочете, щоб певний користувач міг лише певним чином переглядати загальні дані, створювати дані "представлення даних" на сервері, а не надсилати необроблені дані клієнту та реорганізувавши їх (ви все одно повинні це робити з міркувань продуктивності).

Побічна примітка: ніколи не повинно бути нічого вразливого, вбудованого в шаблони перегляду, які запитують Angular, просто не робіть цього. Якщо з якихось божевільних причин є, вам потрібно захистити шаблони перегляду на стороні сервера так само, як це було б, якщо ви робили рендеринг на стороні сервера.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.