PHP Bilder nur für internen Bereich

Ok Security by Obscurity ist es nicht.
Wirklich toll finde ich es trotzdem nicht Credentials für Zugriffe auf Ressourcen über ein Teil der URL abzubilden. Seien es nun Get-Variablen oder ewig lange, zufällige IDs der Ressoucen.
Wobei ich vollkommen verstehen kann, wieso man es so macht wenn man große verteilte Systeme baut.
 
Sparta8 schrieb:
Danke für die Denkanstöße.
D.h. das höchste der Gefühle wäre z.B. Redis für die Sessions und PHP selbst kann man nicht umgehen.

Natürlich wäre es schlecht wenn eine Seite 100 Bilder auf einmal ladet, aber ist die Geschwindigkeit nicht die gleiche als wenn 25 User gleichzeitig 4 Bilder laden? Ich meine nur damit man so ungefähr die Performance abschätzen kann.

Weiß nicht wie genau Facebook das macht, aber sobald man die URL vom Bild hat, bekommt man dieses auch. Ganz ohne Session und egal mit welcher IP/Location. Die Rechte im Album sind auf "nur für mich" gesetzt. Also Freunde und Gäste sehen die Bilder nicht, aber wenn sie die URL haben, liefert der Server ohne zu mucken die Bilder aus.

Was meinst du mit, ich soll mir anschauen wie CB das macht, hier gibts doch gar keinen internen Bereich?

Danke!

Öhm nimm einfach die session von Php? Nichts für ungut aber wenn jemand solche Fragen stellt ist das nix highperformance lastiges auf nem Cluster, da legste einfach login und gehashtes und gesalzenes Passwort in die Db und lässt Php Sessions den Rest machen, das merkste nichtmal beim Rewuest....
Ergänzung ()

Bagbag schrieb:
@Piktogramm

Auch wenn ich dir recht gebe, dass es nicht die sicherste Lösung (in Bezug auf den Kram drum herum wie Browserhistorie oder das Teilen der URL) ist und Facebook das tatsächlich nicht (mehr?) so einfach nutzt, ist es trotzdem kein security through obscurity.
Ich kann dir die gesamte Implementierung dazu geben und trotzdem kommst du nicht an die Bilder, weil randomness und nicht obscurity (Unklarheit [wie das System funktioniert]) die Sicherheit darstellt.

Und das Beispiel Facebook passt trotzdem, weil du mit der URL alleine an das Bild kommst. Das entscheidende ist, dass du die URL nur ausgehändigt bekommst, wenn du dir das Bild anschauen darfst und du die URLs nicht erraten kannst.
Das dürfte das selbe Spiel wie bei S3 (mein Vorschlag oben) sein. Einfach eine presigned URL, mit der man zusätzlich die Gültigkeitsdauer der URL beschränken kann.

https://security.stackexchange.com/...ret-guid-in-an-url-security-through-obscurity

https://www.schneier.com/blog/archives/2015/07/googles_unguess.html

Jo und der erste der ne Url shared bricht dein System statt einfach nur ne Session aufzumachen. Großes Kino, könnt ihr euch mal am bestehenden Bedarf orientieren statt hier müßige Grundsatzdiskussionen über Technik mit völlig offensichtlichen Tradeoffs zu führen? Selten so viele Kanonen auf einen Spatzen gerichtet gesehn....
 
  • Gefällt mir
Reaktionen: Piktogramm und new Account()
Entweder serverseitige Sessions mit einer übergebenen Session-ID (Cookie, URl-Parameter) wenn es ganz sicher sein soll, dann kann man Bilder jedoch erst nach erfolgreichen Login anschauen und es ist ein klein wenig langsamer, da ja jedes Bild von einem Serverseitigen Skript geladen und ausgegeben werden muss.

Oder schwer zu erratene "Zufallsnamen" für die Bilder verwenden, wenn die Sicherheit zwar nicht gänzlich unwichtig aber auch nicht ganz soo wichtig ist. Dann kann jeder, der die URL hat, diese auch teilen aber es kann von außen kaum iteriert werden. Fail2Ban oder andere "Limiter" oder ähnliche Schutzeinrichtungen sollte man dann jedoch auf den Server packen.

Durchnummerieren, wenn die Sicherheit gar keine Rolle spielt und man den "Komfort" des skriptgesteuerten automatisierten Abrufs anbieten möchte.
 
  • Gefällt mir
Reaktionen: new Account()
mambokurt schrieb:
Jo und der erste der ne Url shared bricht dein System statt einfach nur ne Session aufzumachen. Großes Kino, könnt ihr euch mal am bestehenden Bedarf orientieren statt hier müßige Grundsatzdiskussionen über Technik mit völlig offensichtlichen Tradeoffs zu führen? Selten so viele Kanonen auf einen Spatzen gerichtet gesehn....
Jo und der erste der beim Bild auf Teilen drückt bricht dein System mit der Session. Genauso wenig Aufwand wie URL teilen. Großes Kino, eine URL ausgeben oder nicht ausgeben ist weniger aufwendig und eine viel kleinere Kanone als eine Session zu handeln und bei jedem Bild die Rechte prüfen zu müssen. Selten so nonsense gesehen.
 
Es kommt halt auf den Anwendungsfall an. Müssen die Bilder besonders stark vor unberechtigten Zugriffen geschützt werden, muss man mit serverseitigen Sessions (oder einer anderen falsifizierbaren Autorisierung) und einer skriptbasierten Bildausgabe arbeiten.

Ist der Schutzgedanke zwar vorhanden aber ist es auch gleichzeitig nicht so wild, dass die URLs auch geteilt werden dürfen, dann kann man einfach mit stark randomisierten Dateinamen arbeiten.

Edit: Gegen Screenshots hilft eh nichts.
 
Bagbag schrieb:
Jo und der erste der beim Bild auf Teilen drückt bricht dein System mit der Session.
Das man Inhalte die einmal ausgeliefert werden nicht wieder einfangen kann ist glaub jedem bekannt. Gegen 0815 Nutzer hilft es ja ausgesprochen gut unsichtbare Layer vor den eigentlichen Inhalt zu legen und den Inhalt gegebenenfalls als Mosaik zusammenzusetzen.

und eine viel kleinere Kanone als eine Session zu handeln und bei jedem Bild die Rechte prüfen zu müssen. Selten so nonsense gesehen.

Sessionverwaltung schreibt man dank der Integration in PHP eher in ein paar Zeilen runter als eine kollissionsfreie Dateiorganisation mit langen random IDs die dann auch noch mindestens die Performance von Sessions liefern soll.

Zudem kommt man um die Berechtigungsprüfung nicht herum, wenn das Prüfen auf Berechtigung (Nutzer angemeldet ja/nein) in den Anforderungen steht. Mindestens für das Nutzerloggin wird man sich eh mit Sessions auseinandersetzen müssen. Die Frage ist halt ob man ein einmal geschriebenes Modul recycelt oder noch mal parallel etwas Anderes baut.
 
  • Gefällt mir
Reaktionen: new Account()
Bagbag schrieb:
Jo und der erste der beim Bild auf Teilen drückt bricht dein System mit der Session. Genauso wenig Aufwand wie URL teilen. Großes Kino, eine URL ausgeben oder nicht ausgeben ist weniger aufwendig und eine viel kleinere Kanone als eine Session zu handeln und bei jedem Bild die Rechte prüfen zu müssen. Selten so nonsense gesehen.

Die session zu handeln sind in Php nur einige Zeilen Code, teuer wirds genau ein mal nämlich beim Anmelden, da brauchts ein mal Datenbankzugriff. Und wenn der User auf teilen drückt kann er das drölf mal machen, die Session läuft irgendwann aus oder wenn du das verhindern willst kannst du sie an eine IP oder ein Cookie binden.

Das angefragte Bild legste irgendwo in einen unzugänglichen Ordner und wenn du die Seite im Php generierst schiesst du es einfach direkt ins Html als Datenstrom statt es mit src zu verlinken.

Optional: htaccess mit username und passwort zum login, noch einfacher. Credentials einfach von Php in eine .htaccess schreiben lassen und den Bilderordner hinter die .htaccess gelegt. Ab da brauchen wir auch nicht mehr über performance reden, das dürfte nichtmal bemerkbar sein was Ladezeit angeht.
 
  • Gefällt mir
Reaktionen: new Account()
mambokurt schrieb:
Optional: htaccess mit username und passwort zum login, noch einfacher. Credentials einfach von Php in eine .htaccess schreiben lassen und den Bilderordner hinter die .htaccess gelegt. Ab da brauchen wir auch nicht mehr über performance reden, das dürfte nichtmal bemerkbar sein was Ladezeit angeht.

.htpasswd skaliert nicht gut wenn man viele Nutzer hat. Als unsortierte Liste ist da Speicherverbrauch und Laufzeit mit O=(n) eher mäßig.
 
Piktogramm schrieb:
Gegen 0815 Nutzer hilft es ja ausgesprochen gut unsichtbare Layer vor den eigentlichen Inhalt zu legen und den Inhalt gegebenenfalls als Mosaik zusammenzusetzen.
Jeder 0815 Nutzer schafft es ein Screenshot zu machen, zumindest am Smartphone.

Piktogramm schrieb:
Sessionverwaltung schreibt man dank der Integration in PHP eher in ein paar Zeilen runter als eine kollissionsfreie Dateiorganisation mit langen random IDs die dann auch noch mindestens die Performance von Sessions liefern soll.
Eine praktisch kollisionsfreie Id bekommst du in PHP mit $id = bin2hex(random_bytes(16));. Die Dateien kannst du genauso ablegen wie bei den meisten anderen Methoden auch. Ich behaupte sogar, dass es so performanter ist als ne Session, wenn du beim Abrufen gar nichts mehr prüfen musst, gar nicht mal mehr zwingend PHP dazwischen brauchst. Aber ja, beides mehr als schnell genug, wenn man da kein Unsinn implementiert.

Piktogramm schrieb:
Zudem kommt man um die Berechtigungsprüfung nicht herum, wenn das Prüfen auf Berechtigung (Nutzer angemeldet ja/nein) in den Anforderungen steht. Mindestens für das Nutzerloggin wird man sich eh mit Sessions auseinandersetzen müssen. Die Frage ist halt ob man ein einmal geschriebenes Modul recycelt oder noch mal parallel etwas Anderes baut.
Gebe ich dir vollkommen recht. Ich selbst würde es auch nicht mit der Variante die ich "vorgestellt" habe umsetzen, aber es ist halt eine einfache und schnelle Möglichkeit eine einfache Absicherung einzubauen. Die kann je nach Anforderungen reichen oder auch nicht. Das darf der TE selbst entscheiden.

mambokurt schrieb:
teuer wirds genau ein mal nämlich beim Anmelden, da brauchts ein mal Datenbankzugriff
Und überprüfen ob der Nutzer auf das Bild Zugriff hat oder nicht geschieht beim einzelnen Abrufen der Bilder wie?
 
Zuletzt bearbeitet:
Bagbag schrieb:
Und überprüfen ob der Nutzer auf das Bild Zugriff hat oder nicht geschieht beim einzelnen Abrufen der Bilder wie?
Auf Ebene von Gallerien: Die .php zum Zusammenbau der Gallerie wird nur aufgerufen, wenn die Session passt. Zugriff auf Elemente ohne bestehende Sessions werden geblockt bzw. etwas schöner, es werden alle Zugriffe per rewrite auf die index.php umgebogen. Wobei zugriffe wie example.com/pic/foo.png auf die example.com/index.php umgebogen werden und die index.php bekommt als Get-Variable /pic/foo.png
 
Zuletzt bearbeitet:
Bagbag schrieb:
Ja, aber interessanter ist die Überprüfung wenn die Session passt und der Nutzer angemeldet ist. Was passiert beim Abruf der einzelnen Bilder? http://foo/image-handler.php?image=id12

Du gibst die Images direkt mit dem Html mit, also du verlinkst die nicht einfach mit src="foo/bar" sondern über https://caniuse.com/#feat=datauri , damit biste eigentlich save. Das macht das Html natürlich größer, wär jetzt nichts wenn du 200 Bilder anzeigen willst aber zB für bei einer Gallerie wär das ok, Thumbnails als normale Bilder und fullscreen dann über datauri....
 
Das macht man so ganz sicher nicht, wenn man es gut machen will. Bau so mal auf diese Weise eine Gallerie wie https://unsplash.com/ oder https://www.pexels.com/ nach. Das lädt dann je nach Internetgeschwindigkeit Minuten lang, wenn es mehr als die Vorschaubilder inline hat. Und von meinem mobilen Datenvolumen sind dann gleich 100 MB weg, obwohl mich nur ein einziges Bild in der Galerie intressiert... An Nachladen von weiteren Bildern beim Runterscrollen ist so gar nicht erst zu denken. Viel Spaß, gerade wenn die großen Bilder fürs vergrößern gerne mal mehrere MB haben (und ja, das haben da manche). Und auch mit Pagination will ich mehr als nur 3 Bilder angezeigt bekommen. Nein, das ist keine Lösung.

Und die vergrößerten Bilder auf den zwei Seiten haben noch nicht mal so ne tolle Qualität, damit würde ich mich selbst nicht zufrieden geben.
 
Zuletzt bearbeitet:
Bagbag schrieb:
Das macht man so ganz sicher nicht, wenn man es gut machen will. Bau so mal auf diese Weise eine Gallerie wie https://unsplash.com/ oder https://www.pexels.com/ nach. Das lädt dann je nach Internetgeschwindigkeit Minuten lang, wenn es mehr als die Vorschaubilder inline hat. Und von meinem mobilen Datenvolumen sind dann gleich 100 MB weg, obwohl mich nur ein einziges Bild in der Galerie intressiert... An Nachladen von weiteren Bildern beim Runterscrollen ist so gar nicht erst zu denken. Viel Spaß, gerade wenn die großen Bilder fürs vergrößern gerne mal mehrere MB haben (und ja, das haben da manche). Und auch mit Pagination will ich mehr als nur 3 Bilder angezeigt bekommen. Nein, das ist keine Lösung.

Und die vergrößerten Bilder auf den zwei Seiten haben noch nicht mal so ne tolle Qualität, damit würde ich mich selbst nicht zufrieden geben.

Haste schon gelesen dass ich schrob dass das nix ist wenn man 50 Bilder auf der Seite hat ne? Vorschaubilder als Thumbnails öffentlich, Vollbildansicht inline (die Daten kannste auch per Js hin und her schicken)...

Das ist ja auch nur eine Möglichkeit. Das nächste was mir einfiele wäre zb die Bilder eines Users bei Anmeldung per Symlink in einen Ordner mit der SessionId zu spiegeln und aus dem auszuliefern, dann brauchst du nur eine Liste aktiver Sessions zu halten und wenn eine ausgelaufen ist deren Symlink zu löschen, dann gehen alle Links ins leere.

Aber wie gesagt, ich denke nicht dass der TE da jetzt ne Seite mit extrem viel Traffic hat, manchmal ist eine .htaccess schon ausreichend.
 
mambokurt schrieb:
Haste schon gelesen dass ich schrob dass das nix ist wenn man 50 Bilder auf der Seite hat ne?
Oben waren es noch 200, aber selbst bei nur 15 Bildern a 2MB (und teilweise gar mehr) wäre das schon viel zu viel des Guten.

mambokurt schrieb:
die Daten kannste auch per Js hin und her schicken
Dann braucht man wieder ein handler, der was machen muss? Datenbank Abfragen.

mambokurt schrieb:
Das ist ja auch nur eine Möglichkeit. Das nächste was mir einfiele wäre zb die Bilder eines Users bei Anmeldung per Symlink in einen Ordner mit der SessionId zu spiegeln und aus dem auszuliefern, dann brauchst du nur eine Liste aktiver Sessions zu halten und wenn eine ausgelaufen ist deren Symlink zu löschen, dann gehen alle Links ins leere.
Dann hast du aber eine ganz fixe Struktur z.B. nach Gallerien. Du musst beim Anmelden dann für jede Galerie, die der Nutzer ansehen darf ein Symlink erstellen. Der Code beim Abmelden darf auf keinen Fall aus welchem Grund auch immer einen Fehler werfen, sonst hast du Lecks. Sachen synchron halten ist selten eine schöne Lösung. Was machst du, wenn du Bilder eines Nutzers betrachten willst (wovon z.B. nicht alle öffentlich sind)? Geht mit dem System nicht, außer du legst für jeden Nutzer zusätzlich noch eine logische Gallerie an (wohoo, noch mehr Symlinks überall) und brauchst noch mehr Logik um das alles synchron zu halten, beim Hochladen, Löschen, Berechtigungen (public/private) ändern... So viel Logik, so viele Symlinks... und dadurch so viel, das schief gehen kann.
 
Berechtigungen kann man über direkte 1:1 Beziehungen abbilden.
Muss man aber nicht, man kann das auch über ein Powerlevel abbilden, welches man direkt in den Dateinamen oder Pfad kodieren könnte und beim Laden prüft. Oder Über Berechtigungsgruppen. Gibt da viele Möglichkeiten.

Irgendwie muss ja auch das "Bildverzeichnis" auf der Seite, wenn dort mehrere Bilder sind, aus einer Datenbank oder einer anderen Datenstruktur serverseitig geladen werden, damit die Seite überhaupt weiß, welche Bilder angefordert und dargestellt werden sollen (und welche nicht).
Das Abfrageergebnis / diese Datenstruktur könnte man dann Benutzerbezogen auch "Zwischenspeichern" (array mit Dateinamen in die Session speichern) und beim Anfragen der Bild-Ressource dann einfach gegen den Zwischenspeicher prüfen. if (in_array("dateiname.jpg", $_SESSION['bilder'])) { ... } Damit spart man sich die Datenbankzugrife beim Abrufen der Bildressource.

Mit Symlinks usw. ist das viel zu sehr um die Ecke gedacht.
 
Zuletzt bearbeitet:
ayngush schrieb:
man kann das auch über eine Powerlevel abbilden, welches man direkt in den Dateinamen oder Pfad kodieren könnte und beim Laden prüft.
Das setzt aber voraus, dass es fixe Rollen gibt und nicht etwas wie "User A darf Bilder von User B aber nicht von C sehen". Zusätzlich kannst du hier nicht einfach fopen($file) machen, sondern musst immer erst das directory auflisten und filtern oder so etwas wie auf gut Glück alle Powerlevels probieren zu öffnen.

ayngush schrieb:
Das Abfrageergebnis könnte man dann Benutzerbezogen auch "Zwischenspeichern" und beim Anfragen der Bild-Ressource dann einfach gegen den Zwischenspeicher prüfen.
Der Zwischenspeicher in welcher Form auch immer ist ja dann im Grunde wieder eine Datenbank. Selbst die PHP Sessions sind eine Datenbank, in einfachster Variante halt in Form von einfachen Dateien auf dem Dateisystem.

Ich sehe nach wie vor nur zwei sinnvolle Lösungen:
  • zufällige Dateinamen und die URLs einfach nur rausrücken wenn berechtigt. Das dürfte für die meisten Fälle sicher genug sein und ist sehr einfach umzusetzen.
  • ein image-handler, der mit einer Datenbank bei jedem Bild fragt ob berechtigt ist. Das ist für die aller meisten Fälle mehr als schnell genug und wenn man die Authorisierungslogik (die man so oder so braucht) schön in einen Service auslagert, ebenfalls einfach und schön umzusetzen.

Irgendwelche Tricksereien mit Symlinks bringen mehr Aufwand und Ärger als Nutzen.
 
Bagbag schrieb:
Das setzt aber voraus, dass es fixe Rollen gibt und nicht etwas wie "User A darf Bilder von User B aber nicht von C sehen".
Soweit ich den Satz "Es gibt einen Internen Bereich in dem User Bilder hochladen könne, die für Gäste nicht sichtbar sein dürfen" richtig verstehe ist das erst mal so. Ansonsten: Anforderungen eingangs richtig definieren, dann muss das "Developer Team" nicht eine Iteration lang über 42 verschiedene "wenn dann" Szenarien grübeln ;)
 
Stimmt, das hatte ich nach der ganzen Diskussion gar nicht mehr im Kopf.
 
Bagbag schrieb:
Oben waren es noch 200, aber selbst bei nur 15 Bildern a 2MB (und teilweise gar mehr) wäre das schon viel zu viel des Guten.


Dann braucht man wieder ein handler, der was machen muss? Datenbank Abfragen.


Dann hast du aber eine ganz fixe Struktur z.B. nach Gallerien. Du musst beim Anmelden dann für jede Galerie, die der Nutzer ansehen darf ein Symlink erstellen. Der Code beim Abmelden darf auf keinen Fall aus welchem Grund auch immer einen Fehler werfen, sonst hast du Lecks. Sachen synchron halten ist selten eine schöne Lösung. Was machst du, wenn du Bilder eines Nutzers betrachten willst (wovon z.B. nicht alle öffentlich sind)? Geht mit dem System nicht, außer du legst für jeden Nutzer zusätzlich noch eine logische Gallerie an (wohoo, noch mehr Symlinks überall) und brauchst noch mehr Logik um das alles synchron zu halten, beim Hochladen, Löschen, Berechtigungen (public/private) ändern... So viel Logik, so viele Symlinks... und dadurch so viel, das schief gehen kann.


Was ich sagen wollte ist dass du hier Kopf machst wo es nicht sein muss. Schön dass du die ultimative Lösung finden willst aber die gibt es hier mit den Infos nicht. Da brauchts nämlich Infos welcher User wie viel Bilder
Bagbag schrieb:
Das setzt aber voraus, dass es fixe Rollen gibt und nicht etwas wie "User A darf Bilder von User B aber nicht von C sehen". Zusätzlich kannst du hier nicht einfach fopen($file) machen, sondern musst immer erst das directory auflisten und filtern oder so etwas wie auf gut Glück alle Powerlevels probieren zu öffnen.


Der Zwischenspeicher in welcher Form auch immer ist ja dann im Grunde wieder eine Datenbank. Selbst die PHP Sessions sind eine Datenbank, in einfachster Variante halt in Form von einfachen Dateien auf dem Dateisystem.

Ich sehe nach wie vor nur zwei sinnvolle Lösungen:
  • zufällige Dateinamen und die URLs einfach nur rausrücken wenn berechtigt. Das dürfte für die meisten Fälle sicher genug sein und ist sehr einfach umzusetzen.
  • ein image-handler, der mit einer Datenbank bei jedem Bild fragt ob berechtigt ist. Das ist für die aller meisten Fälle mehr als schnell genug und wenn man die Authorisierungslogik (die man so oder so braucht) schön in einen Service auslagert, ebenfalls einfach und schön umzusetzen.

Irgendwelche Tricksereien mit Symlinks bringen mehr Aufwand und Ärger als Nutzen.

Wenn was einfach und performant ist wird es umgesetzt. Wenn was einfach und performant genug ist wird es umgesetzt. Ein symlink ist schnell gesetzt, performant und einfach. Ansonsten: soweit wir wissen ist das die Vereinsseite einer Fußballmannschaft mit 20 Mitgliedern, das hat der TE nicht spezifiziert. Von daher würde ich einfach die simpelste Lösung nehmen und erst wenn die zu lahm ist überhaupt dran denken daran was zu schrauben. Von daher würde ich jetzt nicht anfangen irgendwelche Bilder mit User dran zu hinterlegen und das aus der Db zu ziehen, das ist nämlich weder performant noch einfach. Da gehen die Meinungen vllt auseinander aber das teuerste was es gibt ist Datenbank. Am Besten noch ein Request je Bild, da kannste zugucken wie die Performance in den Keller geht. Handler genauso: 50 Bilder - 50 Aufrufe, wo ist jetzt das Problem einfach EINEN Symlink aufs Bilderverzeichnis zu machen? Das ist nicht kompliziert, das ist das Einfachste wo geht.

Aber Imho liest der TE hier eh nicht mehr mit, von daher ist es eh egal.
 
Zurück
Oben