Category Archives: myQuellcode

Einmalig gültiger Downloadlink mit PHP

Mal wieder etwas PHP-Gefrickel von mir:

if (isset($_GET['tan'])){
   $tan = preg_replace('/[^a-f0-9]/', '', $_GET['tan']);
   $check = @unlink('tan/'.$tan);
   if ($check === true) {
      $basedir = '/home/downloads/';
      $datei = 'datei.zip';
      $filename = sprintf('%s/%s', $basedir, $datei);
      header('Content-Type: application/octet-stream');
      $save_as_name = basename($datei);
      header('Content-Disposition: attachment; filename='.$save_as_name);
      readfile($filename);
   } else {
      echo 'TAN war FALSCH!';
   }
exit;
}

Dazu noch in das Verzeichnis tan einige leere Dateien mit den Dateinamen
246e238a14fcbe127c16add83492f2ff63ea63d8
b7c39fd38a24e8c5a79f89b22c890bc36b480528
ea072e3a66c938ff2a23aff99c28a11606487ca4
...

kopieren und schon können Downloadlinks nach dem folgenden Muster verteilt werden:
http://download/?tan=246e238a14fcbe127c16add83492f2ff63ea63d8


Die Aufgabenstellung war die folgende: Da möchte jemand digitale Inhalte verkaufen, diese aber erst nach erfolgreicher Bezahlung zur Verfügung stellen. Da pro Jahr nur mit einer Handvoll Bestellungen zu rechnen ist, ist eine automatische Abwicklung viel zu aufwändig. Der Versand eines Downloadlinks per E-Mail ist eine durchaus praktikable Lösung.

Meine Idee dazu ist das TAN-Verfahren wie es beim Online-Banking Verwendung findet.


Meine TAN besteht einfach aus einer leeren Datei, deren Dateiname ein Hash ist, also Ziffern von 0 bis 9 und Buchstaben von a bis f. Das preg_replace sorgt dafür, dass nichts anderes angenommen wird, als diese Zeichen. Per unlink wird die TAN bzw. die Datei gelöscht. Konnte die Datei erfolgreich gelöscht werden, so war die TAN korrekt, wenn nicht, dann eben nicht — ganz einfach. War die TAN korrekt, startet automatisch der Download. Damit der Link zur Datei zum einen nicht in dem Download-Manager des Browsers erkennbar ist und zum zweiten die Datei außerhalb von htdocs liegen kann und nur mit Script runtergeladen werden kann, habe ich mich hiervon inspirieren lassen, bzw. den größen Teil daraus entnommen: http://www.php-faq.de/q-datei-download.html


Wenn in ein paar Jahren die TANs aufgebraucht sind, dann müssen nur Dateien mit entsprechendem Dateinamen in das tan-Verzeichnis kopiert werden. :O)


Update: 04.02.2011 – 13:43 Uhr

Konstruktive Kritik und etwas Nachdenken hat nun die preAlpha-Version zur 1xDownloadLink-V.2011.02 erhoben. ;O)

if (isset($_GET['tan'])){
   $tan = preg_replace('/[^a-f0-9]/', '', $_GET['tan']);
   $check = file_exists('tan/'.$tan);
   if ($check === FALSE) {
      echo 'TAN war FALSCH!';
   } else {
      unlink('tan/'.$tan);
      header('Content-Type: application/octet-stream');
      header('Content-Disposition: attachment; filename=datei.zip');
      header('Content-Length: 2330');
      readfile('/Applications/MAMP/downloads/datei.zip');
   }
}
exit;

Website laden: GET- und POST-Request

Es kann verschiedene Gründe geben weshalb der Download einer Website gewünscht wird. Bei mir hat es meist damit zutun dass ich eine Schwachstelle in einer Website gefunden habe und die anfallenden Daten speichern muss , um diese einfacher auswerten zu können.

GET-Request

Eine Website zu laden, deren URL komplett mit allen übertragenen Parametern in der Adresszeile des Browsers angezeigt wird, ist mit PHP sehr einfach möglich.

$seite = file_get_contents('http://sld.tld/?x=1&y=2');
$datei = fopen('file.txt', 'w');
fputs($datei, $seite);
fclose($datei);

Die Website http://sld.tld/?x=1&y=2, bzw. der Quellcode der im Browser angezeigt werden würde, wird in der Datei file.txt gespeichert.

POST-Request

Werden in der Adresszeile allerdings nicht alle übertragenen Parameter angezeigt, dann muss schon etwas mehr Aufwand betrieben werden, um die Seite speichern zu können.

$post = array(
  'var1' => 'a',
  'var2' => 'b',
  'var3' => 'c'
);

$context_options = array (
  'http' => array (
  'method' => 'POST',
  'header' =>
    "Content-type: application/x-www-form-urlencoded\r\n".
    "Content-length: ".strlen(http_build_query($post))."\r\n".
    "Referer: http://sld.tld \r\n".
    "User-Agent: Mozilla/4.0 (compatible; MSIE 8.0; Windows NT 6.1)\r\n",
  'content' => http_build_query($post)
  )
);

$context = stream_context_create($context_options);
$seite = file_get_contents(
  'http://sld.tld/page',false,$context
);

$datei = fopen('file.txt', 'w');
fputs($datei, $seite);
fclose($datei);

Auch dieses Beispiel speichert die Website in der Datei file.txt ab. Die einzelnen zu übertragenen Parameter werden in dem Array der Variable $post hinterlegt. Da manchmal der Referer, also die aufrufende Seite, für die korrekte Funktion einer Seite erforderlich ist, kann auch dies hinterlegt werden.