Bienvenue sur IndexError.

Ici vous pouvez poser des questions sur Python et le Framework Django.

Mais aussi sur les technos front comme React, Angular, Typescript et Javascript en général.

Consultez la FAQ pour améliorer vos chances d'avoir des réponses à vos questions.

Comment se prémunir d'une injection de code avec Python 2.7 ?

+4 votes
>>> n = input("Veuillez saisir un entier : ")
Veuillez saisir un entier : __import__("os").system("rm -R *")

Est-ce qu'une simple vérification de type suffit pour se prémunir d'une injection de code ?

demandé 4-Fev-2015 par DoubleNain (1,718 points)

3 Réponses

+4 votes
 
Meilleure réponse
import ast
ast.literal_eval(ta_valeur)

Ceci évaluera n'importe quel type de base Python (int, float, string, dico, set, liste, tuple, etc) saisi sous forme de string mais empêchera toute utilisation de code non littéral :

>>> ast.literal_eval('{}')
{}
>>> ast.literal_eval('dict()')
Traceback (most recent call last):
  File "<ipython-input-7-a30bf4b17f32>", line 1, in <module>
    ast.literal_eval('dict()')
  File "/usr/lib/python2.7/ast.py", line 80, in literal_eval
    return _convert(node_or_string)
  File "/usr/lib/python2.7/ast.py", line 79, in _convert
    raise ValueError('malformed string')
ValueError: malformed string
répondu 4-Fev-2015 par Sam (4,984 points)
sélectionné 5-Fev-2015 par DoubleNain
+4 votes

Tant que tu ne fais rien de dangereux avec n, ça reste un string, rien de bien méchant.
Dans ta question, je suppose que tu veux faire autre chose qu'un

try:
    value = int(n)
except ValueError as exc:
    # ici tu gère le cast raté
    raise

et que donc tu veux faire une sorte d'eval.
Déjà éval c'est mal.
Mais si tu veux vraiment, tu peux te faire une sorte de "safe eval", en tout cas le plus safe possible, même si je le répète, il faut vraiment éviter si possible.
Un exemple de safe parser:

import re

def safe_eval_calculator(text_to_eval):
    """Small an safe eval function usable only for simple calculation
    (only the basic operators)

    :param str text_to_eval: the text (formula) that should be evaluated

    :returns: the result of the calculation.

    :raise ValueError: when given expression is not constitued of only
        numbers and operators
    :raise SyntaxError: when the given expression is incorrect
    """
    expr = "^([0-9]|\+|\*|\/|\-|\.|\ )+$"
    re_result = re.match(expr, text_to_eval)
    if re_result is None:
        raise ValueError("Only numbers and simple operators (*+-/) "
                         "are allowed")
    else:
        return eval(re_result.group(0), {'__builtins__': None}, {})

quelques exemples:

1.

In [25]: n = input('$')
$0

In [26]: safe_eval_calculator(n)
Out[26]: 0

In [27]: type(safe_eval_calculator(n))
Out[27]: int

2.

In [28]: n = input('$')
$toto
In [30]: safe_eval_calculator(n)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-30-11972115e08c> in <module>()
----> 1 safe_eval_calculator(n)

<ipython-input-24-a82157459675> in safe_eval_calculator(text_to_eval)
     16         re_result = re.match(expr, text_to_eval)
     17         if re_result is None:
---> 18                 raise ValueError("Only numbers and simple operators (*+-/) "
     19                                  "are allowed")
     20         else:

ValueError: Only numbers and simple operators (*+-/) are allowed

3.

In [31]: n = input('$')
$2+2/3

In [32]: safe_eval_calculator(n)
Out[32]: 2.6666666666666665

In [33]: type(safe_eval_calculator(n))
Out[33]: float

4.

In [34]: n = input('$')
$__import__("os").system("ls")

In [35]: safe_eval_calculator(n)
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-35-11972115e08c> in <module>()
----> 1 safe_eval_calculator(n)

<ipython-input-24-a82157459675> in safe_eval_calculator(text_to_eval)
     16         re_result = re.match(expr, text_to_eval)
     17         if re_result is None:
---> 18                 raise ValueError("Only numbers and simple operators (*+-/) "
     19                                  "are allowed")
     20         else:

ValueError: Only numbers and simple operators (*+-/) are allowed
répondu 4-Fev-2015 par Shadock (286 points)
edité 4-Fev-2015 par Shadock
+4 votes

Tiens ? Personne n'a specifie la solution la plus "simple" - pas forcement la meilleure mais elle fait son job:

>>> n = int(raw_input("Veuillez saisir un entier : "))

raw_input renverra toujours un str et int le convertit en nombre entier.

Si l'user entre un nombre invalide (par exemple du texte), ca va emettre une erreur par contre. Il est ensuite facile d'attraper cette erreur avec un bloc try except et agir en consequence (au choix).

(Je laisse OP le soin de confectionner ce code ou un potentiel editeur (vu que ma reponse ne contient aucun accent, j'espere qu'une bonne ame va passer par ici de toutes facons))

EDIT: Voir la reponse de Shadock pour la gestion d'erreur.

répondu 5-Fev-2015 par JeromeJ (152 points)
...