2010-06-08 5 views
7

Ce n'est vraiment qu'une question conceptuelle pour moi à ce stade.Sécurité/validation des données Lisp

En Lisp, les programmes sont des données et les données sont des programmes. Le REPL fait exactement cela - lit puis évalue.

Alors, comment peut-on obtenir des informations de l'utilisateur de manière sécurisée? Evidemment c'est possible - je veux dire viaweb - maintenant Yahoo! Stores est assez sécurisé, alors comment ça se fait?

Répondre

16

Le REPL signifie Read Eval Print Loop.

(loop (print (eval (read)))) 

Au-dessus est seulement conceptuelle, le vrai code de REPL est beaucoup plus compliqué (avec gestion des erreurs, débogage, ...).

Vous pouvez lire toutes sortes de données dans Lisp sans les évaluer. L'évaluation est une étape distincte - indépendante de la lecture des données.

Il existe toutes sortes de fonctions d'E/S dans Lisp. La plus complexe des fonctions fournies est généralement READ, qui lit les s-expressions. Il existe une option dans Common Lisp qui permet une évaluation pendant READ, mais qui peut et doit être désactivée lors de la lecture des données. Donc, les données dans Lisp ne sont pas nécessairement un programme et même si les données sont un programme, alors Lisp peut lire le programme sous forme de données - sans évaluation. Un REPL ne doit être utilisé que par un développeur et ne doit pas être exposé à des utilisateurs arbitraires. Pour obtenir des données auprès des utilisateurs, on utilise les fonctions IO normales, y compris des fonctions telles que READ, qui peuvent lire des expressions S, mais ne les évaluent pas.

Voici quelques choses que l'on ne devrait pas faire:

  • utilisation READ pour lire des données arbitraires. LIRE pour des exemples permet de lire des données vraiment importantes - il n'y a pas de limite.

  • évaluer pendant READ ('read eval'). Cela devrait être désactivé.

  • symboles de lecture de E/S et d'appeler leurs fonctions de symbole

  • lire des structures de données cycliques avec READ, lorsque vos fonctions attendent des listes simples. Marcher sur une liste cyclique peut garder votre programme occupé pendant un certain temps.

  • ne gère pas les erreurs de syntaxe pendant la lecture des données.

+0

+1 bonne réponse. – rook

2

C'est une question qui tue et j'ai pensé la même chose quand je lisais sur Lisp. Bien que je n'ai rien fait de significatif dans LISP, ma réponse est très limitée. Je peux vous dire que eval()is nasty. Il y a un dicton que j'aime "Si eval est la réponse alors vous posez la mauvaise question." --Inconnu.

Si l'attaquant peut contrôler des données qui sont ensuite évaluées, vous avez une très sérieuse vulnérabilité d'exécution de code à distance. Ceci peut être atténué, et je vais vous montrer un exemple avec PHP, parce que c'est ce que je sais:

$id=addslashes($_GET['id']); 
eval('$test="$id";'); 

Si vous faites pas un ajout des barres obliques alors un attaquant pourrait obtenir l'exécution de code à distance en faisant cela :

http://localhost?evil_eval.php?id="; phpinfo();/* 

Mais les barres obliques add tourneront le " en \", gardant ainsi l'attaquant de « sortir » des « données » et d'être en mesure d'exécuter du code. Ce qui est très similaire à l'injection de sql.

+0

+1 pour le devis. Cela s'applique probablement à la plupart des langues. Et bien sûr, chaque fois que j'utilise php, l'entrée est toujours enveloppée dans un htmlspecialchars() –

6

Vous le faites comme tout le monde le fait. Vous lisez une chaîne de données du flux, vous l'analysez pour vos commandes et paramètres, vous validez les commandes et les paramètres, et vous interprétez les commandes et les paramètres.

Il n'y a pas de magie ici. En d'autres termes, ce que vous NE FAITES PAS, vous n'exposez pas votre port d'écoute Lisp à une source de données non validée et non sécurisée. Comme cela a été mentionné, le REPL est l'impression en lecture-à-la-page. @The Rook se concentre sur eval (avec raison), mais n'écartons pas READ. READ est une commande très puissante dans Common Lisp. Le lecteur peut évaluer le code par lui-même, avant même d'avoir à "évaluer".

N'exposez PAS READ à quoi que ce soit en qui vous n'avez pas confiance.

Avec assez de travail, vous pourriez faire un paquet personnalisé, limiter la portée des fonctions disponibles sur ce paquet, etc. etc. Mais je pense que c'est plus de travail que d'écrire simplement un simple analyseur de commandes sans me soucier des effets secondaires que j'ai raté.

+0

C'est exactement là où mon inquiétude est - que le lecteur peut évaluer le code. Y at-il un type d'équivalent à Python 2.6 'raw_input()'? –

+1

http://www.lispworks.com/documentation/HyperSpec/Body/f_rd_lin.htm – Ken

0

J'ai trouvé cette question quitte à controverse. L'évaluation n'évaluera pas votre entrée à moins que vous ne le demandiez explicitement. Je veux dire que votre entrée ne sera pas traitée comme un code LISP mais plutôt comme une chaîne.

Ce n'est pas parce que votre langage a un concept puissant comme l'eval qu'il n'est pas "sûr".

Je pense que la confusion provient de SQL où vous traitez réellement une entrée comme une [partie de] SQL.

(query (concatenate 'string "SELECT * FROM foo WHERE id = " input-id)) 

Ici, l'identifiant d'entrée est en cours d'évaluation par le moteur SQL. C'est parce que vous n'avez pas de bonne façon d'écrire du SQL, ou autre chose, mais le fait est que votre contribution devient une partie de ce qui est évalué.

Donc eval ne vous apporte pas d'insécurité à moins que vous ne l'utilisiez les yeux fermés.

EDIT Oublié de dire que cela s'applique à n'importe quelle langue.

4
  1. Créez votre propre table de lecture et remplissez avec les crochets nécessaires: SET-MACRO-CARACTÈRE, SET-DISPATCH-MACRO-CHARACTER et al.
  2. Lier READTABLE à votre propre table de lecture.
  3. Lier READ-EVAL à zéro pour empêcher #. (Peut ne pas être nécessaire si l'étape 1 est bien fait)
  4. LIRE

probablement autre chose.

Il existe également une astuce pour insérer des symboles dans un paquet temporaire pendant la lecture.

Si les données ne sont pas LL (1) -ish, écrivez simplement l'analyseur habituel.