Das ist wirklich nur eine konzeptionelle Frage für mich an diesem Punkt.
In Lisp sind Programme Daten und Daten sind Programme. Die REPL macht genau das - liest und dann auswertet.
Wie also geht es darum, vom Benutzer auf sichere Weise Input zu erhalten? Offensichtlich ist es möglich - ich meine viaweb - jetzt ist Yahoo! Stores ziemlich sicher, also wie wird es gemacht?
Die REPL steht für Read Eval Print Loop.
%Vor%Oben ist nur konzeptionell, der echte REPL-Code ist viel komplizierter (mit Fehlerbehandlung, Debugging, ...).
Sie können alle Arten von Daten in Lisp lesen, ohne sie zu bewerten. Die Auswertung ist ein separater Schritt - unabhängig vom Lesen der Daten.
In Lisp gibt es alle Arten von IO-Funktionen. Die komplexeste der bereitgestellten Funktionen ist normalerweise READ, die s-Ausdrücke liest. Es gibt eine Option in Common Lisp, die eine Auswertung während READ erlaubt, aber das kann und sollte beim Lesen von Daten ausgeschaltet werden.
Also sind Daten in Lisp nicht unbedingt ein Programm und selbst wenn Daten ein Programm sind, kann Lisp das Programm als Daten lesen - ohne Auswertung. Eine REPL sollte nur von einem Entwickler verwendet werden und sollte nicht willkürlichen Benutzern ausgesetzt werden. Zum Abrufen von Daten von Benutzern verwendet man die normalen IO-Funktionen, einschließlich Funktionen wie READ, die S-Ausdrücke lesen, aber nicht auswerten können.
Hier sind ein paar Dinge, die man NICHT tun sollte:
LESEN, um beliebige Daten zu lesen. READ für Beispiele erlaubt es, wirklich große Daten zu lesen - es gibt keine Begrenzung.
wird während READ ausgewertet ('read eval'). Dies sollte ausgeschaltet sein.
liest Symbole von I / O und ruft deren Symbolfunktionen
liest zyklische Datenstrukturen mit READ, wenn Ihre Funktionen einfache Listen erwarten. Wenn Sie eine zyklische Liste durchlaufen, kann Ihr Programm eine Weile beschäftigt sein.
behandelt keine Syntaxfehler beim Lesen von Daten.
Sie tun es so, wie alle anderen es tun. Sie lesen eine Reihe von Daten aus dem Stream, parsen diese für Ihre Befehle und Parameter, validieren die Befehle und Parameter und interpretieren die Befehle und Parameter.
Es gibt keine Magie hier.
Einfach gesagt, was Sie nicht tun, ist, dass Sie Ihren Lisp-Listener nicht einer nicht validierten, unsicheren Datenquelle aussetzen.
Wie bereits erwähnt, wird die REPL gelesen - eval - print. @ The Rook konzentrierte sich auf eval (mit Grund), aber nicht Rabatt READ. READ ist ein sehr mächtiger Befehl in Common Lisp. Der Leser kann den Code selbst auswerten, bevor Sie sogar auf "eval" zugreifen.
Belichten Sie READ nicht mit Dingen, denen Sie nicht vertrauen.
Mit genügend Arbeit könnten Sie ein benutzerdefiniertes Paket erstellen, den Umfang der für dieses Paket verfügbaren Funktionen einschränken usw. usw. Aber ich denke, das ist mehr Arbeit, als einfach einen einfachen Befehlsparser selbst zu schreiben und sich keine Gedanken über Nebeneffekte zu machen Ich habe es vermisst.
Wahrscheinlich noch etwas.
Es gibt auch einen Trick beim Einpegeln von Symbolen in ein temporäres Paket während des Lesens.
Wenn Daten in nicht LL (1) -ish, schreiben Sie einfach üblichen Parser.
Das ist eine Killerfrage, und ich dachte dasselbe, als ich über Lisp las. Obwohl ich in LISP nichts Sinnvolles gemacht habe, ist meine Antwort sehr begrenzt.
Was ich Ihnen sagen kann ist, dass eval()
böse ist . Es gibt ein Sprichwort, das mir gefällt "Wenn eval die Antwort ist, dann stellst du die falsche Frage." --Unbekannte.
Wenn der Angreifer Daten kontrollieren kann, die dann ausgewertet werden, haben Sie eine sehr schwerwiegende Sicherheitsanfälligkeit bezüglich Remotecodeausführung. Dies kann gemildert werden, und ich werde Ihnen ein Beispiel mit PHP zeigen, denn das ist, was ich weiß:
%Vor%Wenn Sie keine Schrägstriche hinzufügen, kann ein Angreifer Remotecodeausführung ausführen, indem er Folgendes vornimmt:
%Vor% Aber die addierten Schrägstriche machen das "
zu einem \"
, wodurch der Angreifer daran gehindert wird, aus den "Daten" auszubrechen und Code ausführen zu können. Das ist sehr ähnlich zu SQL-Injektion.
Ich fand diese Frage umstritten. Die Bewertung wird nicht ausgewertet, es sei denn, Sie fragen explizit danach. Ich meine, Ihre Eingabe wird nicht als LISP-Code behandelt, sondern als String.
Nicht weil Ihre Sprache ein starkes Konzept wie das Eval hat, dass es nicht "sicher" ist.
Ich denke, dass die Verwirrung von SQL kommt, wo Sie tatsächlich eine Eingabe als [Teil von] SQL behandeln.
%Vor%Hier wird die Eingabe-ID von der SQL-Engine ausgewertet. Dies liegt daran, dass Sie keine gute Möglichkeit haben, SQL zu schreiben, oder was auch immer, aber der Punkt ist, dass Ihre Eingaben Teil dessen werden, was evaluiert wird.
So eval bringen Sie nicht Unsicherheit, es sei denn, Sie verwenden es Augen geschlossen.
EDIT vergessen zu sagen, dass dies für jede Sprache gilt.
Tags und Links security validation lisp