Andi90: Hallo, danke nochmal ...und noch eine kurze Verständnisfrage :D

Hallo,

Danke nochmal an alle die mir geholfen haben! ... (

https://forum.selfhtml.org/self/2018/jan/9/bilder-in-zugriffsverweigerndem-ordner-auslesen/1711704#m1711704

).

Hab Wilfrieds Idee beherzigt und die php-Datei, die mir die Bilder mittels $_GET aus dem geschützten Ordner holt, mit einem Session-Gegencheck versehen ( - soll heißen, sobald jemand die $_GET Anweisung über die Adressleiste aufrufen will, wird er umgeleitet, da keine Session vorhanden).

Bin zum Thema Redirect auf https://www.cyberciti.biz/faq/php-redirect/ gestoßen, dort findet sich unter anderem auch die Festellung:

 (...) header() must be called before any actual output is sent (...)

Soweit im Westen nichts Neues, ...jetzt muss ich aber die Session starten, bevor ich gegenchecken kann ob sie existiert, also

session_start();
if(!isset($_SESSION["login"]) && !isset($_SESSION["pass"])) {
	header("Location: 403.php");
	exit;
}
//sonst weiterer Quelltext

Jetzt meine Verständnisfrage: session_start() ist kein Output in dem Sinne - was wird aber eigentlich als Output definiert?

...wie gesagt, ist eher eine Verständnisfrage denn eine Problemstellung, verstehe es daher durchaus, wenn ihr euch vordergründig lieber anderen Themen widmet... :)

LG, Andi.

  1. Hallo

    Bin zum Thema Redirect auf https://www.cyberciti.biz/faq/php-redirect/ gestoßen, dort findet sich unter anderem auch die Festellung:

     (...) header() must be called before any actual output is sent (...)
    

    Jetzt meine Verständnisfrage: session_start() ist kein Output in dem Sinne - was wird aber eigentlich als Output definiert?

    Irgendein an den Browser gesendetes Zeichen. Das kann zum Beispiel ein Leerzeichen oder Zeilenumbruch vor dem mit <? oder <?php definierten Start des Skriptbereichs sein.

     <= hier irgendein Zeichen vor beginn des Skriptbereichs und du hast „verloren“
    <?php
    // dein Code
    

    Tschö, Auge

    --
    Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
    Toller Dampf voraus von Terry Pratchett
  2. Tach!

    Soweit im Westen nichts Neues, ...jetzt muss ich aber die Session starten, bevor ich gegenchecken kann ob sie existiert, also

    session_start();
    if(!isset($_SESSION["login"]) && !isset($_SESSION["pass"])) {
    	header("Location: 403.php");
    	exit;
    }
    //sonst weiterer Quelltext
    

    session_start() startet eine neue Session oder nimmt eine vorhandene wieder auf. Dein Part ist nicht der Test, ob eine Session existiert, sondern ob sich in der (wieder)eröffneten ein bestimmter Wert befindet. Dieser Wert gibt Auskunft ob der Nutzer berechtigt ist oder nicht.

    Es empfieht sich übrigens nicht, Usernamen und Passwort zu speichern. Die stehen dann nur im Klartext im Session-Dateien-Speicher rum. Oftmals ist das nur ein globaler Ordner im System, auf den jeder Zugriff hat. Du brauchst dir lediglich zu merken, ob der Nutzer authentifiziert oder berechtigt ist. Zur Not seinen Nutzernamen, wenn du den noch anderweitig brauchst, aber das Passwort gehört da nicht hin.

    dedlfix.

  3. Hallo Andi,

    mal andersherum gefragt: Wie wurde denn bisher die Anzeige, also der php-Aufruf, der die HTML-Seite produziert, geschützt? Der Aufruf für die Bilder muss dann nicht besser geschützt sein.

    Wenn Du mit einer Session arbeiten willst, versuch doch mal folgendes (zu knacken 😉):

    In der Seite mit dem HTML:

    <?php
     session_start();
     $id = session_id();
     ?>
    <img src="./showPic.php?name=Bild1&S=<?=$id?>">
    

    in showPic.php:

     session_start();
     $id = session_id();
     if (array_key_exists("S",$_GET)){
        if ($_GET['S'] == $id) $ergebnis="gut"; // Jetzt das Bild anzeigen
        else $gleiche_session="Fehlermeldung"; 
     }
     else $ergebnis="kein Aufruf aus der Seite"; // leere Rückgabe 
     ?>
    

    Auf ein Redirect würde ich verzichten, weil es ja ein Bild in der Seite ist. Stattdessen würde ich als Fehlermeldung ein Bild mit dem Text "Bitte Cookies aktivieren" zurück liefern. Wenn der S-Parameter im Aufruf fehlt, braucht der Aufrufende auch keine Fehlermeldung 😟.

    Der Nachteil bei dieser Lösung ist, dass die Session-ID im Cookie PHPSESSID gespeichert wird. Wenn Cookies komplett gesperrt sind, funktioniert es nicht.

    Viele Grüße

    Wilfried

    1. @@wisch

      <img src="./showPic.php?name=Bild1&S=<?=$id?>">
      

      Das & sollte in HTML escapet sein:

      <img src="./showPic.php?name=Bild1&amp;S=<?=$id?>">
      

      Und dem img fehlt das zwingend notwendige alt-Attribut:

      <img src="./showPic.php?name=Bild1&amp;S=<?=$id?>" alt="">
      

      Wobei da natürlich eine sinnvolle textuelle Alternative zum Bild drinstehen sollte.

      LLAP 🖖

      --
      “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
      1. @@Gunnar:

        Das & sollte in HTML escapet sein:
        
        <img src="./showPic.php?name=Bild1&amp;S=<?=$id?>">
        

        In einer URL trennt das & die Parameter-Paare eines GET-Requests. Es wird also nicht escaped. Als Wert im Parameter müssen Sonderzeichen mit urlencode() codiert werden. Aus & wird dann %26.

        @@Andi:

        Ich hab's "geschafft" 😟:

        Eine neue PHÜ-Session erhält die ID aus dem PHPSESSION-Cookie, wenn eines existiert. Deshalb ist Deine Lösung mit einer Session-Variablen deutlich besser - hier in verfeinert:

        <?php
         session_start();
         $id = session_id();
         $_SESSION[$id] = "irgendwas";
        ?>
        <img src="./showPic.php?name=Bild1&S=<?=$id?>">
        

        und in showPic.php

        <?php
         session_start();
         $id = session_id();
         if (array_key_exists("S",$_GET)){
          	if (isset($_SESSION[$_GET['S']])) $ergebnis="gut"; // Bild anzeigen
            else
            if ($_GET['S'] == $id) $ergebnis="Session abgelaufen"; // Bitte Seite neu laden
            else $ergebnis="Cookie fehlt"; // Bitte Cookies aktivieren         
         }
         else $ergebnis="ungültiger Aufruf"; // nichts liefern
        

        Die Fehlerbmeldungen in Bildern, damit sie sofort angezeigt werden.

        Alles klar?

        Viele Grüße

        Wilfried

        @@Gunnar: Ich beschränke mich auf das für das Thema unverzichtbare😉.

        1. Tach!

          @@Gunnar: Ich beschränke mich auf das für das Thema unverzichtbare😉.

          Korrekte Maskierung ist unverzichtbar. Alles andere ist ein Fehler. Besonders wenn man seinen Code als "good" auszeichnet.

          Ich würde dich auch bitten, das "good" wegzulassen und nicht grundsätzlich bei jedem deiner Code-Beispiele zu setzen. Es ist vorgesehen das zusammen mit als "bad" markiertem Code zu verwenden, um Unterschiede zwischen gutem und schlechtem Code aufzuzeigen, jedoch nicht als generelles Stilmittel. Ich möchte nicht jedes deiner Postings diesbezüglich korrigieren müssen. Danke fürs Verständnis.

          dedlfix.

          1. Ich meint das alt="" im img-Tag.

            Maskierung ist ein anderes Thema.

            1. @@wisch

              Ich meint das alt="" im img-Tag.

              Auch das ist unverzichtbar.

              Ohne das alt-Attribut lesen Screenreader den Dateinamen vor. (Man könnte darüber philosophieren, ob das nun ein Feature ist oder ein Bug; aber es ist nunmal so.)

              Wenn es keinen Alternativtext gibt, weil

              • das Bild nur zur Dekoration dient, was durch role="none presentation" kenntlich gemacht werden kann (Allerdings gehört das Bild dann eher ins Stylesheet als ins Markup.)
              • das Bild schon anderweitig beschriftet ist (bspw. in figcaption), worauf mit aria-labelledby verwiesen werden kann
              • sich zwei Bilder einen Alternativtext teilen
                (<img src="alles.png" alt="Alles Gute!"/><img src="gute.png" alt=""/>)

              dann ist dennoch alt="" mit leerem Wert anzugeben.

              Ansonsten sollte im alt-Wert was Vernünftiges drinstehen.

              (Und das wäre bei <a href="home"><img src="logo" alt=""/></a> bspw. nicht alt="Logo", sondern sowas wie alt="zur Startseite".)

              LLAP 🖖

              --
              “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory
        2. Hallo

          Das & sollte in HTML escapet sein:
          
          <img src="./showPic.php?name=Bild1&amp;S=<?=$id?>">
          

          In einer URL trennt das & die Parameter-Paare eines GET-Requests. Es wird also nicht escaped.

          In HTML wird & maskiert. Auch, wenn es in einer URL benutzt wird.

          Die URL als URL:

          ./showPic.php?name=Bild1&S=3
          

          Die URL in einem HTML-Element:

          ./showPic.php?name=Bild1&amp;S=3
          

          Als Wert im Parameter müssen Sonderzeichen mit urlencode() codiert werden. Aus & wird dann %26.

          Das ist in diesem Zusammenhang irrelevant.

          @@Gunnar: Ich beschränke mich auf das für das Thema unverzichtbare😉.

          Offensichtlich nicht beziehungsweise auch mal auf das Falsche.

          Tschö, Auge

          --
          Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
          Toller Dampf voraus von Terry Pratchett
        3. @@wisch

          Das & sollte in HTML escapet sein:
          
          <img src="./showPic.php?name=Bild1&amp;S=<?=$id?>">
          

          In einer URL trennt das & die Parameter-Paare eines GET-Requests.

          Richtig. (Wenngleich ; dafür besser geeigent gewesen wäre.)

          Es wird also nicht escaped.

          Falsch. Wenn du einen URL in den HTML-Kontext bringst, muss der wie alles andere auch entsprechend behandelt werden – d.h. Sonderzeichen (das sind in HTML < und &; in Attributwerten auch " bzw. ') müssen ggfs. escapet werden.

          Durch die Toleranz von HTML wird auch – wenn man Glück hat – bei nicht-escapeten & was draus: Wenn der Parser &S= ließt, dann weiß er, dass = nicht mehr zur Entity-Referenz gehört. &S gibt’s nicht, also werden die Zeichen & und S einzeln verwendet.

          Anders bei &copy=. &copy gibt’s: ©. Und auf einmal steht ?name=Bild1©=foo im URI[1] und man wundert sich, warum das nicht funktioniert.

          Protip: Sich nicht auf Glück verlassen! Nicht darüber nachdenken, wann & unbedingt zu escapen sind und wann es auch ohne ginge! Immer escapen!

          Als Wert im Parameter müssen Sonderzeichen mit urlencode() codiert werden. Aus & wird dann %26.

          Das ist was anderes. Dann wäre Bild&S=foo der Wert für den Parameter bild.

          Ich beschränke mich auf das für das Thema unverzichtbare😉.

          Die Beachtung jedwegen Kontextwechsels ist unverzichtbar.

          LLAP 🖖

          --
          “When UX doesn’t consider all users, shouldn’t it be known as ‘Some User Experience’ or... SUX? #a11y” —Billy Gregory

          1. Wobei foo hier für die ID steht, die PHP da mit <?=$id?> reinschreibt. ↩︎

          1. @@Gunnar, Auge, dedlfix:
            Ich habe den W3C-Hinweis jetzt auch gefunden. Als ich mich damit erstmals beschäftigt habe (im letzten Jahrhundert), war es in den Lehrbüchern noch anders.

            Aber:

            Anders bei &copy=. &copy gibt’s: ©. Und auf einmal steht ?name=Bild1©=foo im URI1 und man wundert sich, warum das nicht funktioniert.

            Gibt es inzwischen Browser, die auf das abschließende Semikolon verzichten?
            Also &uuml als &uuml; und &copy= als &copy;= anzeigen?

            Aufwendiger wird es bei generierten Inhalten: Die PHP-Funktion http_build_query kennt zwar seit Version 5.1.2 den Parameter arg_separator, aber wer denkt schon daran? Immerhin werden Sonderzeichen sowieso nach RFC 1738 encoded.

            Aber natürlich habt Ihr Recht.

            Viele Grüße
            Wilfried

            1. Hallo

              Ich habe den W3C-Hinweis jetzt auch gefunden. Als ich mich damit erstmals beschäftigt habe (im letzten Jahrhundert), war es in den Lehrbüchern noch anders.

              Damals hat es einfach niemand erwähnt, viele Autoren vermutlich nicht einmal auf dem Schirm gehabt.

              Anders bei &copy=. &copy gibt’s: ©. Und auf einmal steht ?name=Bild1©=foo im URI1 und man wundert sich, warum das nicht funktioniert.

              Gibt es inzwischen Browser, die auf das abschließende Semikolon verzichten?
              Also &uuml als &uuml; und &copy= als &copy;= anzeigen?

              Nein, warum sollten sie? Das abschließende Semikolon gehört zu einem benannten Zeichen dazu.

              Tschö, Auge

              --
              Wenn man ausreichende Vorsichtsmaßnahmen trifft, muss man keine Vorsichtsmaßnahmen mehr treffen.
              Toller Dampf voraus von Terry Pratchett
    2. Hi,

      Wenn der S-Parameter im Aufruf fehlt, braucht der Aufrufende auch keine Fehlermeldung 😟.

      Die Frage der Fehlerbehandlung ist nicht uninteressant und auch nicht unwichtig. Sofern irgendwas beim Ausliefern eines Images schiefgeht und es sich dabei nicht gerade um eine Exception handelt, sondern möglicherweise um einen vom Benutzer selbst verschuldeten Fehler, sollte Letzterer auch wissen warum und was er daran ändern könnte.

      Im Falle <img> gibt es nur eine einzige Möglichkeit, Fehler nach außen sichtbar zu machen: Als value für das alt=Attribute. MfG

      1. Ausgangspunkt ist, dass das Bild nur angezeigt wird, wenn es in der übergeordneten Seite eingebettet ist. Ein Aufruf, der anders aufgebaut ist, als in der Seite, also ohne S-Parameter, kommt offensichtlich ganz woanders her - nach meinem Verständnis illegal.

        1. Ausgangspunkt ist, dass das Bild nur angezeigt wird, wenn es in der übergeordneten Seite eingebettet ist.

          Ja, das kannst Du entweder über die zugehörige Session oder den Referrer sicherstellen. Manipulierbar ist Beides.

          Ein Aufruf, der anders aufgebaut ist, als in der Seite, also ohne S-Parameter, kommt offensichtlich ganz woanders her - nach meinem Verständnis illegal.

          Das ist eine Frage der Policy. Also eine Frage ob man das will, ob man in einer Bildersuche berücksichtigt werden werden will oder nicht. MfG