Seite 1 von 2

Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 14:27
von Alfons Mittelmeyer
Wie kann ich die globals kopieren, sodass sie auch funktionieren.

Ich möchte eine Kopie von den globals, um daraus sicherheitsrelevante builtin Funktionen, wie etwa import beseitigen zu können. Aber nicht mal Kopieren klappt:

Code: Alles auswählen

        my_dict = dict(globals())
        exec(evcode,my_dict,locals())
Mit copy funktioniert es auch nicht.

Ich würde gerne, weil sich builtin Funktionen nicht löschen lassen, mir herauskopieren was ich brauche, etwa:

Code: Alles auswählen

         for key,data in globals().items():
            if key != '__import__':
                s_dict[key]=data
Aber hinterher funktionieren die kopierten globals() anscheinend nicht richtig.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 14:34
von BlackJack
@Alfons Mittelmeyer: Vergiss es, Du bekommst den Python-Interpreter nicht mit einfachen Mitteln sicher. Der ist dafür einfach nicht ausgelegt, so etwas müsste man von Grund auf einplanen.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 14:38
von Alfons Mittelmeyer
Sicher bekäme man ihn schon, so sicher, dass er nicht mal mehr print ausführen kann. Aber so sicher möchte ich ihn nicht haben, anderes sollte doch auch noch funktionieren.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 14:49
von BlackJack
@Alfons Mittelmeyer: Es gab mal den Versuch ihn sicher zu bekommen, das Modul ist aus der Standardbibliothek rausgeflogen weil es immer wieder Wege gab das auszuhebeln, ganz einfach weil Python von seiner Natur aus kein ”private” kennt und Introspection sehr einfach macht. Wenn die Python-Core-Entwickler das trotz fortgesetzter Bemühungen nicht schaffen, wirst Du das sicher auch nicht schaffen. Mal was ganz einfaches: ``python -c 'print object.__subclasses__()'``, da ist unter anderem `zipimport.zipimporter` mit in der Liste. Und das ist nur *ein* weg an andere Objekte heranzukommen die nicht direkt in `__builtins__` drin sind.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 14:54
von jerch
@Alfons:
Was Du brauchst:

Code: Alles auswählen

chroot(Popen(['downstripped_python_interpreter', 'remote.py']))

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 14:56
von bwbg
Zum einen gibt es die dict comprehension:

Code: Alles auswählen

foo = {k: v for k, v in globals().items() if k not in ['__import__']}
Beachten sollte man allerdings, dass hier flache Kopien (shallow copies) angelegt werden.

Zum anderen ist import ein statement und daher Sprachbestandteil, welchen man über diesen Weg nicht ausschließen kann.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 15:11
von Alfons Mittelmeyer
Naja, etwas scheint python nicht von den globals kopieren zu wollen, nämlich keine tkinter widgets. Wieso eigentlich nicht?

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 15:16
von bwbg

Code: Alles auswählen

>>> import tkinter as tk
>>> foo = {k: v for k, v in globals().items()}
>>> root = foo['tk'].Tk()
>>> frame = foo['tk'].Entry(root)
>>> frame.pack()
>>> root.mainloop()
Pas de problème.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 15:25
von Alfons Mittelmeyer
@BlackJack Da ist zipimporter als type drin. Also kennt python auch einen type zipimport.zipimporter. Doch um ihn zu benützen, braucht es wohl:
import zipimport

Der . besagt dass es sich um ein Modul handelt und das muss man ja wohl erst importieren.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 15:54
von BlackJack
@Alfons Mittelmeyer: Nein, es braucht eben *keinen* Import, der Datentyp ist doch in der Liste enthalten. Da kann man ihn sich anhand des Namens rausfischen und dann benutzen.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 15:54
von cofi
Der Punkt besagt nicht mehr als dass es sich um einen Attributszugriff handelt. Um ein Modulobjekt zu bekommen braucht es eben _keinen_ Import. Das ist der ganze Punkt von BlackJacks Post: Die Moeglichkeit `import` loszuwerden bringt dir rein gar nichts.

Code: Alles auswählen

In [14]: [x for x in object.__subclasses__() if 'zipimporter' in x.__name__]
Out[14]: [zipimport.zipimporter]

In [15]: [x for x in object.__subclasses__() if 'zipimporter' in x.__name__][0]('foo.zip')
---------------------------------------------------------------------------
ZipImportError                            Traceback (most recent call last)
<ipython-input-15-821efb93d245> in <module>()
----> 1 [x for x in object.__subclasses__() if 'zipimporter' in x.__name__][0]('foo.zip')

ZipImportError: not a Zip file
Und wenn man jetzt noch ein Zip Modul an dem Pfad hat, dann hat man einen Import.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 16:02
von Sirius3
@Alfons Mittelmeyer: nochmal ein illustratives Beispiel. Du importierst irgendwo subprocess und gibst Deinem exec nur eine unschuldige Klasse und keine __builtins__:

Code: Alles auswählen

import subprocess
class Abc(object):
    pass
exec """
Popen = [cl for cl in Abc.__base__.__subclasses__() if cl.__name__=='Popen'][0]
Popen('ls').communicate()
""" in {'__builtins__': {}, 'Abc':Abc},{}
:twisted: :twisted: :twisted:

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 16:25
von jerch
@Alfons:
Wir haben das doch schon zigmal durchgekaut - Du bekommst das mit Python innerhalb eines Interpreters nicht sicher, egal ob Du exec, import, weiss der Geier was.... mit Pythoncode nutzt. Geht nicht. Punkt. Egal welche Verrenkung Du anstellst - solange Du nicht den Interpreter selbst manipulierst, wird das nicht sicher. Egal wie wenig Du das hören möchtest, es wird nichts. Nein. Geht nicht.

Diese Diskussionen haben schon was von täglichen Murmeltieren.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 16:29
von Alfons Mittelmeyer
Also das mit global ist wohl ein spezielles unidentifizierbares Problem. Es geht ewig gut und läuft da vielmals richtig durch, die GUI wird zum großen Teil aufgebaut, und dann findet das Programm etwas nicht. Wo es dann aussteigt, haben sowohl die globals() als auch die kopierten, jeweils 800 Zeilen. Ob da ein Unterschied ist, schwer zu sagen. Müßte man mit irgendeinem Programm alphabetisch sortieren, um es dann nebeneinander legen zu können.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 16:48
von Alfons Mittelmeyer
Natürlich bekommt man Python nicht vollkommen sicher. Aber wenn man einfache Beispielprogramme für tkinter nach kritischen Stellen per Programm durchsucht, sie sich anschaut und begutachtet und zusätzlich bei den Nutzern Dinge wie import ausschaltet bei http:// sollte große Sicherheit bestehen.

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.

Wenn jemand Programme aus unsicheren Stellen einbindet, das kann er auch mit import tun, dagegen kann man nichts machen. Es geht hier nicht darum, dass man mit Python möglichst viel machen kann, sondern nur soviel, wie für tkinter Programmbeispiele nötig ist und da dürfte sich das Risiko auf Null reduzieren lassen, wenn auch die Programme nicht ohne Prüfung durchgelassen werden.

Was jemand allerdings selber programmiert und für sich nutzt, und was er da tut, das bleibt ihm selbstverstänldich selber überlassen.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 16:55
von sparrow
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.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 17:05
von cofi
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.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 17:11
von jerch
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.

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 17:31
von Alfons Mittelmeyer
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

Re: Wie kann ich die globals() kopieren?

Verfasst: Dienstag 10. November 2015, 17:35
von DasIch
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.