web-dev-qa-db-fra.com

Renvoyer exprès le mauvais code de réponse HTTP?

J'écris une simple REST API, et je veux restreindre l'accès à mon client mobile uniquement. En d'autres termes, j'essaie d'empêcher un utilisateur malveillant d'utiliser par exemple curl pour faire une demande non autorisée POST.

Bien sûr, c'est impossible. Cependant, il existe certaines contre-mesures qui empêchent un pirate de réussir. En ce moment, je crypte toutes les demandes avec une clé privée, stockée côté client (évidemment, ce n'est pas idéal, mais la difficulté de rétro-ingénierie d'une application iOS dissuadera, espérons-le, tous les pirates, sauf les plus déterminés).

Une idée simple que j'ai eue est de renvoyer le mauvais code de réponse HTTP pour une demande non autorisée. Plutôt que de renvoyer un "401 non autorisé", pourquoi ne pas retourner par exemple "305 Use Proxy", c'est-à-dire délibérément déroutant. Quelqu'un a-t-il déjà pensé à faire cela?

36
Miles Luders

Quelqu'un a-t-il déjà pensé à faire cela?

Oui, il y avait en fait une discussion à ce sujet au defcon 21 ( vidéo , slides ).

Leur conclusion était que travailler avec des codes de réponse comme sécurité offensive peut parfois entraîner un ralentissement sévère des scanners automatiques, des scanners qui ne fonctionnent pas et une quantité massive de faux positifs ou de faux négatifs (cela fera évidemment peu ou rien pour les scans manuels) .

Bien que la sécurité par obscurité ne devrait jamais être votre seule défense, elle peut être utile comme défense en profondeur (autre exemple: il est recommandé de ne pas diffuser les numéros de version de tous les composants utilisés).

D'un autre côté, une API REST doit être aussi propre que possible, et répondre avec des codes HTTP délibérément incorrects peut être source de confusion pour les développeurs et les clients légitimes (c'est un peu moins un problème pour les navigateurs , où les utilisateurs ne voient pas réellement les codes). Pour cette raison, je ne le recommanderais pas dans votre cas, mais c'est toujours une idée intéressante.

83
tim

Cela ne ralentira pas vraiment un attaquant, mais cela ennuiera vraiment les futurs développeurs qui travaillent sur votre plate-forme. Il se peut également que certaines fonctionnalités Nice de vos bibliothèques de requêtes HTTP ne soient pas aussi agréables, car elles fonctionnent à partir d'informations incorrectes.

C'est une forme très faible de la sécurité par l'obscurité . Lorsque vous concevez un système comme celui-ci, vous devriez penser à ralentir un attaquant de centaines d'années, pas de dizaines de minutes - sinon vous allez toujours perdre.

Plutôt que de renvoyer un "401 non autorisé", pourquoi ne pas retourner par exemple "305 Use Proxy", c'est-à-dire délibérément déroutant.

Oui, cela confondra un attaquant. Mais pour un entraîneur, ce ne sera peut-être pas plus de deux secondes à plat. Et les codes d'état ne sont pas du tout utiles, principalement uniquement lors du forçage brutal des noms de fichiers.

Supposons que j'ai une clé valide et que je puisse vous observer renvoyer des codes de plage 200 pour mon authentification. Si je change un peu ma clé, et pour chaque demande que vous retourniez soit 305s, je penserai immédiatement "Hmm. On dirait que le développeur a peut-être foiré". Si vous retournez des codes aléatoires, je saurai que c'était exprès et je les ignore simplement.

la difficulté de l'ingénierie inverse d'une application iOS dissuadera, espérons-le, tous les pirates, sauf les plus déterminés

Oui, mais comme il n'en faut qu'un pour le publier, cela ralentit encore une fois ..

9
J.A.K.

C'est la sécurité par l'obscurité, c'est-à-dire qu'elle n'apporte pas beaucoup de sécurité. La solution que vous proposez ne fera que ralentir un attaquant, pas l'empêcher d'utiliser son propre client. En fait, votre méthode de chiffrement des demandes, en fonction de votre implémentation, peut en fait rendre votre application moins sécurisée en ouvrant des attaques contre d'autres parties du système de chiffrement. Il serait préférable de consacrer vos efforts à essayer de sécuriser les fonctions de l'API elles-mêmes (c'est-à-dire de les tester et de les protéger contre les attaques telles que l'injection SQL), plutôt que d'essayer d'empêcher les clients non autorisés d'y accéder.

6
Dan Landberg

Mais l'utilisateur IS utilise déjà votre protocole.

Votre problème est que l'interface de votre serveur de ce que l'utilisateur peut faire n'est pas sécurisée!
Vous décidez quelles données votre serveur envoie à qui!
(Bonjour, chers journaux en ligne. Oui, je vous regarde!)

Concevez-le, en supposant que l'utilisateur est le client. Pas votre code. Parce qu'il l'est. Peu importe le client utilisé.
Votre application fonctionne sur un processeur qui est sous le contrôle matériel de l'utilisateur. Votre code n'est qu'une liste de commandes/données, et l'utilisateur et son processeur peuvent le traiter comme bon leur semble. Y compris pas le traiter.
Il décide de ce que fait son processeur. Ne confondez pas sa grâce d'accepter votre code d'application tel quel pour un droit à une exécution aveugle. Vous êtes celui à qui vous faites confiance ici, et cette confiance est très éphémère.
Surtout avec des tactiques louches comme celle-ci.

Dans tous les cas: vous remettez à l'utilisateur la clé de chiffrement et tout, et attendez-vous à ce qu'il ne l'utilise pas lui-même, car vous la mettez quelque part dans votre panier de code. … Tout comme DRM, c'est de l'huile de serpent et ça ne marchera jamais.
Il suffit d'une personne pour trouver où mettre la clé. (Ce serait moi, par exemple.) Tout le monde n'a qu'à google pour ça.

Mais je suis surpris que vous ne pensiez qu'à chiffrer le protocole contre l'utilisateur, au lieu de le protéger contre les attaques de l'homme du milieu.
En supposant la raison pour laquelle cela est généralement fait (Oui, je vous parle à nouveau de "l'industrie du contenu".): Si votre utilisateur est votre ennemi, vous devriez peut-être chercher un modèle commercial basé sur l'équité et un gagnant-gagnant, au lieu d'arracher l'utilisateur et d'avoir à faire face à un jeu.

P.S .: Ignorez toutes les réponses "la sécurité par l'obscurité". Il s'agit d'une erreur qui se traduit par un comportement correct, mais est toujours basée sur des hypothèses invalides. L'utiliser comme argument est, au mieux, amateur et pas vraiment compétent.
En réalité, toute la sécurité passe par l'obscurité. Certains sont juste plus obscurs (= mieux déguisés). La vraie raison pour laquelle cela est mauvais, c'est parce que ce que nous appelons la sécurité réelle est un bazillion fois plus obscur, ce qui lui donne un obscurité réelle (statistique) fiable, par opposition à une obscurité très simple qui est tout simplement trop probable pour que quelqu'un vienne de rien.

4
Evi1M4chine

Comme d'autres l'ont déjà expliqué, la sécurité par l'obscurité ralentit au mieux un attaquant.

Dans votre cas particulier, je dirais que cela n'aura aucun effet appréciable. Pour arriver à ce point, votre attaquant a déjà dû procéder au reverse engineering de votre application et extraire la clé privée. Cela signifie que votre agresseur n'est pas un idiot et sait ce qu'il fait. Un peu d'obscurité lui coûtera moins de temps qu'il n'en faut pour le mettre en œuvre.

3
Tom

Comme d'autres l'ont déjà mentionné, vous proposez d'utiliser Security by Obscurity. Bien que cette technique ait son but, tenez compte des éléments suivants avant de choisir d'adopter cette approche:

  • Fournir un support technique pour votre API. L'utilisation de codes de réponse HTTP trompeurs complique la tâche de toute personne autre que vous. Ils doivent déterminer si la situation particulière envoie réellement le bon code de réponse ou s'il en envoie un obscur. Si vous décidez de rester le seul contact pour toute demande d'assistance, cela ne devrait pas être un problème.
  • Qu'est-ce qu'un "utilisateur malveillant"? Soyez prudent lorsque vous catégorisez une demande comme malveillante car elle peut avoir des effets négatifs. Supposons qu'une adresse IP soit déterminée pour envoyer du trafic malveillant et que des contre-mesures soient utilisées. Supposons maintenant que la même IP soit en fait un proxy avec des centaines ou des milliers d'utilisateurs derrière. Vous avez maintenant appliqué votre contre-mesure à chacun d'eux. Ce même principe peut être appliqué à l'identification d'une activité malveillante dans les en-têtes et/ou le corps.
  • Le code d'application est le plus lent. La requête doit traverser toute la pile pour finalement accéder à la logique de "sécurité". Cette architecture ne s'adapte pas bien et est lente. Les requêtes incorrectes doivent être arrêtées le plus tôt possible, ce qui est le principe de l'utilisation des pare-feu d'application Web (WAF).
  • Extension de l'accès. Si votre API devient accessible à davantage de clients alors qu'elle a été conçue à l'origine, ces nouveaux clients devront être conscients de l'utilisation possible de codes de réponse HTTP trompeurs.
  • Utilisateurs malveillants persistants. Comme d'autres l'ont mentionné, cette technique n'est qu'un ralentisseur.

Meilleure approche

Concentrez votre temps sur l'inscription sur liste blanche de toutes les bonnes demandes connues. C'est tellement plus facile que d'essayer d'identifier toutes les mauvaises requêtes potentielles. Tout ce qui ne figure pas sur la liste blanche devrait immédiatement obtenir un code de réponse approprié tel que HTTP 400 ou HTTP 405 si vous filtrez sur des verbes HTTP (comme exemples). De préférence, cela se produit avant que la demande ne frappe votre code d'application.

En plus de la liste blanche des demandes autorisées, assurez-vous que votre application est sécurisée en fonction de OWASP Guidelines . Vous obtiendrez de bien meilleurs résultats en passant votre temps avec OWASP, puis vous essayerez de déterminer ce qu'est un utilisateur malveillant et retournerez un code de réponse HTTP obscur.

1
user2320464

Je ne ferais pas ça. Cela signifie généralement que vous créez votre propre norme, ce qui provoque:

  1. votre API pour être prédictif après avoir fait une carte de vos réponses http à leur signification réelle. Changer les réponses HTTP pourrait fonctionner sur certains "hackers" qui abandonneraient après quelques tentatives, mais pas sur d'autres, plus déterminés. Voulez-vous protéger votre API des anciens types uniquement, c'est-à-dire des enfants de 11 ans? Je ne pense pas.

  2. une certaine confusion pour les développeurs et probablement les testeurs, en particulier ceux qui sont habitués à fonctionner selon les normes mondiales.

  3. Choisissez une autre façon. Il y en a certainement quelques-uns. Je me bats avec le même headcratcher depuis quelques semaines ces derniers temps et j'ai trouvé au moins 2 moyens plus ou moins fiables pour atteindre les restrictions souhaitées [je ne peux pas les poster ici cependant].

Il y a certainement de meilleures façons BEAUCOUP plus efficaces d'obtenir ce que vous voulez. Essayez de regarder votre API sous un angle différent ... Si vous étiez un pirate informatique et que votre vie dépendait du piratage de cette API - que feriez-vous pour réussir? Que devrait-il arriver pour que vous soyez frustré dans vos tentatives de le briser?

1
netikras

Fondamentalement, vous NE POUVEZ PAS empêcher des clients non autorisés d'envoyer des demandes. La chose la plus proche possible serait de faire effectuer une sorte de vérification cryptographique chez le client, mais comme l'a dit Sherlock Holmes, "ce que l'on peut inventer, un autre peut le découvrir". (Je le sais avec certitude, car j'ai à plusieurs reprises mis en cause la sécurité côté client des utilisateurs.)

Au lieu de cela, créez votre API de sorte que n'importe qui soit soit autorisé à l'utiliser à l'aide de clients personnalisés. Rendez-le convivial. Que perdez-vous par là? Les attaquants attaqueront quoi que vous fassiez, et si vous rendez votre API facile à utiliser, quelqu'un trouvera quelque chose à quoi vous n'avez jamais pensé et rendra votre serveur encore plus grand que vous ne l'auriez jamais imaginé. Que pourrait faire un client qui parle à la fois à votre API et à une autre? Quelles sont les innombrables possibilités et cela vous fera-t-il vraiment du mal de les autoriser?

1
rosuav

Une bonne raison de ne pas le faire, en particulier pour une application mobile, est qu'il est très probable que votre application parle déjà à votre serveur via plusieurs proxy, par exemple dans la compagnie de téléphone, déjà. La plupart des grandes entreprises utilisent des proxys sur leur réseau pour essayer de protéger leurs systèmes contre les contenus malveillants, et de nombreuses compagnies de téléphone réduisent la qualité des vidéos ou des images en transit. Cela rendra également inutile l'utilisation des différentes bibliothèques système pour HTTP sur votre plate-forme. Une approche couramment utilisée consiste à dériver une clé ou un jeton à partir d'informations que l'utilisateur ne voudra probablement pas partager, telles que le hachage de son adresse de nom et des détails de sa carte de crédit. De cette façon, même si votre application est piratée, les gens se méfieront de donner les informations requises à un programme aléatoire qu'ils ont téléchargé, ce qui limite la capacité de partage de toute attaque éprouvée.

0
james

Ce n'est généralement pas une bonne idée.

J'en ai fait un usage très ciblé une fois à bon escient lorsque le site Web d'un client était utilisé par un réseau de blanchiment de cartes de crédit volé. Il y avait des caractéristiques d'identification partagées uniquement par les transactions frauduleuses, donc plutôt que de les refuser poliment, je demanderais au site de retarder la réponse de quelques minutes (personne n'aime un site Web qui prend quelques minutes pour faire quelque chose), puis de retourner un 500 avec le site. message standard "désolé, ce n'est pas vous, c'est moi" pour les erreurs de serveur (il a également consigné les détails à transmettre aux forces de l'ordre). Nous avons eu trois tentatives de transactions qui ont obtenu cette réponse de jeu d'opportunum et nous n'avons plus jamais entendu parler d'eux.

C'était pourtant:

  1. En réponse à quelque chose que nous savions être une attaque plutôt que d'être désagréable pour les utilisateurs ayant un problème.
  2. Pas une défense contre une attaque contre la sécurité du protocole lui-même, mais au niveau humain au-dessus.
  3. Explicable à travers d'autres explications, c'est-à-dire que nous faisions semblant d'avoir un site Web vraiment nul dans une situation où cela était plausible (il y a beaucoup de sites Web excitants là-bas) et nous n'étions pas une cible spécifique (les avantages sociaux passeraient à quelqu'un d'autre ).

Les utilisateurs ayant un problème doivent être aidés, pas maltraités. "Je ne peux pas faire ça parce que vous n'êtes pas correctement autorisé" refuse de faire quelque chose de manière utile. "Je ne peux pas faire ça parce que vous devez utiliser un proxy" quand quelqu'un n'a pas besoin d'utiliser un proxy est abusif. Être délibérément inutile n'est approprié que lorsque vous savez que vous êtes attaqué et que cela ne devrait pas ressembler à un message manifestement faux ou que vous n'avez rien caché (potentiellement vous avez réellement révélé quelque chose si le même statut faux n'est pas utilisé pour chaque erreur client).

Cela dit, il est approprié de prendre des mesures pour que les statuts ne fuient pas les informations. Par exemple. il est acceptable (décrit comme tel dans les normes) pour /admin/ à 404 mais 200 dans un autre cas (utilisateur autorisé, adresses IP client autorisées, etc.) Alternativement si /members/my-profile 200 pour un utilisateur autorisé et 403 ou 401 dans le cas contraire, alors si /members/fdsasafdasfwefaxc serait 404 pour un utilisateur autorisé, c'est une bonne idée qu'il soit 403 ou 401 pour l'utilisateur non autorisé. Il ne s'agit pas tant de sécurité par obscurité que de considérer quels URI se rapportent aux ressources pour être l'un des bits d'information qui est protégé.

0
Jon Hanna