Чи повинен MVC / REST повернути 403 або 404 за ресурси, що належать іншим користувачам?


33

Працюючи з сайтом, що базується на ресурсах (наприклад, програма MVC або послуга REST), ми маємо два основні варіанти, коли клієнт намагається GETотримати ресурс, до якого він не має доступу:

  • 403 , де йдеться про те, що клієнт несанкціонований ; або
  • 404 , де йдеться про те, що ресурс не існує (або його не можна було знайти).

Здається, загальна мудрість і звичайна практика відповідати правдою - тобто 403. Але мені цікаво, чи це насправді правильно робити.

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

З точки зору конфіденційності , здається, набагато безпечніше повернути 404. Мені пригадується інцидент, коли хтось, як повідомляється, дізнався переможців реаліті-шоу (Survivor, я думаю), переглядаючи, які ресурси не існували на сайт проти того, що робили. Мене хвилює те, що 403 потенційно може передавати конфіденційну інформацію, наприклад, серійний номер або номер рахунку.

Чи є вагомі причини не повернути 404? Чи може політика 404 мати негативні побічні ефекти в інших місцях? Якщо ні, то чому практика не є більш поширеною?


1
Причинна причина не повертати 404: Якщо служба не працює або є помилка / помилка в аутентифікації, ви отримаєте 404, але клієнт / користувач / тестер / розробник / служба підтримки, яка намагається діагностувати проблему, може не мати уявлення що не так у повідомленні про помилку
Стівен Еверс

@Snorfus: Це хороший момент - я б сказав це у відповідь. Хоча Джош вже додав хороший контрапункт ...
Aaronaught

Ще один аспект, який слід пам’ятати, такий: як ставляться до 404-х нижче за течією? Чи є CDN або якесь кешування? Якщо ви хочете коли-небудь мати можливість кешувати ці дані, ви, ймовірно, не хочете, щоб ваші "користувачі не мають дозволу" 404 були кешовані.
pc1oad1etter

Відповіді:


15

Існує загальна помилкова думка (і неправильне використання), пов’язана з цим 403 Forbidden: це не повинно давати нічого про те, що сервер думає про запит. Він спеціально розроблений, щоб сказати:

Я отримую те, що ви просите, але я не збираюся обробляти цей запит, незалежно від того, що ви намагаєтеся. Тож перестаньте намагатися.

Будь-яка UA або клієнт повинні інтерпретувати це, щоб означати, що запит ніколи не спрацює, і відповісти належним чином.

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

403на відміну від того 401 Authorization Required, що не дає сервера обробляти запит до тих пір, поки ви передасте правильні облікові дані. Про це зазвичай думають люди, коли чують 403.

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

Із, 401і 404сервер нічого не каже клієнтові або UA про те, як вони повинні діяти: вони можуть продовжувати намагатись отримати іншу відповідь.

Це 404правильний спосіб обробки сторінки, яку ви не хочете показувати всім, але не хочете нічого віддавати про те, чому ви не будете показувати її в певних ситуаціях.

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

Тобто, скажімо, ваш обробник users/*. Якщо я знаю users/foo, users/barі users/baazробота, сервер повертаючи 401, 403або 404для users/quuxне означає , що я не збираюся спробувати, особливо якщо у мене є підстави вважати , що там єquux користувач. Стандартний приклад сценарію - Facebook: мій профіль приватний, але мої коментарі до публічних профілів - ні. Зловмисний клієнт знає, що я існую, навіть якщо ви повернетесь 404на сторінку мого профілю.

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


4
Хороші бали приблизно 401 проти 403. Хоча я не згоден з остаточністю ваших заяв на 404. Звичайно, на прикладі Facebook ви вже знаєте, що quuxіснує. Але зовнішні докази не завжди є, особливо на не-соціальних сайтах, де дані клієнтів дійсно приватні . Цікаве або вороже користувач може в кінцевому рахунку бути в змозі вивести , що ти брешеш, але не обов'язково , які ресурсами ви брешете про . Я думаю, що важлива точка тут насправді, не переймайтеся 404 ресурсами, якщо немає інших методів виявлення.
Aaronaught

@Aaronaught Справа в тому, що ти повинен бути справді, справді впевнений, що хтось не може зрозуміти, в чому сервер обманливий, або що не існує якогось способу виявлення, до якого ти не загартувався. Досить розумна людина буде зрозуміти це, і в той момент, код статусу НЕ має сенсу.

1
Мені все ще не зрозуміло, як достатньо розумна людина могла б це зрозуміти, якщо немає обміну даними між профілями користувачів. Я розумію, що хтось визначив, врешті-решт зрозуміє "о, 404 насправді означає, що він може існувати, але я просто не можу отримати доступ до нього" - але припускаючи, що сервер повертає ту саму помилку для ресурсів, яких справді не існує, як би скажіть різницю між неіснуючим ресурсом і привілейованим?
Aaronaught

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

8

Відповідно до RFC2616

10.4.4 403 Заборонено

Сервер зрозумів запит, але відмовляється його виконувати. Авторизація не допоможе, і запит НЕ повинен повторюватися. Якщо метод запиту не був HEAD і сервер бажає оприлюднити, чому запит не був виконаний, він ДОЛЖЕН описувати причину відмови в організації.Якщо сервер не бажає надавати цю інформацію клієнту, замість цього може використовуватися код статусу 404 (Не знайдено).

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


Я знаю RFC, хоча він мало нагадує реальність. Майже жоден сервер ніколи не пояснює причину 403 за межами цього першого речення ("Сервер зрозумів запит, але відмовляється його виконувати"), а більшість фреймворків MVC навіть мають щось подібне до того, HttpUnauthorizedResultщо призначене для використання для пільгових ресурсів . Я також усвідомлюю (очевидно), що 404 можна використовувати замість цього; моє питання полягає в тому, чи варто його використовувати чи ні , і що слід враховувати при прийнятті такого рішення.
Aaronaught

@Aaronaught: RFC не просто дозволяє вам використовувати 404, він рекомендує кинути 404, коли ви нічого не хочете визнавати.
Лі Лі Раян

3
Це добре, але коли я нічого не повинен визнати? А точніше, коли я повинен ? У цьому справді суть питання.
Aaronaught

5

Ви повинні? Так .

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

Недоліком використання 404 запитів є те, що зовні воно виглядатиме так, ніби сторінки не існує, і це може мати конфлікти у порівнянні зі сторінками, які повинні існувати, але замість цього відсутні. Якщо ви не турбуєтесь про веб-сканери (аутентифіковані системи в будь-якому випадку повністю відмовлятимуться), вам слід зовсім не робити це. Кожен API, який я обробляю несанкціонований доступ, точно так само, як і StackOverflow . Не можете бачити цю сторінку? Запевняю вас , це дійсно існує, хоча вона стверджує , що ні.

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


Причинна причина не повертати 404: Якщо служба не працює або є помилка / помилка в аутентифікації, ви отримаєте 404, але клієнт / користувач / тестер / розробник / служба підтримки, яка намагається діагностувати проблему, може не мати уявлення що не так у повідомленні про помилку

Розробники повинні мати доступ до журналів, що вказуватиме на спробу доступу до захищеного ресурсу. Клієнти / Користувачі / Тестери генерують зворотній зв'язок, який врешті-решт потрапить на розробника.

Безпека від незрозумілості ... справді?

Це не безпека через невідомість. Ви використовуєте невідомість на додаток до правильних заходів безпеки.

Дійсні запити, отримуючи "404" з іншого боку, лише додають складності та неясності там, де це не потрібно

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


Безпека від незрозумілості ... справді? Якщо хтось намагається тхнути вашими послугами зі зловмисними намірами, вони вже знають, що там є. Дійсні запити, що отримують "404" з іншого боку, лише додають складності та неясності там, де це не потрібно.
Стівен Еверс

4
@Snorfus: Тут має бути тонке розмежування між безпекою та конфіденційністю . Конфіденційність - це майже за визначенням, "невизначеність". Це особливо важливо в контексті системи, що базується на ресурсах , оскільки існування або відсутність ресурсу є потенційно важливою інформацією. Можуть бути і аргументи безпеки, хоча я з ними менше переймаюся. Я хотів би почути більше про цю додаткову складність; Ви можете розібратися в деталях поза вашим первинним коментарем? (Можливо, у більш вичерпній відповіді? Вас вкусили 404'ed 403s?)
Aaronaught

2
@Snorfus: Я також хотів би додати, як думка, що захист у глибині не є такою ж, як безпека через неясність . Останнє означає, що інших засобів захисту немає. Але додавання незрозумілості вже захищеній системі часто може бути хорошою справою - до тих пір, поки це не спричинить інших проблем в дорозі. У цьому випадку мова йде про те, що система вже захищена, оскільки 404 передаються кодом авторизації.
Aaronaught

@Aaronaught: Я опублікую більш поглиблену відповідь, але на питання: якщо ресурс приватний, то які міркування викривати його публічно?
Стівен Еверс

@Snorfus: Ресурс є приватним для клієнта - а може, і для групи - не для всього світу.
Aaronaught

0

Це дійсно залежить від інформації, наданої кодом статусу 403. Якщо у вас є кінцева точка API, що відповідає GET /myresource/{id}404, коли ресурс не існує, код статусу, який повертається кінцевою точкою, коли ресурс існує, але поточний користувач не має права, повинен залежати від передбачуваності idпараметра та суми інформації, яку вона містить сама по собі.

  • Якщо idце приватне поле, наприклад електронна адреса або номер банківського рахунку, воно, ймовірно, завжди повинно бути прихованим за номером 404. У випадку електронної адреси це може запобігти спам-ботам не складати список дійсних адрес електронної пошти, зареєстрованих на вашому веб-сайті.
  • Якщо id це загальнодоступне ім’я користувача, не турбуйтеся, є інші способи отримати доступ до цієї інформації (наприклад, просто переглянувши сторінку форуму вашого веб-сайту).
  • Якщо idце непрозорий, але передбачуваний ідентифікатор (наприклад, ціле число, що автоматично збільшується), ви не надаєте зловмиснику жодної інформації, яку він не зміг отримати іншим способом. Тому, на мою думку, безпечно повернути код статусу 403.
  • Якщо idце непрозорий і непередбачуваний ідентифікатор (як випадковий GUID), питання є більш тонким. Я особисто думаю, що немає проблеми з поверненням коду статусу 403. Цією інформацією можна скористатися, лише якщо у вашому API є інша недолікова кінцева точка, яка використовує цей ідентифікатор, але реальний недолік - Ваша інша кінцева точка.

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

Механізм безпеки не повинен бути просто швидким для нападника, інакше це просто марно. У цьому випадку це може навіть перешкодити правильному використанню інших функцій (сканери, брандмауер веб-додатків, які шукають ненормальну кількість 403 кодів стану для блокування користувачів ...).

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