<?php
include_once $_SERVER['DOCUMENT_ROOT'] . '/include/shared-manual.inc';
$TOC = array();
$TOC_DEPRECATED = array();
$PARENTS = array();
include_once dirname(__FILE__) ."/toc/security.inc";
$setup = array (
  'home' => 
  array (
    0 => 'index.php',
    1 => 'PHP Manual',
  ),
  'head' => 
  array (
    0 => 'UTF-8',
    1 => 'de',
  ),
  'this' => 
  array (
    0 => 'security.filesystem.php',
    1 => 'Sicherheit des Dateisystems',
    2 => 'Sicherheit des Dateisystems',
  ),
  'up' => 
  array (
    0 => 'security.php',
    1 => 'Sicherheit',
  ),
  'prev' => 
  array (
    0 => 'security.sessions.php',
    1 => 'Session Sicherheit',
  ),
  'next' => 
  array (
    0 => 'security.filesystem.nullbytes.php',
    1 => 'Probleme im Zusammenhang mit Nullbytes',
  ),
  'alternatives' => 
  array (
  ),
  'source' => 
  array (
    'lang' => 'de',
    'path' => 'security/filesystem.xml',
  ),
  'history' => 
  array (
  ),
  'extra_header_links' => 
  array (
    'rel' => 'alternate',
    'href' => '/manual/en/feeds/security.filesystem.atom',
    'type' => 'application/atom+xml',
  ),
);
$setup["toc"] = $TOC;
$setup["toc_deprecated"] = $TOC_DEPRECATED;
$setup["parents"] = $PARENTS;
manual_setup($setup);

contributors($setup);

?>
<div id="security.filesystem" class="chapter">
   <h1 class="title">Sicherheit des Dateisystems</h1>
<h2>Inhaltsverzeichnis</h2><ul class="chunklist chunklist_chapter"><li><a href="security.filesystem.nullbytes.php">Probleme im Zusammenhang mit Nullbytes</a></li></ul>

   <p class="simpara">
    <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> ist hinsichtlich der Berechtigungen auf Datei-
    und Verzeichnisebene von den in den meisten Serversystemen implementierten
    Sicherheitseinstellungen abhängig. Dies verleiht Ihnen Kontrolle darüber,
    welche Dateien im Dateisystem gelesen werden dürfen. Es sollte
    sichergestellt werden, dass alle öffentlich zugänglichen Dateien von allen
    Benutzern, die Zugang zu diesem Dateisystem haben, gelesen werden können,
    ohne die Sicherheit zu gefährden.
   </p>
   <p class="simpara">
    Da <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> entwickelt wurde, um Zugriffe auf das Dateisystem
    auf Benutzebene zu erlauben, ist es natürlich auch möglich, ein
    <abbr title="PHP: Hypertext Preprocessor">PHP</abbr>-Skript zu schreiben, dass Ihnen erlaubt,
    Systemdateien wie <var class="filename">/etc/passwd</var> zu lesen,
    Ethernetverbindungen zu modifizieren, enorme Druckaufträge zu senden
    etc. Dies hat offensichtliche Implikationen, indem Sie sicherstellen
    müssen, dass alle von Ihnen zu lesenden bzw. zu schreibenden Dateien
    auch die richtigen sind.
   </p>
   <p class="simpara">
    Stellen Sie sich folgendes Skript vor, in dem ein Benutzer zum Ausdruck
    bringt, dass er eine Datei in seinem Heimatverzeichnis löschen möchte.
    Es wird davon ausgegangen, dass ein <abbr title="PHP: Hypertext Preprocessor">PHP</abbr>-Webinterface
    regelmäßig für das Dateimanagement verwendet wird und dass der
    Apache-Benutzer berechtigt ist, in seinem Heimatverzeichnis Dateien zu
    löschen.
   </p>
   <p class="para">
    <div class="example" id="example-1">
     <p><strong>Beispiel #1 Schlechte Variablenprüfung führt zu....</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// Löschen einer Datei aus dem Heimatverzeichnis des Users<br /></span><span style="color: #0000BB">$username </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_name'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">$userfile </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">$homedir  </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">);<br /><br />echo </span><span style="color: #DD0000">"Die Datei wurde gelöscht!"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    Da Benutzer- und Dateiname über ein Benutzerformular bereitgestellt werden,
    kann jeder jemand anderes Benutzer- und Dateinamen übertragen und so
    Dateien löschen, ohne über die entsprechnde Erlaubnis zu verfügen.
    In diesem Fall empfiehlt es sich, eine andere Form der Authentifizierung zu
    verwenden. Stellen Sie sich vor was passieren würde, wenn die übertragenen
    Variablen <code class="literal">&quot;../etc/&quot;</code> und <code class="literal">&quot;passwd&quot;</code>
    beinhalten würden.
    Der Code würde dann folgendermaßen aussehen:
    <div class="example" id="example-2">
     <p><strong>Beispiel #2 ... Ein Angriff auf das Dateisystem</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// Löscht eine Datei irgendwo auf der Festplatte, wo der Benutzer<br />// die nötigen Rechte besitzt. Wenn PHP root-Zugriff hat:<br /></span><span style="color: #0000BB">$username </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_name'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// "../etc"<br /></span><span style="color: #0000BB">$userfile </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// "passwd"<br /></span><span style="color: #0000BB">$homedir  </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">; </span><span style="color: #FF8000">// "/home/../etc"<br /><br /></span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">); </span><span style="color: #FF8000">// "/home/../etc/passwd"<br /><br /></span><span style="color: #007700">echo </span><span style="color: #DD0000">"Die Datei wurde gelöscht!"</span><span style="color: #007700">;</span><span style="color: #0000BB">?&gt;<br /></span><br />?&gt;</span></code></div>
     </div>

    </div>
    Es gibt zwei wichtige Kriterien die Sie beachten sollten, um diese
    Dinge zu vermeiden:
    <ul class="itemizedlist">
     <li class="listitem">
      <span class="simpara">
       Erteilen Sie dem <abbr title="PHP: Hypertext Preprocessor">PHP</abbr> Web-user (Binärdatei) nur eingeschränkte Rechte.
      </span>
     </li>
     <li class="listitem">
      <span class="simpara">
       Prüfen Sie alle übertragenen Variablen.
      </span>
     </li>
    </ul>
    Hier ist ein verbessertes Skript:
    <div class="example" id="example-3">
     <p><strong>Beispiel #3 Etwas sicherere Prüfung des Dateinamens</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br /></span><span style="color: #FF8000">// Löscht eine Datei von der Festplatte, auf die<br />// der PHP-Benutzer Zugriff hat.<br /></span><span style="color: #0000BB">$username </span><span style="color: #007700">= </span><span style="color: #0000BB">$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_USER'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// using an authentication mechanism<br /></span><span style="color: #0000BB">$userfile </span><span style="color: #007700">= </span><span style="color: #0000BB">basename</span><span style="color: #007700">(</span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">]);<br /></span><span style="color: #0000BB">$homedir  </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$filepath </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br />if (</span><span style="color: #0000BB">file_exists</span><span style="color: #007700">(</span><span style="color: #0000BB">$filepath</span><span style="color: #007700">) &amp;&amp; </span><span style="color: #0000BB">unlink</span><span style="color: #007700">(</span><span style="color: #0000BB">$filepath</span><span style="color: #007700">)) {<br />    </span><span style="color: #0000BB">$logstring </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$filepath</span><span style="color: #DD0000"> gelöscht\n"</span><span style="color: #007700">;<br />} else {<br />    </span><span style="color: #0000BB">$logstring </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$filepath</span><span style="color: #DD0000"> konnte nicht gelöscht\n"</span><span style="color: #007700">;<br />}<br /><br /></span><span style="color: #0000BB">$fp </span><span style="color: #007700">= </span><span style="color: #0000BB">fopen</span><span style="color: #007700">(</span><span style="color: #DD0000">"/home/logging/filedelete.log"</span><span style="color: #007700">, </span><span style="color: #DD0000">"a"</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">fwrite</span><span style="color: #007700">(</span><span style="color: #0000BB">$fp</span><span style="color: #007700">, </span><span style="color: #0000BB">$logstring</span><span style="color: #007700">);<br /></span><span style="color: #0000BB">fclose</span><span style="color: #007700">(</span><span style="color: #0000BB">$fp</span><span style="color: #007700">);<br /><br />echo </span><span style="color: #0000BB">htmlentities</span><span style="color: #007700">(</span><span style="color: #0000BB">$logstring</span><span style="color: #007700">, </span><span style="color: #0000BB">ENT_QUOTES</span><span style="color: #007700">);<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
    Auch dies nicht ohne Schwachstellen. Wenn Ihr Authentifizierungssystem
    Benutzern erlauben sollte, deren eigene Logins zu kreieren, und ein
    Benutzer wählt den Login <code class="literal">&quot;../etc/&quot;</code>, ist das System
    erneut angreifbar. Aus diesem Grund sollten Sie eventuell eine speziellere
    Überprüfung durchführen
    <div class="example" id="example-4">
     <p><strong>Beispiel #4 Sicherere Dateinamensprüfung</strong></p>
     <div class="example-contents">
<div class="phpcode"><code><span style="color: #000000"><span style="color: #0000BB">&lt;?php<br /><br />$username     </span><span style="color: #007700">= </span><span style="color: #0000BB">$_SERVER</span><span style="color: #007700">[</span><span style="color: #DD0000">'REMOTE_USER'</span><span style="color: #007700">]; </span><span style="color: #FF8000">// Nutzung eines Authentifikationsmechanismus<br /></span><span style="color: #0000BB">$userfile     </span><span style="color: #007700">= </span><span style="color: #0000BB">$_POST</span><span style="color: #007700">[</span><span style="color: #DD0000">'user_submitted_filename'</span><span style="color: #007700">];<br /></span><span style="color: #0000BB">$homedir      </span><span style="color: #007700">= </span><span style="color: #DD0000">"/home/</span><span style="color: #0000BB">$username</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br /></span><span style="color: #0000BB">$filepath     </span><span style="color: #007700">= </span><span style="color: #DD0000">"</span><span style="color: #0000BB">$homedir</span><span style="color: #DD0000">/</span><span style="color: #0000BB">$userfile</span><span style="color: #DD0000">"</span><span style="color: #007700">;<br /><br />if (!</span><span style="color: #0000BB">ctype_alnum</span><span style="color: #007700">(</span><span style="color: #0000BB">$username</span><span style="color: #007700">) || !</span><span style="color: #0000BB">preg_match</span><span style="color: #007700">(</span><span style="color: #DD0000">'/^(?:[a-z0-9_-]|\.(?!\.))+$/iD'</span><span style="color: #007700">, </span><span style="color: #0000BB">$userfile</span><span style="color: #007700">)) {<br />    die(</span><span style="color: #DD0000">"Ungültiger Benutzer- oder Dateiname"</span><span style="color: #007700">);<br />}<br /><br /></span><span style="color: #FF8000">// etc.<br /><br /></span><span style="color: #0000BB">?&gt;</span></span></code></div>
     </div>

    </div>
   </p>
   <p class="para">
    Abhängig vom Betriebssystem gibt es eine große Anzahl Dateien, auf die Sie
    achten sollten, inklusive Einträge für Geräte (<var class="filename">/dev/</var>
    oder <var class="filename">com1</var>), Konfigurationsdateien (die Dateien in
    <var class="filename">/etc/</var> und die <code class="literal">.ini</code>-Dateien),
    allgemein bekannte Verzeichnisse (<var class="filename">/home/</var>,
    <var class="filename">My Documents</var>) etc. Aus diesem Grund ist es für
    gewöhnlich einfacher, eine Richtlinie zu erstellen, in der alles verboten
    ist, was Sie nicht ausdrücklich erlauben.
   </p>
   

  </div>
<?php manual_footer($setup); ?>