Wie kann ich die globals() kopieren?

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Nach wie vielen Zeichenketten willst du denn suchen, um die zu verhindern?
Es gibt schlicht eine endlose Liste von Möglichkeiten, die du unmöglich überblicken kannst.

Hier haben dir schon eine Menge Leute gesagt, dass das was du tust nicht funktioniert. Du bist wieder der Geisterfahrer.

Und du machst dir Gedanken über Dinge, die von sehr vielen Leuten bereits beleuchtet wurden. Das ist Verschwendung.
Benutzeravatar
cofi
Python-Forum Veteran
Beiträge: 4432
Registriert: Sonntag 30. März 2008, 04:16
Wohnort: RGFybXN0YWR0

Ein Glueck, dass nur Zeichenketten problematisch sind! Offensichtlich unschuldig:

Code: Alles auswählen

reduce(lambda a, b: a + b, (chr(i) for i in [122, 105, 112, 105, 109, 112, 111, 114, 116, 101, 114]))

@sparrow: Nein, das kann nicht sein, schliesslich sieht er doch Hunderte von Geisterfahrern.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Alfons Mittelmeyer hat geschrieben:Und so etwas, bei dem zipimport und __subclasses__ und dergleichen vorkommt - das kann man ja mit einem search feststellen, das lässt man nicht zu.
Na dann, auf gehts:

Code: Alles auswählen

eval("[k sbe k va bowrpg.__fhopynffrf__() vs 'mvcvzcbegre' va k.__anzr__]".decode('rot13'))
Alfons Mittelmeyer hat geschrieben:... wie für tkinter Programmbeispiele nötig ist und da dürfte sich das Risiko auf Null reduzieren lassen ...
Dir ist doch sicherlich klar, dass tkinter intern einen Tcl-Interpreter hat, gelle? Dieser Interpreter ist im Übrigen auch für systemnahe Programmierung ausgelegt, nur halt nicht so verbreitet wie Python selbst. Der geneigte Alfons wird schon rausfinden, was das eigentlich in Bezug auf die Aussage bedeutet. Vielleicht.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Fehler gefunden: globale Variable

Das ist schon sehr alter Code. hatte gedacht, weil das ein Objekt wäre, wäre es keine Variable:

Code: Alles auswählen

_Selection=Create_Selection()
Ist aber nicht so. Diese Referenz ändere ich ständig. Wenn ich globals() kopiere bekomme ich den augenblicklichen Wert (Referenz auf ein Objekt).
Wenn dann _Selection aktualisiert wird (neue Referenz), dann nicht in der Kopie der globals().

Eine Funktion dagegen hilft:

Code: Alles auswählen

def _get_selection(): return _Selection
DasIch
User
Beiträge: 2718
Registriert: Montag 19. Mai 2008, 04:21
Wohnort: Berlin

PyPy hat Sandboxing was tatsächlich funktioniert und sicher ist. Der Code dem man nicht vertraut wird allerdings auch in einem anderen Prozess ausgeführt und man muss dann mit dem irgendwie kommunizieren und sicherstellen dass man dabei nicht selbst wieder Sicherheitslücken einführt.
BlackJack

@Alfons Mittelmeyer: Nochmal: Es haben schon Leute mit viel Erfahrung und guten Kenntnissen von der CPython-Implementierung versucht einen Sandkasten zu bauen und sind gescheitert. Ähnlich erging es dem `pysandbox`-Projekt wo der Entwickler nach drei Jahren mit der Erkenntnis aufgegeben hat dass das nicht möglich ist, und zwar weil sowohl Python's Introspection als auch die CPython-Implementierung darauf einfach nicht ausgelegt ist. Er war a) immer am hinterherfixen von Wegen aus der Sandbox auszubrechen und b) das Ergebnis war dann am Ende nicht mehr vernünftig nutzbar weil zu viel verboten werden muss.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

jerch hat geschrieben:Na dann, auf gehts:

Code: Alles auswählen

eval("[k sbe k va bowrpg.__fhopynffrf__() vs 'mvcvzcbegre' va k.__anzr__]".decode('rot13'))
Ja Jerch, das mit eval wollte ich mal testen. Da hatte ich probiert:

Code: Alles auswählen

print(eval("5+3"))
Und was kam raus? Das da:
don't do this
don't do this
Man muss nur eval richtig definieren. Dazu braucht man eine Funktion:

Code: Alles auswählen

def dont_do_this(*args):
    print("don't do this")
    return "don't do this"
Und dann schreibt man:

Code: Alles auswählen

        evcode = compile(code,filename,'exec')
        my_scope = dict(globals())
        my_scopel['eval'] = dont_do_this
        my_scope['exec'] = dont_do_this
        my_scope['compile'] = dont_do_this
        exec(evcode,my_scope)
Da siehst Du wie gut compile und exec und eval funktioniert :wink:

Auch print kann man verbieten, import aber nicht. Import ist ein großes Sicherheitsrisiko. Kann man natürlich mit find suchen, und dann nicht zulassen, was etwas importiert.
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: Deine Borniertheit nervt.

Code: Alles auswählen

def dont_do_this(*args):
    print("don't do this")
    return "don't do this"

code = """print(eval.__globals__['__builtins__'].eval("5+3"))"""

evcode = compile(code,"",'exec')
my_scope = dict(globals())
my_scope['eval'] = dont_do_this
my_scope['exec'] = dont_do_this
my_scope['compile'] = dont_do_this
exec(evcode,my_scope)
Und ja, diese Lücke läßt sich auch leicht stopfen, aber das Spiel kann man beliebig lange spielen.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Wenn es so nicht weggeht, dann eben so:

Code: Alles auswählen

def exec_allowed(code):
    forbidden = ('eval','import','compile','exec','__','globals','locals')
    for entry in forbidden:
        if code.find(entry) >= 0:
            print('not allowed: ' + entry)
            return

    evcode = compile(code,"",'exec')
    exec(evcode)
            
code = """print(eval.__globals__['__builtins__'].eval("5+3"))"""
exec_allowed(code)
Sirius3
User
Beiträge: 17749
Registriert: Sonntag 21. Oktober 2012, 17:20

@Alfons Mittelmeyer: das langweilt. Nicht nur, dass jetzt so gut wie kein Code mehr funktioniert, Deinem Ziel bist Du keinen Millimeter weit näher gekommen.

Code: Alles auswählen

code = """print(getattr(getattr(lambda:2,'_'+'_glob'+'als_'+'_')['_'+'_buil'+'tins_'+'_'],'ev'+'al')("5+3"))"""
BlackJack

@Alfons Mittelmeyer: Damit ist das aber immer noch nicht sicher. Falls Du jetzt versuchst das Katz und Maus-Spiel zu wiederholen was die Entwickler des Moduls aus der Standardbibliothek und von `pysandbox` jahrelang durchgemacht haben: Forsche da bitte selber nach. Du wirst das nicht sicher und benutzbar hinbekommen. Sehr wahrscheinlich nicht einmal sicher.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

Was heißt jahrelang durchmachen. Dass ich natürlich nur eine Beispiel gegeben hatte ist auch klar. Und dass lambda selbstverständlich auch nicht sein darf, weil das auch kompiliert, versteht sich auch. Also lambda sicher auch nicht - partial stelle ich natürlich dafür schon zur Verfügung. Und wenn Ihr noch ein paar Beispiele findet und man die ausschließt, dann ist sehr bald keines mehr da. Und getattr natürlich auch nikcht. So etwas wie Rechenoperationen, Stringoperationen oder len darf man n atürlich tun. type auch und print auch. Input aber wahrscheinlich nicht.
Zuletzt geändert von Alfons Mittelmeyer am Mittwoch 11. November 2015, 00:26, insgesamt 1-mal geändert.
jerch
User
Beiträge: 1669
Registriert: Mittwoch 4. März 2009, 14:19

Alfons "Don Quijote" und der Kampf gegen Python built-ins.

Was evtl. ginge - man baut eine eigene Import-Funktion per C-Modul und markiert die hierüber importierten Codeframes. Alle markierten Frames laufen in einem Whitelist-Kontext, oder halt früher noch per Ast-Auswertung ein eigenes Subset auf Parserebene verwalten. Du musst in jedem Fall an den Zustand des Interpreters ran und diesen irgendwie kontrollierbar halten. D.h. aber gleichzeitig, dass full-featured Python in Deinen remote-Importen nicht mehr möglich ist. Damit drehen wir uns im Kreis, das haben wir alles schonmal durchgekaut. Langsam habe ich das Gefühl, dass Du das Problemfeld nicht richtig verstehst.
BlackJack

@Alfons Mittelmeyer: Eben das bald kein Beispiel mehr da sein wird ist ein Trugschluss und genau das heisst jahrelang durchmachen: Immer wenn die Entwickler sicher waren jetzt ist alles sicher kam dann doch wieder jemand mit einem Gegenbeispiel.

Du kannst auch nicht anhand von „Ich finde keine Beispiele mehr“ argumentieren es sei sicher, denn nur das Du oder jemand anders keine Lücken mehr findet beziehungsweise meldet, heisst ja nicht dass sie nicht mehr da sind. Der Entwickler von `pysandbox` war sich auch sehr sicher weil länger nichts mehr aufgefallen war — dann wurde das Projekt bei einer Challenge verwendet und schon während der ersten 24 Stunden gab es dann gleich zwei Codes die aus seinem Sandkasten ausbrachen.

Lern aus den Fehlern anderer und beschäftige Dich erst einmal selber in Ruhe für Dich mit dem Modul was mal in der Standardbibliothek war und mit `pysandbox` statt hier weiter zu trollen.
Benutzeravatar
pillmuncher
User
Beiträge: 1484
Registriert: Samstag 21. März 2009, 22:59
Wohnort: Pfaffenwinkel

Angenommen eine Funktion, die für jeden gültigen Pythonsatz True ausgibt, sofern dieser sicher importier-/compile-/exec-/evalbar ist und für jeden anderen gültigen Pythonsatz False. Das ist äquivalent dazu zu sagen, dass es zwei Sprachen SafePython und UnsafePython gibt mit einer Funktion, die True ausgibt, wenn ein gültiger Pythonsatz zur ersten Sprache gehört und False, wenn er zur zweiten Sprache gehört.

Der Satz von Rice besagt nun, dass es eine solche Funktion nicht im allgemeinen Fall geben kann. Anders ausgedrückt: es ist unentscheidbar, ob eine von irgendeiner Turingmaschine verstandene Sprache dieselbe ist wie SafePython. Außer natürlich, man beschränkt SafePython auf eine nicht-turingvollständige Teilmenge der gültigen sicheren Pythonsätze. Das heißt dann aber, es muss alles verboten werden, was irgendwie nützlich ist, Listen, Tupel, Sets, Dicts, Funktionsaufrufe, Objekte, File-IO, da man die alle benutzen kann, um rekursive Funktionsaufrufe durchzuführen oder zu simulieren, und damit hätte man wieder Turingvollständigkeit.

Oder anders gesagt: man bindet einfach keinen Fremdcode in sein Programm ein, wenn man der Quelle nicht trauen möchte.
In specifications, Murphy's Law supersedes Ohm's.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,

@Alfons Mittelmeyer: kennst du eigentlich das Buch "Fluent Python" oder besitzt es vielleicht sogar?

Gruß, noisefloor
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@noisefloor Das habe ich leider nicht. Aber sicher lohnenswert sich das anzuschaffen. Das wäre dann das erste Buch über Python, das ich dann lesen würde.
Benutzeravatar
sparrow
User
Beiträge: 4193
Registriert: Freitag 17. April 2009, 10:28

Alfons Mittelmeyer hat geschrieben:Das wäre dann das erste Buch über Python, das ich dann lesen würde.
Es wäre nicht schlecht, wenn du das noch mit dem einen oder anderen machen würdest. Es ist immer ein bisschen schwierig über Dinge zu sprechen, die man nicht verstanden hat und trotzdem verteidigt.
Alfons Mittelmeyer
User
Beiträge: 1715
Registriert: Freitag 31. Juli 2015, 13:34

@pillmuncher Es ist wohl das Beste keinen Code einzubinden dem man nicht traut. Hier im Forum war bisher niemand in der Lage, erklären zu können, weshalb man compile und exec als 'böse' ansieht. Es macht weniger wie import, es läßt sich mehr beschränken und außerdem hat man dann nicht durch eine Modul globale Definitionen und der Code wandert auch wieder in den Garbage Collector.

Es liegt doch vielmehr daran, dass Python an sich unsicher ist und anscheinend nicht sicher zu bekommen ist. Wenn man sich an die Regeln hält dass imports am Anfang stehen und kein exec und compile drin steht, dann sieht man, was eingebunden ist und wenn das dann nur Module sind, die man kennt, wie functools oder tkinter, dann ist man zufrieden.

Wenn man allerdings überall und unbegrenzt reinlädt, hat man keinen Überblick mehr, ob da auch etwas 'böses' dabei sein könnte.

Mit compile und exec, wenn man es selber benutzt, erhält man so etwas wie entfesseltes Python mit bielebiger Zuladung nur temporär benutzter Tools, die nach Gebrauch wieder in den Garbage Collector wandern. Auch ist es kein Problem, Fenster doppelt hinzuzuladen, ohne dass das Instanzen einer Klasse sind. Man hat dann einfach den Code doppelt im Speicher, der sich dann auch nicht in das Gehege kommt.

Allerdings liegt es wohl an der Unsicherheit von Python, dass man das gegenüber import auch nicht unsicherere compile und exec nicht mag, weil dann die Übersicht verloren geht, wo etwas geschieht.

Ein safe python wäre möglich, nämlich Syntax von python, also : und eingerückt statt { und }. Das wäre dann ziemlich abgespeckt und würde Vieles nicht bieten bzw. auch einschränken lassen.

Aber was nützt mir ein safe python, also etwas mit python Syntax, wenn es dafür keine tkinter Einbindung gibt. Python ist wohl nicht nur wegen seiner Syntax so beliebt, sondern auch wegen der Vielzahl der dazu vorhandenen Bibliotheken, die man einbinden kann. Ohne das und nur eine python Syntax hat man nicht viel.

Der Sandbox Weg - wobei man bei einigen Sandboxen nicht mal mehr ein Statement verwenden kann, sondern lambda dafür benutzen muss, hat sich nicht als besonders praktikabel herausgestellt.

Der gangbare Weg dagegen ist eine Sandbox, die auf einem sicheren OS beruht. Und wenn dann auch jemand das ganze Filesystem löschen würde, Na und? War eh nur temperär vorhanden und wird bei Programmende eh beseitigt.

Das ist der erfolgversprechende Weg, dass man Python ruhig machen läßt, was es will, nur raus aus dem OS kann es nicht und mehr als man dem OS erlaubt, kann es auch nicht.
Benutzeravatar
noisefloor
User
Beiträge: 3856
Registriert: Mittwoch 17. Oktober 2007, 21:40
Wohnort: WW
Kontaktdaten:

Hallo,
@noisefloor Das habe ich leider nicht. Aber sicher lohnenswert sich das anzuschaffen. Das wäre dann das erste Buch über Python, das ich dann lesen würde.
Aha... ob's als erstes Buch taugt weiß ich nicht, weil es schon sehr tief geht. Aber es würde definitiv dein Verständnis von Python _deutlich_ verbessern und viele deiner Fragen obsolet machen.

Gruß, noisefloor
Antworten