J'édite un objet existant avec cette vue:

@using (Html.BeginForm("EditPat","bff"))
{
    @Html.AntiForgeryToken()
    @Html.ValidationSummary(true)
    @Html.HiddenFor(m => m.IdNumPart)
    ...more code

En fait, le champ IdNumPart n'est pas visible pour les utilisateurs courants, mais s'ils utilisent Chrome DevTools, ils peuvent modifier la valeur masquée:

<input data-val="true" data-val-number="The field IdNumPart must be a number." data-val-required="The IdNumPart field is required." id="IdNumPart" name="IdNumPart" type="hidden" value="13">

Et quand ils soumettent, cela affectera la logique de mon contrôleur, de manière à pouvoir modifier tout enregistrement modifiant le IdNumPart

[HttpPost]
public ActionResult EditPat(inspListaNoParte model)
{
    try
    {
        var oldModel = bff.inspListaNoPartes.Find(model.IdNumPart);
        bff.Entry(oldModel).State = EntityState.Modified;
        oldModel.UMC = model.UMC;
        bff.SaveChanges();
        TempData["AlertMessage"] = "Success";
    }
    catch (Exception ex)
    {
        TempData["ErrorMessage"] = "Error";
        throw;
    }
    return View();
}

Donc, je cherche un moyen de me protéger de ces problèmes.

1
Rodolfo 28 déc. 2015 à 23:28

4 réponses

Meilleure réponse

Vous pouvez utiliser des attributs pour interdire l'accès aux méthodes à certains utilisateurs

[HttpPost]
[Authorize(Roles = "Administrator,Editors")]
public ActionResult EditPat(inspListaNoParte model)
{
    try
    {
        var oldModel = bff.inspListaNoPartes.Find(model.IdNumPart);
        bff.Entry(oldModel).State = EntityState.Modified;
        oldModel.UMC = model.UMC;
        bff.SaveChanges();
        TempData["AlertMessage"] = "Success";
    }
    catch (Exception ex)
    {
        TempData["ErrorMessage"] = "Error";
        throw;
    }
    return View();
}

Ou vous pouvez vérifier si l'utilisateur est à l'intérieur du groupe en utilisant la méthode

if(User.IsInRole("Administrator"))

Et ajoutez un champ à votre table de base de données "ModifiedBy" afin que vous puissiez savoir qui était la dernière personne à avoir modifié l'enregistrement.

oldModel.LastModifiedBy= WebSecurity.CurrentUserId;

Si l'utilisateur a accès au mode d'édition pour certains produits, il suffit de vérifier si ce produit lui appartient

if(oldModel.OwnerId == WebSercurity.CurrentUserId)

J'espère que ça aide.

2
Senad Meškin 28 déc. 2015 à 21:11

Ce dilemme est commun à toutes les applications Web. Il existe quelques approches avec des compromis variables.

  • Forcer toute modification à être authentifiée (bonne pratique). Cela n'empêche pas le problème, mais au moins vous avez une trace de qui est un mauvais acteur et vous pouvez désactiver son compte. (d'autres réponses ont plus de détails à ce sujet)
  • Conservez les champs masqués dans une forme de stockage de session. L'avantage est que la seule information dans le client est l'ID de session. L'ID de session est utilisé pour ramener les informations de l'utilisateur. Vous devrez réassembler l'enregistrement vous-même et gérer la possibilité que les informations ne soient pas là parce que l'utilisateur a modifié l'identifiant de session stocké dans un cookie. REMARQUE: ViewBag et TempData sont des types spécifiques de données de session. Vous aurez besoin de quelque chose qui dure depuis l'affichage de la page d'édition jusqu'à l'action qui la gère. Je crois que TempData a été conçu dans ce but, mais revérifiez.

Il peut y avoir d'autres moyens assez compliqués impliquant la sérialisation JSON et l'obscurcissement du code, mais la meilleure chose à faire est de ne jamais faire confiance aux données provenant d'un navigateur à leur valeur nominale.

En combinant les champs masqués dans les données de session avec une interaction authentifiée, vous pouvez comparer les valeurs de champ masqué avec les valeurs de session et, si elles ne correspondent pas, marquer le compte utilisateur. Faites juste attention si vous introduisez JavaScript pour faire ces modifications vous-même.

2
Berin Loritsch 28 déc. 2015 à 20:56

La réponse simple est d'autoriser l'accès lors de l'édition, ce que vous devriez faire de toute façon.

Chaque fois que vous obtenez un POST, exécutez le même code d'autorisation que vous avez pour vous assurer que la personne est en mesure de voir l'élément. S'ils ne le font pas, 403 eux.

Il est vrai que HTTP n'est pas particulièrement "sécurisé" de cette manière, car il est sans état. Vous ne pouvez pas supposer que quelqu'un ne changera pas les choses. Pire encore, quelqu'un pourrait ouvrir cURL ou Fiddler et vous envoyer une requête directement, sans même avoir à utiliser des outils de développement.

Il est recommandé de toujours revérifier l'authentification (ce que votre framework fera probablement pour vous de toute façon) et l'autorisation pour chaque demande, que ce soit une consultation ou une modification.

Bien sûr, si vous utilisez une autorisation basée sur les rôles (comme avec l'attribut Authorize, par exemple), MVC se chargera de tout cela pour vous.

1
Matthew Haugen 28 déc. 2015 à 20:39

Une autre façon de le faire est de hacher la valeur de IdNumPart et de l'envoyer en tant que deuxième champ masqué. Vous devriez le hacher avec une sorte de clé de serveur. Lors de la publication, la valeur de hachage du deuxième champ doit correspondre à IdNumPart. Si quelqu'un modifie ne serait-ce qu'un caractère du hachage ou de l'IdNumPart, vous le saurez et vous devrez rejeter la modification. Un autre conseil serait de ne jamais prendre une suggestion de sécurité de quelqu'un sur Internet qui, du haut de sa tête, propose une solution de sécurité.

1
Zuzlx 29 déc. 2015 à 21:28