Was wir gegen Podlove-Exploits tun

Posted by jonas on Friday, September 26, 2025

Es begann mit ersten Meldungen von Usern, dass ihre Websites plötzlich nicht mehr erreichbar seien oder komische Fehlermeldungen werfen. Während wir die ersten ein, zwei Meldungen untersuchten und schon feststellten, dass sich auf den betreffenden Websites PHP-Schadcode befand, rollte eine regelrechte Exploit-Welle los. Die Gemeinsamkeit: Alle betroffenen WordPress-Installationen setzen den Podlove Podcast Publisher ein.

Inzwischen wissen wir mehr. Der erst wenige Tage alte Exploit hat den Namen CVE-2025-10147, und alle Podlove Publisher-Versionen bis inkl. 4.2.6 sind anfällig - die aktuelle Version 4.2.7 ist mit einem Fix gepatcht.

Grob gesagt funktioniert der Exploit so: Eine ins Netz exponierte Funktion des Podlove Publishers ist, dass man Bild-URLs angeben kann, die sich das Plugin dann ins eigene Cache-Verzeichnis ziehen. So weit, so gut; das Problem ist, dass es das überraschenderweise nicht nur mit Bild-URLs tut, sondern auch… mit anderen Dateitypen. Der Patch sieht insofern so aus, dass nun wesentlich gründlicher geschaut wird, ob es sich bei der angegebenen URL überhaupt um ein Bild handelt und zusätzlich nun auch eine ganze Reihe potentiell bedenklicher Dateiendungen ausschließt.

Was tun?

Updaten.

Also, ernsthaft. Updaten. Jetzt.

Und danach gerne zum Weiterlesen wieder hierher zurück kommen. :-)

Zeit für Strategieplanung

Wir haben verschiedene Strategien gleichzeitig entwickelt, um mit dieser Situation umzugehen.

Zunächst vorweggeschickt: Die Verantwortung für Updates liegt bei denen, die sich das WordPress und das Plugin installiert haben. Unser eigener Lab-Guide für WordPress hat extra einen Abschnitt zu Updates. Wir sind nicht - wie auf Mastodon vermutet wurde - klammheimlich zu einem Managed-WordPress-Hoster mutiert.

Es ist uns allerdings nicht genug, an dieser Stelle die Hände in den Schoß zu legen. Denn seien wir ehrlich: In der Realität hängen viele mit Updates ein bisschen hinterher… oder auch ein bisschen viel. Und es ist auch nicht so, dass uns gehackte WordPress-Instanzen völlig egal sein können, nach dem Motto “Was kümmert’s uns, wenn dem User seine Website gehackt ist” (Gruß an Bastian Sick), denn die tun dann in der Regel lauter Dinge, die nicht nur die betreffende Website selbst, sondern auch unsere Reputation schädigen, zum Beispiel in dem Angriffe auf andere Sites gefahren werden, was unsere Hosts auf Blocklists wie die XBL bringt, oder es wird Spam verschickt, was unsere Hosts auf Blocklists wie die SBL bringt. In jedem Fall resultiert daraus ein indirekter Schaden für alle: Mails werden weniger verlässlich zugestellt, weil Dritte sie ablehnen; manche Firewalls sperren den Zugriff auf Hosts gleich ganz, wenn sie auf der XBL stehen.

Unser Plan, der teils schon umgesetzt ist und teils gerade umgesetzt wird, während dieser Blogpost entsteht:

  1. Wir blockieren die HTTPS-Requests, die den Exploit auszunutzen versuchen.
  2. Wir identifizieren soweit möglich alle WordPress-Installationen, die bereits infiziert sind, sperren jene und informieren die betreffenden User.
  3. Dort, wo es möglich ist, aktualisieren wir das Podlove-Plugin mittels wp plugin update und informieren die betreffenden User.
  4. Wo das nicht möglich ist, zum Beispiel weil das Plugin zu alt ist, um ohne Komplikationen aktualisiert zu werden, oder wo die WordPress-Installation so kaputtkonfiguriert ist, dass schon ein wp core version nicht funktioniert, beschränken wir uns auf eine Information an die betreffenden User.
  5. Wir schreiben diesen Blogpost, denn Wissen zu teilen ist wichtig.

Globales Unschädlichmachen mit nginx

Wir haben zunächst untersucht, welche Gemeinsamkeiten die HTTPS-Requests haben, die wir auf unseren Systemen vorgefunden haben. Es stellte sich dabei heraus, dass es immer ein Pattern als genau zwei Requests gab. Hier ein konkretes Beispiel:

0.0.0.0 - - [26/Sep/2025:17:54:00 +0200] "GET /index.php?podlove_image_cache_url=68747470733a2f2f6933302e627a2f6769662f6769662e706870&podlove_file_name=xaglrbmf HTTP/1.1" 403 146 "www.google.com" "Mozilla/6.4 (Windows NT 11.1) Gecko/2010102 Firefox/99.0"
0.0.0.0 - - [26/Sep/2025:17:54:00 +0200] "GET /wp-content/cache/podlove/08/ab26d12bf901677afc5ce0098eb0e8/xaglrbmf_original.php?up=1 HTTP/1.1" 403 146 "www.google.com" "Mozilla/6.4 (Windows NT 11.1) Gecko/2010102 Firefox/99.0"

Es war immer das Pattern aus genau diesen zwei URLs.

Eine Sache fällt sofort auf: Als Referrer ist "www.google.com" angegeben. Da ein Referrer per Definition aber immer eine URL sein muss, und hier aber ein URL-Schema wie http:// oder https:// fehlt, ist schon mal völlig klar: Das ist Fake. Und damit haben wir auch schon unsere erste Regel:

# Prevent fake Google referrers
if ($http_referer = "www.google.com") {
   return 403;
}

Aber da geht noch mehr.

Wir haben festgestellt, dass bei podlove_file_name=... immer ein Dateiname aus genau 8 Buchstaben (niemals Zahlen) angegeben wird. Das ist aber schwer als Kriterium heranzuziehen, denn auch völlig valide Bilddateien können natürlich einen 8-buchstabigen Dateinamen haben. Wir haben bei podlove_image_cache_url eine auffällige Häufung von 68747470733a2f2f6933302e627a2f6769662f6769662e706870 gefunden - aber auch andere Werte. Es erscheint nun erstmal schwierig, an diesem Hexadezimalstring festzustellen, ob der “böse” ist. Wobei…

$ echo 68747470733a2f2f6933302e627a2f6769662f6769662e706870 | xxd -r -p
https://i30.bz/gif/gif.php

A-ha! Eine URL, die auf .php endet - das verheißt nichts Gutes. Schnell haben wir festgestellt: Auch wenn sich die Hexadezimalcodes unterscheiden: Sie enden alle mit 2e706870, der Hex-Schreibweise für .php. Danach lässt sich dann doch super filtern! Und das tun wir nun auch:

# Prevents Podlove from loading URLs ending in ".php" through index.php?podlove_image_cache_url=...
if ($arg_podlove_image_cache_url ~ "2e706870$") {
   return 403;
}

Nun hatten uns die Podlove-Entwickler - an dieser Stelle vielen Dank für den schnellen und unkomplizierten Austausch via Mastodon; so wünscht man sich das! - in der Zwischenzeit aber auch auf dieses Stück Code hingewiesen:

add_action('init', function () {
    add_rewrite_rule(
        '^podlove/image/([^/]+)/([0-9]+)/([0-9]+)/([0-9])/([^/]+)/?$',
        'index.php?podlove_image_cache_url=$matches[1]&podlove_width=$matches[2]&podlove_height=$matches[3]&podlove_crop=$matches[4]&podlove_file_name=$matches[5]',
        'top'
    );
}, 10);

Es reicht also nicht, nur URLs zu blocken, bei denen der Query-Parameter podlove_image_cache_url auf 2e706870 endet. Wir müssen auch URLs blocken, die auf podlove/image lauten und dann einen Hex-Wert haben, der auf 2e706870 endet, plus potentiell noch weitere Parameter. Machen wir doch glatt:

# Prevents Podlove from loading URLs ending in ".php" through /podlove/image/...
location ~ /podlove/image/[0-9a-fA-F]*2e706870(?:/|$) {
    return 403;
}

Kleiner Regex-Exkurs: (?:/|$) bedeutet, dass nach dem 2e706870 entweder ein / kommen muss oder aber die URL zuende ist, und das ?: innerhalb der runden Klammern legt fest, dass es sich um eine “non-capturing group” handelt, also ein Match innerhalb der Klammer nicht als Match weiterverarbeitet werden braucht. Das macht die Sache minimal performanter.

Und schließlich noch: Was machen wir denn mit den Sites, denen schon eine PHP-Datei untergejubelt worden ist? Es wäre dann ja schön, wenn jene sich zumindest nicht mehr aufrufen ließe.

Das ist nun zum Glück wieder relativ trivial: Nichts von dem, was unterhalb von wp-content/cache/podlove liegt, sollte auf .php enden dürfen. Also bauen wir daraus Regel Nummer 4:

# Prevent requests to already infected sites
location ~ "/wp-content/cache/podlove/[0-9a-f]{2}/[0-9a-f]{30}/[a-z]{8}_original\.php$" {
   return 403;
}

Wir sind guten Mutes, dass wir damit den aktuell kursierenden Exploit auch von ungepatchten Podlove-Installationen fernhalten können.

Aber nur um das klar zu sagen: Das ist keine Entschuldigung, seine Plugins nicht upzudaten. Wir versuchen hier, die Extrameile zu gehen, damit eure WordPress-Installationen nicht gehackt werden, aber das ändert nichts daran, dass das originär nicht unsere Aufgabe ist. Wenn wir hier aber die Möglichkeit haben, mit überschaubarem Aufwand Schaden von euch und uns und allen anderen Usern und den potentiellen Opfern von ausgehenden Attacken und Spam abzuhalten, dann tun wir das natürlich gerne.

Ach ja: Vorsicht mit KI

Rein spaßeshalber probieren wir immer mal aus, wie KI in der IT-Sicherheit und im Softwaredevelopment so funktioniert. Und so haben wir die CVE-Nummer des Podlove-Exploits mal als CVE-2025-10147 mitigation in Google geworfen, einfach um zu schauen, ob vielleicht schon jemand nginx-Block-Regeln geschrieben hat, so wie wir nun. Festhalten:

To mitigate CVE-2025-10147, users should apply the security update for Windows 11 (24H2) and Windows Server 2025, as the vulnerability is patched through Windows Graphics component updates that prevent an attacker from exploiting a malformed JPEG file for remote code execution, according to a Rapid7 analysis.

Alles klar, wir gehen dann mal Windows-Updates auf unseren Linux-Kisten einspielen. :-)

Foto von Kelly Sikkema auf Unsplash