7
votes

Sécurité de la «eval» de Python pour la désérialisation de la liste

Y a-t-il des exploits de sécurité qui pourrait se produire dans ce scénario: xxx pré>

insanitudisé_user_input code> est un objet STR. La chaîne est générée par l'utilisateur et pourrait être méchant. En supposant que notre réseau Web ne nous ait pas manqué, c'est une réelle instance honnête à Dieu str des cométine de Python. P>

Si cela est dangereux, pouvons-nous faire quelque chose à l'entrée pour la rendre en sécurité?

nous ne veut pas em> vouloir exécuter quoi que ce soit contenu dans la chaîne. p>

Voir aussi: p>


8 commentaires

"La raison de faire cela ferait beaucoup plus de sens si j'ai présenté le contexte plus large" Pourriez-vous s'il vous plaît élaborer sur le problème? Actuellement, la commande semble totalement inutile - la même chose que de ne rien faire avec nonanitisé_user_input ..


"Nous avons des milliers de ceux-ci" Cela n'a aucun sens. Pourquoi voudriez-vous stocker l'entrée de cette façon? Il n'y a pas de point dans REC () une chaîne à des fins de stockage.


Pourquoi n'utilisez-vous pas de cornichon ou quelque chose de plus simple?


cornichon est plus qu'un ordre de grandeur plus lent et pas nécessairement plus sûr, si les documents doivent être croyés


Moi aussi, je suis curieux pourquoi les données sont en train d'être reprémées en premier lieu.


Les données sont reproduites pour modifier la structure de la liste imbriquée en une chaîne, de sorte qu'il peut être compressé et stocké dans une propriété blob.


Demander la question évidente, la sérialisation / la désémarification est-elle vraiment un goulot d'étranglement ou êtes-vous en train de participer à une optimisation prématurée?


Bonne observation nick, c'est pas un goulot d'étranglement avec le nombre actuel d'utilisateurs de l'application et l'utilisation actuelle actuelle de la CPU est très faible, mais après quelques problèmes de charge avec mon application précédente, j'ai testé avec 1000 utilisateurs et malheureusement, la sérialisation devient tout à fait le goulot d'étranglement à ce moment-là. Cependant, il ne peut jamais y avoir que beaucoup de vrais utilisateurs, c'est toujours un jeu de devinettes


5 Réponses :


19
votes

C'est vraiment dangereux et l'alternative la plus sûre est ast.literal_eval (voir le ast module dans la bibliothèque standard). Vous pouvez bien sûr construire et altérer un ast pour fournir par exemple. Évaluation des variables et similaires avant d'évaluer l'AST résultant (quand il est à la baisse des littéraux).

L'exploit possible de eval commence par n'importe quel objet, il peut obtenir ses mains sur (dire vrai ici) et aller via .__ class_ sur son objet de type, etc. Pour Objet , obtient ensuite ses sous-classes ... Fondamentalement, il peut accéder à n'importe quel type d'objet et épave Havoc. Je peux être plus précis, mais je préférerais ne pas le faire dans un forum public (l'exploit est bien connu, mais compte tenu du nombre de personnes l'ignorant, ce qui l'a révélé aux enfants de script de Wannabe pourraient faire pire des choses ... juste éviter Eval sur la saisie de l'utilisateur insanitué et vivez heureux pour toujours! -).


0 commentaires

3
votes

Généralement, vous ne devez jamais autoriser quiconque à poster du code.

Les "programmeurs professionnels payants" ont un code d'écriture suffisamment difficile qui fonctionne réellement.

Accepter le code du public anonyme - sans avantage de la QA formelle - est le pire de tous les scénarios possibles.

Programmeurs professionnels - Sans bonne et solide Formel QA - fera un hasch de presque n'importe quel site Web. En effet, je suis inverse en génie un peu de code incroyablement mauvais des professionnels rémunérés.

L'idée de permettre à un code non professionnel - non-encombré par le code postal est vraiment terrifiant.


0 commentaires

8
votes

Si vous pouvez prouver au-delà du doute que insanitudisé_user_input est une instance STR à partir des intégrés de python sans altéré, cela est toujours sûr. En fait, ce sera en sécurité même sans tous ces arguments supplémentaires depuis eval (REC (REC (AR)) = AR pour tous ces objets à chaîne. Vous mettez dans une chaîne, vous récupérez une chaîne. Tout ce que vous avez fait était de l'évasion et de l'insessape.

Tout cela me conduit à penser que eval (REC (REC (X)) n'est pas ce que vous voulez - aucun code ne sera jamais exécuté à moins que quelqu'un ne vous donne un insanitudisé_user_input Objet qui ressemble à une chaîne mais n'est pas, mais c'est une question différente - à moins que vous n'essayez de copier une instance de chaîne de la manière la plus lente possible: d.


1 commentaires

C'est exactement juste; Je ne veux vraiment rien que rien dans la chaîne soit exécuté. La raison de faire cela rendrait beaucoup plus de sens si j'ai présenté le contexte plus large, mais j'ai essayé de simplifier le scénario de la question.



5
votes

Avec tout ce que vous décrivez, il est techniquement sûr pour évaluer les chaînes à reproduire, mais j'éviterais de le faire quand même pour demander des problèmes:

  • Il pourrait y avoir un cas étrange d'angle d'étrange où votre hypothèse qui ne reprogeait que des chaînes est stockée (par exemple, un bogue / une voie différente dans le stockage qui ne reproche pas instantanément une injection de code exploitant autrement inexploitable)

  • Même si tout va bien maintenant, les hypothèses peuvent changer à un moment donné, et des données insanitaires peuvent être stockées dans ce domaine par une personne ignorante du code eval.

  • Votre code peut être réutilisé (ou pire, copier + collé) dans une situation que vous n'avez pas considérée.

    comme Alex Martelli a souligné, à Python2. 6 et plus, il y a ast.literal_eval qui gérera en toute sécurité les chaînes et d'autres types de données simples comme des tuples. C'est probablement la solution la plus sûre et la plus complète.

    Une autre possibilité est toutefois d'utiliser le codec String-SCASS . Ceci est beaucoup plus rapide que Eval (environ 10 fois en fonction du TimeIt), disponible dans les versions antérieures que littéral_eval, et devrait faire ce que vous voulez: xxx

    (le [1: 1] est de dépouiller les citations extérieures REC ajoute.)


0 commentaires

1
votes
repr([unsanitized_user_input_1,
      unsanitized_user_input_2,
      ...

1 commentaires

Une des raisons est que les chaînes doivent être comprimées pour s'adapter à la limite d'entité de 1 Mo de 1 Mo du moteur de l'App, et je pensais que les frais généraux de compresser individuellement les 1 000 secondes seraient probablement beaucoup plus élevés que les sérialisés, les compressant tous ensemble et les mettre dans une blob. . Les économies d'espace seront probablement moins. Mais c'est un bon point ... Je cherche définitivement des moyens d'éviter les évaluations sans augmenter la course à pied.