Navigation
 Startseite
 Fachbücher
 Anzeigenmarkt
 Forum
 Webmaster News
 Script Newsletter
 Kontakt
 Script Installation
 Php
 Php Tutorials
 Lernpfade
 Webhoster Vergleich
 Impressum

Community-Bereich
 kostenlos Registrieren
 Anmelden
 Benutzerliste

Script Datenbank
 Script Archiv
 Script Top 20
 Screenshots
 Testberichte

Suche
 

Unsere Php Scripts
 Counter Script
 Umfrage Script
 Bilder Upload Script
 Terminverwaltung
 Simple PHP Forum
 RSS Grabber

Tools und Generatoren
 .htpasswd Generator
 md5 Generator
 base64 Generator
 Markdown to HTML
 Colorpicker
 Unix timestamp Tool
 Unit Test Generator
 TLD Liste
 Webkatalog‑Verzeichnis

Hosterplus.de
Bekommen Sie Speicherplatz (Webspace), Domains und...
https://www.Hosterplus.de
Artfiles.de
Bietet Serviceorientierte Internetdienstleistungen...
https://www.Artfiles.de
 
 
 

PHP finfo: MIME-Type sicher per Magic-Bytes erkennen

Sie befinden sich: Home > Php Tutorial > PHP finfo: MIME-Type sicher...

PHP finfo: MIME-Type sicher per Magic-Bytes erkennen
Eintrag am:
12.07.2026
Hits / Besucher:
99
Sprache:
  Deutsch
Tutorial Art:
eigenes
Eingetragen von:
Merkliste:
 
Beschreibung

Datei-Uploads gehören zu den sicherheitskritischsten Stellen einer PHP-Anwendung, denn beim Dateityp darf der Browser lügen. Mit PHP finfo_file und der Fileinfo-Erweiterung lässt sich der echte MIME-Type einer Datei direkt aus ihrem Inhalt ermitteln, statt sich auf Endungen oder Client-Angaben zu verlassen.

Was leistet PHP finfo_file und die Fileinfo-Erweiterung?

Wer in PHP Datei-Uploads verarbeitet oder Dateien aus externen Quellen einliest, braucht eine verlässliche Antwort auf eine wichtige Frage: Welchen Typ hat diese Datei wirklich? Genau das macht PHP finfo_file. Die Funktion liest die ersten Bytes einer Datei (die sogenannten Magic-Bytes) und ermittelt daraus den tatsächlichen MIME-Type. Im Gegensatz zur Dateiendung oder zum vom Browser gemeldeten $_FILES['type']-Wert lässt sich dieser Wert vom Client nicht manipulieren und ist die verlässliche Grundlage für weitere Prüfungen.

Illustration zum Tutorial: PHP finfo: MIME-Type sicher per Magic-Bytes erkennen

Die folgenden Abschnitte zeigen den prozeduralen Aufruf, die Whitelist-Prüfung und einen sauberen Endung-zu-MIME-Abgleich gegen Polyglot-Dateien.

In Upload-Workflows ist das ein Sicherheitsthema. Eine Datei mit der Endung .jpg muss noch lange kein Bild sein, sie kann auch verstecktes PHP enthalten. Dieses Tutorial zeigt, wie sich der echte MIME-Type per Fileinfo-Erweiterung ermitteln lässt, wie man eine MIME-Whitelist baut und welche Stolperfallen über Polyglot-Dateien zu beachten sind. Die Fileinfo-Erweiterung ist seit PHP 5.3 standardmäßig aktiv und ist die offizielle Empfehlung anstelle des veralteten mime_content_type().

Syntax und Aufruf von PHP finfo_file

Im klassischen prozeduralen Stil arbeiten drei Funktionen zusammen: finfo_open() initialisiert die Datenbank, PHP finfo_file liest die Datei und finfo_close() räumt auf. Seit PHP 8.1 ist finfo zusätzlich als Objekt verfügbar.

<?php

finfo_open(int $flags = FILEINFO_NONE, string $magic_database = ''): finfo|false
finfo_file(finfo $finfo, string $filename, int $flags = 0, ?resource $context = null): string|false
finfo_close(finfo $finfo): bool

Die wichtigste Konstante für Uploads ist FILEINFO_MIME_TYPE. Sie liefert den reinen MIME-String wie image/jpeg oder application/pdf. FILEINFO_MIME ergänzt das Charset (text/html; charset=UTF-8), FILEINFO_MIME_ENCODING liefert nur das Charset. Im Fehlerfall geben die Funktionen false zurück.

Standard-Pattern PHP finfo_file: finfo_open, finfo_file, finfo_close

Wer PHP finfo_file zum ersten Mal nutzt, ist von der Schlichtheit überrascht. Im einfachsten Fall sind es drei Zeilen. Der Aufruf von finfo_open() lädt die magic-Datenbank, finfo_file() ermittelt den MIME-Type, finfo_close() gibt die Ressource frei.

<?php

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$mime = finfo_file($finfo, 'beispiel.pdf');
finfo_close($finfo);

echo $mime;
/* z.B. application/pdf */

Wer mehrere Dateien hintereinander prüfen will, sollte finfo_open() einmalig aufrufen und das gleiche $finfo-Handle wiederverwenden. Jeder Aufruf von finfo_open() lädt intern die Magic-Datenbank, das ist auf großen Listen unnötig teuer.

<?php

$finfo = finfo_open(FILEINFO_MIME_TYPE);
$dateien = ['a.pdf', 'b.jpg', 'c.png'];

foreach ($dateien as $datei) {
echo $datei . ' -> ' . finfo_file($finfo, $datei) . "\n";
}

finfo_close($finfo);

Magic-Bytes mit PHP finfo_file vs. $_FILES type aus dem Browser

PHP finfo_file zeigt seine Stärke gerade gegenüber Browser-Angaben. Hier liegt der Sicherheits-Kern. Beim Upload schickt der Browser einen Content-Type-Header mit, den PHP unter $_FILES['type'] zur Verfügung stellt. Diese Information stammt aber komplett vom Client und kann mit beliebigen Tools (curl, Postman, eigener HTTP-Client) frei gesetzt werden.

<?php

/* UNSICHER, NICHT MACHEN */
if ($_FILES['datei']['type'] !== 'image/jpeg') {
exit('Nur JPG erlaubt');
}

/* SICHER */
$finfo = new finfo(FILEINFO_MIME_TYPE);
if ($finfo->file($_FILES['datei']['tmp_name']) !== 'image/jpeg') {
exit('Nur JPG erlaubt');
}

Magic-Bytes sind die ersten Bytes einer Datei und folgen festen Konventionen. Ein JPEG beginnt mit FF D8 FF, ein PNG mit 89 50 4E 47, ein PDF mit 25 50 44 46. finfo_file() liest diese Bytes und vergleicht sie gegen die Magic-Datenbank des Servers. Das Ergebnis spiegelt den tatsächlichen Datei-Inhalt, nicht das, was der Browser behauptet.

MIME-Whitelist für Uploads mit PHP finfo_file

Das Standard-Pattern für sichere Uploads kombiniert PHP finfo_file mit einer expliziten Whitelist erlaubter MIME-Strings. Alles, was nicht in der Liste steht, wird abgelehnt. Diese positive Liste ist sicherer als eine schwarze Liste, weil neue Datei-Typen nicht ungewollt durchrutschen.

<?php

$erlaubt = ['image/jpeg', 'image/png', 'image/webp'];

if ($_FILES['bild']['error'] !== UPLOAD_ERR_OK) {
exit('Upload-Fehler');
}

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES['bild']['tmp_name']);

if (!in_array($mime, $erlaubt, true)) {
exit('Dateityp ' . htmlspecialchars($mime) . ' nicht erlaubt.');
}

move_uploaded_file(
$_FILES['bild']['tmp_name'],
'uploads/' . basename($_FILES['bild']['name'])
);

Der true-Parameter im in_array() sorgt für einen strikten Vergleich, das schließt PHPs Type-Juggling aus. Anschließend wird die Datei mit move_uploaded_file in den Upload-Ordner verschoben, das wiederum prüft, ob die Quelle wirklich aus einem HTTP-Upload stammt. Beide Prüfungen zusammen bilden eine solide Basis.

flowchart TD
    A[Upload empfangen] --> B[finfo_open / new finfo]
    B --> C[finfo_file Magic-Bytes lesen]
    C --> D{MIME in Whitelist?}
    D -->|Ja| E[Datei akzeptieren]
    D -->|Nein| F[Datei ablehnen]
    E --> G[move_uploaded_file]

finfo_buffer als Variante zu PHP finfo_file ohne Datei

Manchmal lässt sich PHP finfo_file nicht direkt einsetzen, weil schlicht keine Datei da ist. Nicht immer liegt der Inhalt als Datei vor. Manche Skripte laden Bytes per cURL, lesen sie aus einer Datenbank-Spalte oder erhalten sie als Base64-codierten String aus einer API. Für diesen Fall gibt es finfo_buffer(). Die Funktion arbeitet auf einem String und braucht keine lokale Datei.

<?php

$bytes = file_get_contents('https://example.com/bild.jpg');

$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->buffer($bytes);

echo $mime;
/* image/jpeg */

Das ist nützlich in API-Endpunkten, die ein Bild als Base64-String entgegennehmen. Mit file_get_contents für URLs ließe sich die Datei zwar zwischenspeichern, aber der Umweg über eine temporäre Datei ist überflüssig, wenn die Bytes ohnehin schon im Speicher liegen.

Objekt-Style für PHP finfo_file ab PHP 8.1

Mit PHP finfo_file lässt sich ab PHP 8.1 auch komplett objektorientiert arbeiten. Seit PHP 8.1 ist finfo ein Objekt mit gleichnamigen Methoden. Funktional identisch, aber syntaktisch eleganter. finfo_close() ist nicht mehr nötig, der Garbage Collector räumt das Objekt am Ende auf.

<?php

$finfo = new finfo(FILEINFO_MIME_TYPE);

echo $finfo->file('beispiel.pdf') . "\n";
echo $finfo->buffer(file_get_contents('beispiel.png'));

Bestehender Code mit finfo_open() funktioniert weiterhin und wird unter der Haube auf das Objekt abgebildet. Wer Legacy-Code wartet, muss also nicht hektisch umschreiben. Bei neuem Code ist der Objekt-Style die übersichtlichere Wahl.

Stolperfallen bei PHP finfo_file: Polyglot-Dateien und Defense-in-Depth

So nützlich PHP finfo_file ist, eine Prüfung allein reicht nicht immer. Es gibt sogenannte Polyglot-Dateien, die gleichzeitig als gültiges Bild und als gültiger PHP-Code interpretierbar sind. Ein Angreifer kann ein Bild bauen, das finfo_file() brav als image/jpeg meldet, das aber von einem PHP-Interpreter beim Aufruf trotzdem ausgeführt wird. Die Verteidigung dagegen besteht aus mehreren Schichten.

Erstens: MIME-Prüfung mit finfo_file() als Basis. Zweitens: Endung mit MIME abgleichen, weil ein .php mit image/jpeg-Inhalt kein gültiger Upload ist. Drittens: Upload-Verzeichnis so konfigurieren, dass der Webserver dort kein PHP ausführt (per .htaccess oder Apache-Config). Viertens: Bilder bei Bedarf neu encodieren, etwa mit der GD-Library, weil dabei eingebetteter Schadcode verloren geht.

<?php

$mapping = [
'jpg' => 'image/jpeg',
'jpeg' => 'image/jpeg',
'png' => 'image/png',
'webp' => 'image/webp',
];

$endung = strtolower(pathinfo($_FILES['datei']['name'], PATHINFO_EXTENSION));
$finfo = new finfo(FILEINFO_MIME_TYPE);
$mime = $finfo->file($_FILES['datei']['tmp_name']);

if (!isset($mapping[$endung]) || $mapping[$endung] !== $mime) {
exit('Endung und Inhalt passen nicht zusammen.');
}

Diese Mismatch-Erkennung schlägt sofort an, wenn jemand eine .jpg-Datei hochlädt, die in Wirklichkeit ein PDF oder eine HTML-Seite ist. Im Zusammenspiel mit der Whitelist und einer ggf. ergänzenden filter_var-Prüfung für URLs und E-Mails entsteht eine robuste Eingabe-Validierung.

Fazit zu PHP finfo_file

PHP finfo_file ist die Standardlösung in PHP, um den echten MIME-Type einer Datei per Magic-Bytes zu ermitteln. PHP finfo_file ist sicherer als $_FILES['type'], weil der Wert direkt aus dem Datei-Inhalt stammt und nicht vom Client. Mit einer MIME-Whitelist, dem Endung-zu-MIME-Mismatch-Check und dem ergänzenden Re-Encoding entsteht eine solide Upload-Sicherheit. Der moderne Objekt-Style mit new finfo() macht den Code seit PHP 8.1 noch lesbarer, das prozedurale Pattern bleibt für Legacy-Projekte voll funktionstüchtig.

 


 

Kommentare (0)

Noch keine Kommentare. Sei der Erste!

Melde dich an, um einen Kommentar zu schreiben.
Bücherregal mit drei Büchern: 'PHP 4 - Grundlagen und Profiwissen' von Hanser Verlag, 'Webdesign in a Nutshell' von O'Reilly Verlag, und 'Webgestaltung' von Galileo Computing.