16 Stimmen

Ausführen von vom Benutzer bereitgestelltem Ruby-Code auf einem Webserver

Ich möchte meinen Benutzern die Möglichkeit geben, Ruby-Skripte zu erstellen, die Berechnungen mit Daten auf dem Webserver durchführen und dann die Ergebnisse ausgeben. Die Skripte werden auf dem Server ausgeführt. Gibt es eine Möglichkeit, dies auf sichere Weise zu tun?

Genauer gesagt, würde ich gerne:

  • die Ressourcen, die das Skript nutzen kann (Arbeitsspeicher und Prozessor), und die Laufzeit begrenzen
  • einschränken, welche Kernklassen das Skript verwenden kann (z. B. String, Fixnum, Float, Math usw.)
  • das Skript auf Daten zugreifen und diese zurückgeben lassen
  • eventuelle Fehler an den Benutzer ausgeben

Gibt es irgendwelche Bibliotheken oder Projekte, die das tun, wonach ich frage? Wenn nicht in Ruby, dann vielleicht in einer anderen Sprache?

17voto

Wayne Conrad Punkte 95828

Sie können eine "leere Tafel" als reinen Raum und als Sandkasten nutzen, in dem Sie die sicheres Niveau bis 4.

Ein unbeschriebenes Blatt ein Objekt, von dem Sie alle Methoden entfernt haben:

class BlankSlate

  instance_methods.each do |name|
    class_eval do
      unless name =~ /^__|^instance_eval$|^binding$|^object_id$/
        undef_method name
      end
    end
  end

end

Ein Reinraum ist ein Objekt, in dessen Kontext Sie anderen Code bewerten:

  clean_room = BlankSlate.new

Lesen Sie einen Befehl aus einer nicht vertrauenswürdigen Quelle und heben Sie ihn dann auf. Solange er nicht untainted ist, weigert sich Ruby, die Zeichenkette in einer Sandbox auszuwerten.

  command = gets
  command.untaint

Führen Sie nun die Zeichenfolge in einer Sandbox aus und erhöhen Sie die Sicherheitsstufe so weit wie möglich. Der $SAFE-Level wird wieder auf den normalen Wert zurückgesetzt, wenn der Prozess endet. Wir führen den Befehl im Kontext der Bindung des Reinraums aus, so dass er nur die Methoden und Variablen sehen kann, die der Reinraum sehen kann (bedenken Sie aber, dass der Reinraum wie jedes Objekt alles in global scape sehen kann).

  result = proc do
    $SAFE = 4
    clean_room.instance_eval do
      binding
    end.eval(command)
  end.call

drucken Sie das Ergebnis:

  p result

CodeJaeger.com

CodeJaeger ist eine Gemeinschaft für Programmierer, die täglich Hilfe erhalten..
Wir haben viele Inhalte, und Sie können auch Ihre eigenen Fragen stellen oder die Fragen anderer Leute lösen.

Powered by:

X