Seite 2 von 2

Re: Media Verzeichnis schützen

Verfasst: Sonntag 3. November 2019, 01:01
von knasan
sorry falsche URL:
https://stackoverflow.com/questions/115 ... able-files

Hm, irgendwie habe ich kein Bearbeiten Button gefunden/gesehen, deswegen nochmal die Korrektur zur URL.

Gruß Sandy

Re: Media Verzeichnis schützen

Verfasst: Sonntag 3. November 2019, 04:46
von __blackjack__
@knasan: Ad 1. Gegenfrage, gibt's da was uneleganteres? 😜

Aber vielleicht erst einmal zu vorhergehenden Problemen. Das fängt mit der Route an, der reguläre Ausdruck ist kaputt, der erlaubt zum Beispiel das hier als Route:

Code: Alles auswählen

"media/something/really anything goes here 🐁/../../../etc/hosts"
"media" ist fest, bei "something" ist man auf Zeichen der ”word”-Klasse beschränkt, aber danach kann dann wirklich *alles* kommen.

Die Urls für diese Route müssen auch nicht mit "media/" anfangen, denn auch das hier geht:

Code: Alles auswählen

"../../really anything goes here 📭/something_a/something_b"
Einzige Einschränkung: `something_a` und `something_b` müssen aus Zeichen der ”word”-Klasse bestehen. Davor kann *alles* stehen.

In keiner der beiden Varianten lässt sich am Ende allerdings eine Dateiendung mit einem Punkt angeben. Das geht dann also nur für Dateien die keine Dateiendung haben.

Reguläre Ausdrücke sind mächtig, aber auch kompliziert und damit fehleranfällig. `path()` würde ich in der Regel vorziehen. Mir ist nicht so ganz klar was Du da genau mit dem regulären Ausdruck erreichen wolltest, aber das wäre wohl so etwas in diese Richtung:

Code: Alles auswählen

path("media/<filename>", views.listfiles, name="listfiles"))

...

def listfiles(request, filename):
    ...
Bei dem Code der dann in der `listfiles()` bei Dir folgt sind die Pfadoperationen nicht wirklich sicher. Auch wenn der reguläre Ausdruck dich wahrscheinlich schützt, hast Du ja gesehen wie leicht man da Fehler machen kann. Darum würde ich auch danach immer Sicherheitsmassnahmen ergreifen die verhindern das bei absichtlich oder unabsichtlich eingegebenen Daten böse Sachen passieren können, wie beispielsweise jemand der versucht mit "..", "../..", und so weiter über das Wurzelverzeichnis hinaus zu kommen. Aus dem gezeigten Code wird beispielsweise nicht ersichtlich ob Benutzernamen so etwas erlauben, dass man aus einer Kombination aus Benutzernamen ("../../etc/") und URL die mit "/hosts" endet nicht vielleicht doch an die ``/etc/hosts`` auf dem Server heran kommen kann.

Letztlich würde ich das aber sowieso versuchen zu vermeiden selbst zu schreiben. Django bietet da beispielsweise schon eine Abstraktion auf Dateisysteme, so dass man notfalls auch virtuelle Dateisysteme verwenden kann wo die Dateien in Datenbanken gespeichert werden, oder bei Cloudanbietern, oder…

Django selbst bietet da bereits ein `FileSystemStorage` an. Das kümmert sich unter anderem um ein sicheres erstellen eines Pfades, also so das man nicht über das Wurzelverzeichnis heraus kommen kann.

Ungetestet:

Code: Alles auswählen

def download_file(request, filename):
    if not request.user.is_authenticated():
        return HttpResponseForbidden("<h1>User is not logged in</h1>")

    try:
        file = default_storage.open(os.path.join(str(request.user), filename))
    except FileNotFoundError:
        return HttpResponseNotFound("<h1>File not found</h1>")
    else:
        return FileResponse(file)
Benutzer-ID ist hier eventuell sinnvoller als Benutzername, zumindest wenn das System Änderung des Nutzernamens erlauben sollte.

Dann noch mal Ad 1.: ``.split("/")[1:][0]`` ist etwas umständlich für ``.split("/")[1]``:

Code: Alles auswählen

In [43]: "foo/bar/baz/spam".split("/")                                          
Out[43]: ['foo', 'bar', 'baz', 'spam']

In [44]: "foo/bar/baz/spam".split("/")[1:]                                      
Out[44]: ['bar', 'baz', 'spam']

In [45]: "foo/bar/baz/spam".split("/")[1:][0]                                   
Out[45]: 'bar'

In [46]: "foo/bar/baz/spam".split("/")[1]                                       
Out[46]: 'bar'
Wobei man da bei `split()` auch noch das zweite Argument nutzen kann um unnötige Elemente zu vermeiden:

Code: Alles auswählen

In [47]: "foo/bar/baz/spam".split("/", 2)                                       
Out[47]: ['foo', 'bar', 'baz/spam']

In [48]: "foo/bar/baz/spam".split("/", 2)[1]                                    
Out[48]: 'bar'
Ad 2. MVC? View? Welches MVC? Es gibt nicht *das* MVC. Jedes Rahmenwerk hat offenbar eine eigene Meinung dazu wie MVC auszusehen hat, von einzelnen Entwicklern mal ganz abgesehen. Das ist eine nette Theorie die in der Praxis kein wirkliches Entwurfsmuster ist. Denn Entwurfsmuster impliziert ja, dass man ein Muster gefunden und dem einen Namen gegeben hat, damit alle das gleiche darunter verstehen. Das ist bei MVC so ganz und gar nicht der Fall.

Wie Django das sieht steht in der FAQ: https://docs.djangoproject.com/en/2.2/f ... dard-names

Die nennen das auch lieber MTV was sie machen — Model, Template, View.

Re: Media Verzeichnis schützen

Verfasst: Montag 4. November 2019, 22:19
von knasan
Hallo ,

danke @__blackjack__,

danke für deine Erklärung, jetzt ist mir auch vieles klar geworden.
Ein path mit optionen (filename) und dann die Funktion diese in die Parameterliste aufnehmen, war mir so nicht klar. Aber dank deines Beispiels ist mir ein licht aufgegangen.

Ich denke, das ich nun verstanden habe wie es geht und werde es in der Datenbank speichern (File im Storage) und die Zugriffe in der DB. Denke so werde ich es hinbekommen.
Sobald ich neuen Code habe, werde ich meine Lösung mal hier posten. Wie ich eben gelernt habe, ist unachtsam im code etwas böses ;-)

Gibt es eine Art Security Check für Python entwickelte Webseiten? Der mich auf das eine oder andere Aufmerksam macht oder muss jede Webseite manuell überprüft werden ob diese evtl. Schwachstellen enthält?

Re: Media Verzeichnis schützen

Verfasst: Montag 4. November 2019, 22:32
von nezzcarth
knasan hat geschrieben: Montag 4. November 2019, 22:19 Gibt es eine Art Security Check für Python entwickelte Webseiten? Der mich auf das eine oder andere Aufmerksam macht oder muss jede Webseite manuell überprüft werden ob diese evtl. Schwachstellen enthält?
Vielleicht hilft das ja weiter, wenn noch nicht bekannt: https://docs.djangoproject.com/en/2.2/h ... checklist/
Ansonsten gibt es diverse generische Werkzeuge für diesen Zweck; etwas python-spezifisches ist mir aber nicht geläufig.

Re: Media Verzeichnis schützen

Verfasst: Dienstag 5. November 2019, 21:39
von knasan
Das Verzeichnis zu Schützen usw über den view kostet zu viel Ressourcen. Ich hatte die Möglichkeit dieses Thema mit einem python django Dozent zu diskutieren. Er hat mir am Ende der Diskussion diese URL gegeben wie man es umsetzen könnte. https://wellfire.co/learn/nginx-django- ... redirects/

Ich dachte, ich teile diesen link mal mit euch 😁

Am Wochenende werde ich mir mal ein Server aufsetzen und das ganze testen.

Gruß Sandy

Re: Media Verzeichnis schützen

Verfasst: Dienstag 5. November 2019, 21:50
von nezzcarth
knasan hat geschrieben: Dienstag 5. November 2019, 21:39 Er hat mir am Ende der Diskussion diese URL gegeben wie man es umsetzen könnte. https://wellfire.co/learn/nginx-django- ... redirects/
Was den Vorschlag von Sirius3 weiter vorne eine Anleitung für Django zur Seite stellt ;). (Das in dem Link erwähnte mod_xsendfile für Apache ist allerdings mit Vorsicht zu genießen, da veraltet und nicht mehr gepflegt).