Wenn Sie ein WordPress-Veteran sind, erinnern Sie sich sicher an TimThumb. Es war ein kleines PHP-Skript, das um 2010 in fast jedem “Premium-Theme” zu finden war. Es ermöglichte einfaches Zuschneiden und Skalieren von Bildern im laufenden Betrieb.
Im August 2011 wurde darin eine kritische Zero-Day-Sicherheitslücke entdeckt, über die Angreifer PHP-Code auf Servern mit dem Skript hochladen und ausführen konnten. Das markierte das Ende der Ära der “einfachen Skripte”.
Heute, im Jahr 2026, verfügt WordPress über eine leistungsstarke Engine für die Medienhandhabung. Wenn Sie immer noch timthumb.php in Ihrem Theme sehen, löschen Sie es sofort. Dieser Leitfaden zeigt, wie man es professionell macht.
Warum TimThumb unsicher war
TimThumb arbeitete im laufenden Betrieb: Es nahm ein Bild von einer URL, verarbeitete es und speicherte es in einem Cache. Die Probleme waren zahlreich und ernst:
Sicherheit: Es ermöglichte Remote Code Execution (RCE). Mark Maunder machte die Lücke am 1. August 2011 öffentlich, nachdem sein eigenes Blog angegriffen worden war. Das Skript verglich den Hostnamen nur teilweise mit seiner Whitelist von Domains, also konnte ein Angreifer es eine PHP-Datei in sein Cache-Verzeichnis laden lassen und diese Datei danach mit einer direkten Anfrage ausführen. Das bedeutete vollen Zugriff auf die Website und potenziell auf den ganzen Server. Maunder empfahl außerdem, das WordPress-Verzeichnis nach der Funktion
base64_decodeund langen kodierten Zeichenketten zu durchsuchen, der typischen Spur von eingeschleustem Code.Performance: Es belastete den PHP-Server bei jeder neuen Bildanfrage. Bei jedem Seitenaufruf mit TimThumb-Bildern musste der Server PHP starten, den Cache prüfen, das Bild bei Bedarf verarbeiten und ausliefern. Auf Websites mit viel Traffic bedeutete das viele zusätzliche PHP-Aufrufe, die CPU und Arbeitsspeicher verbrauchten. Bildverarbeitung ist rechenintensiv, und sie live über PHP zu erledigen war sehr ineffizient im Vergleich zur Auslieferung vorab erzeugter statischer Dateien.
Keine Integration: Es erkannte die WordPress-Mediathek nicht. TimThumb arbeitete komplett außerhalb des WordPress-Ökosystems. Es nutzte weder Hooks noch Core-Funktionen, speicherte verarbeitete Bilder nicht in der Datenbank und profitierte nicht von den Verbesserungen, die WordPress an seiner Medienverwaltung vornahm. TimThumb-Bilder erschienen nicht in der Mediathek, ließen sich nicht im Backend verwalten und hatten weder Alternativtext noch Beschreibungen oder Bildnachweise.
Chronik der TimThumb-Sicherheitslücken
Die Geschichte des Skripts passt in vier Daten, und jedes ist in Primärquellen belegt:
| Datum | Was geschah | Quelle |
|---|---|---|
| August 2011 | Fehler in der Domain-Whitelist der Versionen vor 2.0, aktiv ausgenutzt | NVD, CVE-2011-4106 |
| August 2011 | Maunder schreibt das Skript als WordThumb neu, das in TimThumb 2.0 aufgeht | Blog von Mark Maunder |
| Juni 2014 | Remote Command Execution in TimThumb 2.8.13 und WordThumb 1.07, wenn die Funktion WebShot aktiviert ist | NVD, CVE-2014-4663 |
| 27. September 2014 | Der Autor Ben Gillbanks stellt die Pflege ein | BinaryMoon |
Die Kennung CVE-2011-4106 wurde erst im Oktober 2013 in der NVD veröffentlicht, die offizielle Beschreibung hält aber fest, dass die Lücke im August 2011 ausgenutzt wurde. Maunder schätzte die Verbreitung damals indirekt: Google lieferte über 39 Millionen Treffer für den Namen des Skripts. Seine Grunddiagnose gilt weiterhin für jeden Bildskalierer, der in einem Theme steckt:
“timthumb.php ist von Natur aus unsicher, weil es darauf angewiesen ist, Dateien in ein Verzeichnis schreiben zu können, auf das die Besucher Ihrer Website zugreifen können.”
Mark Maunder, 1. August 2011, eigene Übersetzung
Der Patch von 2011 schloss dieses konkrete Loch, änderte aber nicht die Konstruktion. Drei Jahre später kam die WebShot-Lücke, die Shell-Metazeichen aus dem Parameter src an einen Systembefehl weitergab. Gillbanks schrieb in seiner Ankündigung von 2014, er habe den Code seit Jahren kaum angefasst, und wer TimThumb weiter nutze, tue das auf eigenes Risiko. Ein Theme, das die Datei noch enthält, stützt sich also auf Code, der seit über einem Jahrzehnt nicht mehr gepflegt wird.
Wie man native Bildgrößen mit add_image_size nutzt
WordPress verfügt seit Jahren über die Funktion add_image_size(). Sie erlaubt es Ihnen, Formate zu definieren, die das System beim Hochladen automatisch generiert. Das ist der effizienteste und sicherste Weg, die verschiedenen Bildgrößen zu verwalten, die Ihr Theme braucht.
Bildgrößen in functions.php registrieren
function wppoland_setup_theme() {
// Unterstützung für Beitragsbilder aktivieren
add_theme_support( 'post-thumbnails' );
// Standardgrößen (weicher Beschnitt: behält Proportionen bei)
add_image_size( 'blog-list', 800, 400 );
// Harter Beschnitt (schneidet Überschuss ab)
// WordPress schneidet genau die Mitte des Bildes aus
add_image_size( 'team-member', 300, 300, true );
// Beschnitt mit Positionierung (z. B. von oben, von links)
add_image_size( 'hero-banner', 1920, 600, ['center', 'top'] );
}
add_action( 'after_setup_theme', 'wppoland_setup_theme' );Wenn Sie eigene Größen mit add_image_size() definieren, erzeugt WordPress alle Varianten beim Hochladen. Die aufwendige Verarbeitung läuft einmal beim Upload und nicht bei jedem Seitenaufruf. Deshalb ist dieser Ansatz deutlich schneller als jede Skalierung im laufenden Betrieb.
Es lohnt sich, die drei Beschnittmodi zu kennen. Der weiche Beschnitt (soft crop) ist Standard, wenn Sie keinen Beschnittparameter angeben. WordPress verkleinert das Bild so, dass es in die angegebenen Maße passt, und behält das Seitenverhältnis bei; eine der Seiten kann also kleiner ausfallen als angegeben. Der harte Beschnitt (hard crop), aktiviert mit true als drittem Parameter, erzwingt exakt die angegebenen Maße und schneidet die Ränder ab. Der positionierte Beschnitt legt fest, von welcher Stelle des Bildes aus zugeschnitten wird, was bei Bannern hilft, deren Hauptmotiv meist oben liegt.
Bildgröße im Template ausgeben (single.php)
if ( has_post_thumbnail() ) {
the_post_thumbnail( 'hero-banner', ['class' => 'img-fluid'] );
}Wenn Sie bereits die ID des Anhangs haben, erledigt wp_get_attachment_image() dasselbe außerhalb des Loops:
echo wp_get_attachment_image( $attachment_id, 'blog-list' );Vorteil: Bilder werden einmal generiert (beim Upload). Sie werden als fertige statische Dateien ausgeliefert. Keine PHP-Last bei der Anzeige. Statische Dateien lassen sich außerdem leicht auf dem Server und im CDN cachen.
Wie man Thumbnails mit WP-CLI neu erzeugt
Wenn Sie einem bestehenden Theme neue Bildgrößen hinzufügen, fehlen den bereits hochgeladenen Bildern die neuen Varianten. Die Thumbnails müssen neu erzeugt werden, am effizientesten über WP-CLI:
wp media regenerate --yesFür große Mediatheken bietet die Dokumentation von wp media regenerate Optionen, um die Arbeit einzugrenzen: --only-missing erzeugt nur fehlende Größen, --image_size=<name> erzeugt eine einzelne Größe neu, und --skip-delete behält alte Thumbnails, falls jemand von außen darauf verlinkt:
wp media regenerate --only-missing --yes
wp media regenerate --image_size=hero-banner --yesWelche Bildgrößen WordPress standardmäßig erzeugt
Bevor Sie eigene Größen registrieren, lohnt der Blick darauf, wie viele Dateien der Core bei jedem Upload bereits anlegt. Die Standardwerte der Optionen im WordPress-Schema lauten:
| Name | Standardmaße | Seit |
|---|---|---|
thumbnail | 150 × 150, harter Beschnitt | Medien-Einstellungen |
medium | höchstens 300 × 300 | Medien-Einstellungen |
medium_large | 768 breit, ohne Höhenlimit | WordPress 4.4 |
large | höchstens 1024 × 1024 | Medien-Einstellungen |
1536x1536 | höchstens 1536 × 1536 | WordPress 5.3 |
2048x2048 | höchstens 2048 × 2048 | WordPress 5.3 |
Die beiden letzten fügt die interne Funktion _wp_add_additional_image_sizes() hinzu, und ein Kommentar im Core-Code rät davon ab, sie zu ändern, weil der Name die Maße widerspiegelt. Jedes add_image_size() Ihres Themes kommt zu dieser Liste hinzu, ein einzelner Upload erzeugt also schnell zehn Dateien oder mehr.
WordPress 5.3 führte außerdem einen Schwellenwert für große Bilder ein. Überschreitet das Original 2560 Pixel in Breite oder Höhe, erzeugt der Core eine verkleinerte Kopie mit dem Suffix -scaled und nutzt sie als Größe “full”; das Original bleibt erhalten, sein Name steht in den Metadaten des Anhangs (original_image). Der Wert lässt sich mit dem Filter big_image_size_threshold ändern oder abschalten:
// Schwelle auf 4000 px anheben
add_filter( 'big_image_size_threshold', fn() => 4000 );
// Ganz abschalten
add_filter( 'big_image_size_threshold', '__return_false' );Für srcset gibt es eine parallele Grenze: Der Filter max_srcset_image_width schließt im aktuellen Core-Code Kandidaten aus, die breiter als 2048 Pixel sind. Braucht ein Theme größere Kandidaten für Bildschirme mit hoher Pixeldichte, ist dieser Filter die Stellschraube, nicht ein Skalierungsskript.
Wie man WordPress-Bilder per CDN skaliert
Native Größen haben einen Nachteil: Wenn Sie das Theme wechseln, müssen Sie Thumbnails neu generieren (z. B. mit dem Plugin Regenerate Thumbnails), was bei einer 100GB-Bibliothek ewig dauert.
Im Jahr 2026 sind Server schnell und CDNs billig. Wir nutzen oft einen hybriden Ansatz oder externe Dienste, die Bilder am Edge, nahe beim Nutzer, verarbeiten.
Bilder per URL-Parameter im CDN skalieren
Anstatt Ihren PHP-Server zu belasten, nutzen Sie URL-Parameter, und das CDN übernimmt die Verarbeitung. Die genaue Syntax hängt vom Anbieter ab; schematisch:
<img src="https://ihreseite.de/wp-content/uploads/bild.jpg?width=400&height=300&format=avif">Das Original liegt auf Ihrem Server, das CDN skaliert es, wandelt das Format um und liefert die optimierte Version aus. Sie benötigen dafür kein PHP-Skript auf Ihrem Server.
Die Vorteile sind klar. Erstens müssen Sie für neue Größen keine Thumbnails neu erzeugen, weil das CDN jede Größe auf Anfrage erstellt. Zweitens läuft die Formatumwandlung automatisch: Das CDN kann AVIF an Browser liefern, die es unterstützen, und WebP als Fallback. Drittens landet jede Transformation im Edge-Cache, die Rechenarbeit fällt also nur einmal an.
Cloudflare Image Resizing
Bei Cloudflare fordert man die Transformation direkt in der URL an, im Format https://<zone>/cdn-cgi/image/<optionen>/<originalbild>, zum Beispiel /cdn-cgi/image/width=400,format=auto/wp-content/uploads/2026/10/foto.jpg. Laut Cloudflare-Dokumentation funktioniert das in Zonen mit aktivierten Transformationen, und format=auto liefert das effizienteste Format, das der anfragende Browser unterstützt. Ein Worker ist dafür nicht nötig; Worker lohnen sich, wenn Sie eigene Regeln brauchen, etwa das automatische Umschreiben der URLs unter /wp-content/uploads/.
Wie man srcset und sizes bei WordPress-Bildern einsetzt
WordPress generiert automatisch das srcset-Attribut für Ihre Bilder, sodass der Browser die passende Größe für das Gerät wählen kann (Handy vs. Desktop 4K). Die Funktion kam mit WordPress 4.4 und wurde seither weiterentwickelt.
<!-- WordPress generiert dies automatisch: -->
<img src="bild-800x400.jpg"
srcset="bild-300x150.jpg 300w,
bild-800x400.jpg 800w,
bild-1024x512.jpg 1024w"
sizes="(max-width: 600px) 100vw, 800px">Das Attribut srcset listet alle verfügbaren Varianten des Bildes mit ihrer Breite in Pixeln. Der Browser kombiniert diese Angabe mit dem Attribut sizes und wählt die Datei, die am besten zu Bildschirmgröße, Pixeldichte und Viewport-Breite passt.
Laut der Entwicklernotiz zu WordPress 4.4 entspricht der Standardwert von sizes dem Ausdruck (max-width: {breite}px) 100vw, {breite}px, und wenn das HTML im Inhalt bereits srcset oder sizes enthält, lässt WordPress sie unverändert. Ihre Aufgabe als Entwickler ist es, sizes über den Filter wp_calculate_image_sizes korrekt zu definieren. Damit beschreiben Sie, wie das Bild an den Breakpoints Ihres Layouts dargestellt wird, damit der Browser optimal wählen kann:
add_filter( 'wp_calculate_image_sizes', function( $sizes, $size, $image_src, $image_meta ) {
// Für Bilder in Beiträgen
if ( is_singular() ) {
return '(max-width: 768px) 100vw, (max-width: 1200px) 75vw, 800px';
}
return $sizes;
}, 10, 4 );Welche Ladeattribute WordPress Bildern hinzufügt
Seit WordPress 5.5 wird das Attribut loading="lazy" automatisch zu Bildern hinzugefügt. Bilder außerhalb des ersten Viewports werden erst geladen, wenn der Nutzer zu ihnen scrollt, was den ersten Seitenaufbau beschleunigt.
WordPress 6.1 ergänzte wp_get_attachment_image() um das Attribut decoding="async", mit dem der Browser Bilder dekodieren kann, ohne das Rendering zu blockieren. Seit WordPress 6.3 entscheidet eine einzige Funktion über alle drei Attribute, wp_get_loading_optimization_attributes(). Sie versieht das erste ausreichend große Bild mit fetchpriority="high" (die Standardschwelle liegt bei 50 000 Pixeln Fläche, Filter wp_min_priority_img_pixels) und gibt ihm kein loading="lazy", weil ein Element nie beides tragen sollte. Kommt Ihr LCP-Bild aus einem Block oder einem CSS-Hintergrund, den diese Funktion nicht sieht, markieren Sie es selbst.
Wie man WordPress-Bilder mit WebP und AVIF optimiert
Im Jahr 2026 sind JPG und PNG Relikte für Fotos. WordPress unterstützt nativ WebP (seit Version 5.8) und AVIF (seit Version 6.5), sofern die Bildbibliothek des Servers (Imagick oder GD) das Format beherrscht. Unter Werkzeuge > Website-Zustand, Reiter Bericht, Abschnitt Medienverarbeitung, sehen Sie, welche Formate Ihr Server unterstützt.
Sie benötigen keine Plugins. Laden Sie einfach eine AVIF-Datei hoch, und WordPress verarbeitet sie. Oder nutzen Sie das Plugin Modern Image Formats des WordPress-Performance-Teams, das aus hochgeladenen JPEGs Zwischengrößen in AVIF erzeugt (oder in WebP, wenn der Server AVIF nicht unterstützt) und das Original behält.
Wie viel WebP und AVIF gegenüber JPG sparen
Die offiziellen Zahlen aus dem Core lauten:
- WebP: im Schnitt rund 30% kleiner als das JPEG- oder PNG-Gegenstück, laut der Notiz zu WordPress 5.8.
- AVIF: bis zu 50% kleiner als JPEG bei gleicher Qualität, laut der Notiz zu WordPress 6.5.
AVIF komprimiert meist besser als WebP, vor allem bei Fotos mit weichen Verläufen. WebP hat in älteren Browsern etwas breitere Unterstützung, daher ist eine verbreitete Strategie AVIF als erste Wahl und WebP als Fallback.
Wie man das picture-Element mit AVIF und WebP nutzt
Für maximale Kontrolle über die ausgelieferten Formate können Sie das HTML-Element <picture> verwenden:
<picture>
<source srcset="bild.avif" type="image/avif">
<source srcset="bild.webp" type="image/webp">
<img src="bild.jpg" alt="Beschreibung des Bildes">
</picture>In den meisten Fällen ist es aber praktischer und wartungsärmer, die Formatverhandlung WordPress und dem CDN zu überlassen.
Wie man Qualität und Ausgabeformat in WordPress ändert
Jede Zwischengröße, die WordPress erzeugt, läuft durch die Klasse WP_Image_Editor, und zwei Filter steuern das Ergebnis.
Der erste betrifft die Qualität. Im aktuellen Quellcode der Klasse liegt die Standardqualität bei 82 für JPEG und 86 für WebP; andere Formate erhalten 82. Der Filter wp_editor_set_quality erhält Qualität und MIME-Typ, Sie können also jedes Format getrennt einstellen. Bei JPEG wendet der Core danach den älteren Filter jpeg_quality an, der das letzte Wort hat, wenn ein Plugin ihn nutzt:
add_filter( 'wp_editor_set_quality', function( $quality, $mime_type ) {
if ( 'image/avif' === $mime_type ) {
return 70;
}
return $quality;
}, 10, 2 );Der zweite betrifft das Ausgabeformat. Der Filter image_editor_output_format ordnet jedem Eingangs-MIME-Typ das Format zu, in dem die Zwischengrößen gespeichert werden. Die Notiz zu WordPress 6.5 nutzt genau dieses Beispiel, damit hochgeladene JPEGs Zwischengrößen in AVIF erzeugen:
add_filter( 'image_editor_output_format', function( $formats ) {
$formats['image/jpeg'] = 'image/avif';
return $formats;
} );Seit WordPress 6.7 nutzt der Core denselben Mechanismus standardmäßig für HEIC-Fotos von iPhones: Kann der Server sie lesen, wandelt er sie beim Upload in JPEG um. Die Formatänderung betrifft nur neue oder neu erzeugte Bilder, nach dem Aktivieren des Filters ist also wp media regenerate fällig.
Wie man TimThumb aus WordPress entfernt
Mehr über unsere WordPress-Sicherheitsaudits.
Wenn Sie ein altes Projekt geerbt haben, entfernen Sie TimThumb sicher und vollständig:
- Scannen: Durchsuchen Sie das
wp-content-Verzeichnis nachtimthumb.phpoderthumb.php. Suchen Sie auch nach zugehörigen Cache-Verzeichnissen. - Löschen: Löschen Sie die Datei und das zugehörige Cache-Verzeichnis (meist ein Ordner
cacheim Theme-Verzeichnis). - Reparieren: Finden Sie den Aufruf im Code:
// ALTER CODE (SCHLECHT) <img src="<?php echo get_template_directory_uri(); ?>/timthumb.php?src=..." /> // ERSETZEN DURCH (GUT) <?php the_post_thumbnail( 'meine-groesse' ); ?> - Regenerieren: Installieren Sie
WP-CLIund führen Siewp media regenerateaus. - Prüfen: Gehen Sie nach der Migration alle wichtigen Seiten durch und stellen Sie sicher, dass die Bilder korrekt angezeigt werden. Achten Sie besonders auf Archivseiten, Sidebar-Widgets und den Footer, wo TimThumb im Einsatz gewesen sein könnte.
Wie man TimThumb-Verweise mit grep findet
Die Datei zu löschen reicht nicht. Sie müssen alle Verweise im Code finden:
# In allen PHP-Dateien des Themes suchen
grep -r "timthumb" wp-content/themes/ihr-theme/
grep -r "thumb.php" wp-content/themes/ihr-theme/
# Auch in eigenen Plugins suchen
grep -r "timthumb" wp-content/plugins/
# Spur von eingeschleustem Code, die Maunder zu prüfen empfahl
grep -rl "base64_decode" wp-content/Jeden gefundenen Verweis ersetzen Sie durch die passende native WordPress-Funktion. Meist heißt das the_post_thumbnail() oder wp_get_attachment_image() mit der richtigen Größe. Ein Treffer für base64_decode beweist keine Infektion, weil manche legitime Plugins die Funktion nutzen, aber jedes Vorkommen in einem Theme sollte man lesen.
Wie man die Bild-Performance in WordPress misst
Prüfen Sie nach dem Umstieg von TimThumb auf native Methoden, ob die Performance besser geworden ist. Nutzen Sie Google PageSpeed Insights, Lighthouse und WebPageTest, um die Ladezeiten vor und nach der Migration zu messen.
Welche Bildmetriken man misst: LCP, CLS und TTFB
- Largest Contentful Paint (LCP): Das Hauptbild ist meist das LCP-Element. Mit vorab erzeugten nativen Größen,
fetchpriority="high"und einem CDN sollte der LCP-Wert sinken. - Cumulative Layout Shift (CLS): Sorgen Sie dafür, dass alle Bilder
widthundheighthaben, damit das Layout beim Laden nicht springt. Die Anhang-Funktionen von WordPress setzen sie selbst. - Time to First Byte (TTFB) der Bilder: Ohne Skalierung per PHP wartet die Antwort für jedes Bild nicht mehr auf PHP oder GD.
Serverkonfiguration für WordPress-Bilder
Für gute Bild-Performance in WordPress 2026 umfasst die empfohlene Konfiguration:
- Browser-Cache mit langen
Cache-Control-Headern für Bilddateien (mindestens ein Jahr) - CDN mit Bildtransformationen und automatischer Formatumwandlung
- Preload des LCP-Bildes über
<link rel="preload">, wenn das Bild nicht früh im HTML auftaucht
Wie man Bilder in WordPress ohne TimThumb verarbeitet
Die Geschichte von TimThumb ist eine Lektion in Demut. Bequemlichkeit (Skalierung im laufenden Betrieb) darf nicht über Sicherheit stehen. Im Jahr 2026 haben wir natives add_image_size(), responsives srcset und CDNs, die Bilder in der Cloud verarbeiten. Es gibt keinen Grund, zu Lösungen von vor 15 Jahren zurückzukehren.
Moderne Bildverwaltung in WordPress ruht auf drei Säulen: Erzeugung der Größen beim Upload mit add_image_size(), responsive Auslieferung mit srcset und sizes sowie Formatoptimierung mit WebP/AVIF. Zusammen mit einem CDN für die Auslieferung ergeben sie schnelle, sichere und wartbare Bilder für jede WordPress-Website.






