Як захистити виклики REST API?


92

Я розробляю спокійний веб-додаток, який використовує популярний веб-фреймворк, наприклад, (rails, sinatra, flask, express.js). В ідеалі я хочу розробити сторону клієнта за допомогою Backbone.js. Як дозволити лише моїй стороні клієнта javascript взаємодіяти з цими викликами API? Я не хочу, щоб ці виклики API були загальнодоступними та викликалися ними curlабо просто вводячи посилання в браузері.


Чи всі ваші виклики API вимагають маркера, який передається клієнту під час обслуговування вашої сторінки?
hajpoj


JavaScript AWS для SDK Java
rjha94,

Відповіді:


91

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

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

  • Я впевнений, що ваш API має якесь поле автентифікації (наприклад, хеш, обчислений на клієнті). Якщо ні, погляньте на це ТАКЕ питання . Переконайтеся, що ви використовуєте сіль (або навіть ключ API), який надається вашому клієнту JS на основі сеансу (дуже жорстко закодований). Таким чином, несанкціонований споживач вашого API змушений набагато більше працювати.

  • Завантажуючи клієнт JS, пам’ятайте деякі заголовки HTTP (на думку спадає агент користувача) та IP-адресу та просіть про повторну автентифікацію, якщо вони змінюються, використовуючи чорні списки для звичайних підозрюваних. Це змушує зловмисника знову більш ретельно виконувати домашнє завдання.

  • На стороні сервера пам’ятайте кілька останніх викликів API, і перед тим, як дозволити інший, перевірте, чи дозволяє бізнес-логіка новий зараз: це позбавляє зловмисника можливості сконцентрувати багато своїх сеансів в одному сеансі з вашим сервером: у поєднанні з іншими заходами це зробить кривдника легко виявити.

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


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

@Thepyramid Неважливо, що робить виклик API на стороні сервера, особливо якщо сторона сервера робить ще один виклик API другого рівня. Найважливіша частина - ставитись до свого сервера не як до проксі, а як до програми.
Євген Рік,

Ви можете пояснити більше, як зробити додаток не таким, як проксі
Піраміда

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

1
@PirateApp Зловмисник може просто ігнорувати заголовки CSRF. Вони працюють лише в тому випадку, якщо кінцевий пристрій є
невідпакованим

12

Вам слід застосувати якусь систему автентифікації. Хороший спосіб вирішити це - визначити деякі очікувані змінні заголовка. Наприклад, ви можете мати виклик API auth / login, який повертає маркер сеансу. Подальші виклики вашого API очікують, що маркер сеансу буде встановлено у змінну заголовка HTTP із певним ім’ям, наприклад, `` your-api-token ''.

Багато систем також створюють очікувані маркери доступу або ключі (наприклад, YouTube, Facebook або Twitter), використовуючи якусь систему облікових записів API. У цих випадках ваш клієнт повинен буде зберігати їх якимось чином у клієнта.

Тоді справа лише в тому, щоб додати чек на сеанс у ваш фреймворк REST і викинути виняток. Якщо це можливо, код стану (щоб бути спокійним) буде помилкою 401.


8
Хоча ніщо не заважає їм дивитись на заголовки та відтворювати їх.
cdmckay

1
@cdmckay - маркер повинен відповідати маркеру, що зберігається в сеансі. Просто відтворення заголовка призведе до "Несанкціонованої" відповіді, якщо вона надходить з іншого сеансу.
Андрій Волгін

3
Вони все ще можуть використовувати той самий сеанс і змінювати запити перед тим, як їх надсилати в API, хоча ... або навіть за допомогою консолі під час виконання генерувати виклик із відповідними заголовками / полями, змінюючи лише ті частини, які вам потрібні ...
Potter Rafed

2
@PotterRafed: Якщо користувач отримує доступ до власного дійсного сеансу, це викликається за допомогою програми, а не атакує її. Метою автентифікації є запобігання доступу до сеансів / даних інших користувачів .
Андрій Волгін,

@AndreiVolgin так, досить справедливо, але це все одно вразливість
Поттер Рафід

9

Існує відкритий стандарт, який зараз називається "Веб-маркер JSON",

див. https://jwt.io/ & https://en.wikipedia.org/wiki/JSON_Web_Token

Веб-маркер JSON (JWT) - це відкритий стандарт на основі JSON (RFC 7519) для створення токенів, які заявляють певну кількість заявок. Наприклад, сервер може генерувати маркер, який має твердження "зареєстрований як адміністратор", і надати його клієнту. Потім клієнт може використовувати цей маркер, щоб довести, що він увійшов як адміністратор. Маркери підписуються ключем сервера, тому сервер може перевірити, що маркер легітимний. Маркери розроблені для компактності, безпечності URL-адрес та використання, особливо в контексті єдиного входу веб-браузера (SSO). Претензії JWT зазвичай можуть використовуватися для передачі ідентифікації автентифікованих користувачів між постачальником ідентифікації та постачальником послуг, або будь-яким іншим типом заявок, як вимагають бізнес-процеси. [1] [2] Маркери також можуть бути автентифіковані та зашифровані. [3] [4]


Що завадить користувачеві скопіювати свій маркер і використовувати його в будь-якій іншій відповіді?
Улад Касах

1
@UladKasach, чесно кажучи, я ніколи не заглиблювався в них глибоко, але, натомість, вони є доступними, унікальними для вашого користувача та зашифрованими за допомогою SSL (що ви, звичайно, практикуєте), це абсолютно та сама ідея, що стоїть за oauth afaik
bbozo

3

Вибачте @MarkAmery та Eugene, але це неправильно.

Ваш додаток js + html (клієнт), що працює в браузері, МОЖЕ бути налаштований для виключення несанкціонованих прямих викликів до API наступним чином:

  1. Перший крок: Налаштуйте API на вимогу автентифікації. Клієнт повинен спочатку ідентифікувати себе через сервер (або який - або інший сервер безпеки) , наприклад , з проханням людини користувача надати правильний пароль.

Перед аутентифікацією дзвінки до API не приймаються.

Під час автентифікації повертається "маркер".

Після автентифікації приймаються лише виклики API із аутентифікацією "маркер".

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

  1. Другий крок: Налаштуйте додатковий API захисту, який потрібно викликати протягом короткого часу після того, як клієнтська програма js + html була спочатку запитана на сервері. Цей "зворотний дзвінок" повідомляє серверу, що клієнт успішно завантажений. Обмежте свої виклики API REST лише тоді, коли клієнт був нещодавно та успішно запитаний.

Тепер, щоб використовувати ваш API, вони повинні спочатку завантажити клієнт і фактично запустити його у браузері. Лише після успішного отримання зворотного виклику, а потім введення користувачем протягом короткого періоду часу, API прийматиме виклики.

Тому вам не доведеться турбуватися про те, що це може бути неавторизований користувач без облікових даних.

(Заголовок запитання: "Як я можу захистити виклики REST API", і з більшості того, що ви говорите, це ваше головне занепокоєння, а не буквальне питання про те, ЯК називається ваш API, а швидше, КОМУ, правильно? )


5
Другий пункт не має сенсу. Якщо зловмиснику потрібно завантажити вашу програму, він зробить це (ваш зворотний дзвінок видно). А потім атакувати.
Андрій Волгін

Пункт 2 доповнює пункт 1. Зловмиснику все ще потрібна автентифікація. Пункт 2 лише додає до цього необхідність фактично завантажити програму html, щоб отримати авторизацію. Отже, виклик безпосередньо до API без програми (мабуть, доступний і завантажений лише після автентифікації) неможливий. Що і було запитано у цьому питанні.
пашуте

Ви можете просто дозволити запити лише з вашого домену.
Андрій Волгін

Це обмежує лише виклики всередині домену, тому тепер користувачі браузера-програми javascript повинні знаходитися всередині домену (мабуть, це не те, що хоче knd), і ці користувачі все ще можуть викликати API безпосередньо через curl.
пашуте

2
Ви, мабуть, не помічаєте, що ЩОБ Ви не попросили браузер вашого користувача, зловмисник може відтворити - щоб браузер це зробив, він повинен бути читабельним.
Eugen Rieck

1
  1. Встановіть змінну SESSION на сервері, коли клієнт вперше завантажує ваш index.html(або backbone.jsін.)

  2. Перевіряйте цю змінну на стороні сервера під час кожного виклику API.

PS це не "безпечне" рішення !!! Це лише для того, щоб полегшити навантаження на ваш сервер, щоб люди не зловживали ним або не "гарячим посиланням" ваш API з інших веб-сайтів та додатків.


0

Ось що я роблю:

  1. Захистіть API за допомогою заголовка HTTP із такими дзвінками, як X-APITOKEN:

  2. Використовуйте змінні сеансу в PHP. Створіть систему входу та збережіть маркер користувача у змінних сеансу.

  3. Викличте код JS з Ajax до PHP і використовуйте змінну сеансу з curl для виклику API. Таким чином, якщо змінна сеансу не встановлена, вона не буде викликати, а PHP-код містить маркер доступу до API.

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