WordPress updaten, geht nur mit genug Platz :)

Für alle, die planen einen Blog mit echt vielen Grafiken und Medieninhalten zu bestücken, hier ein kurzer Hinweis zum WordPress 5.5 Update 🙂

WordPress updaten, geht nur mit genug Platz 🙂

Wer dieses Blog verfolgt, wird festgestellt haben, daß sich die Artikelzahl in diesen Jahr stark erhöht hat. Das liegt hauptsächlich natürlich an Coronaartikeln, die jede Menge Bildern zu den verschiedenen Statistiken intus haben. Ich habe jetzt 2.950 MB Daten im Blog und wollte ein Update auf WordPress 5.5 durchziehen. Das ist normalerweise kein Problem. Kurz auf „Update“ klicken und warten. Er lädt im Hintergrund schnell das WP Archiv runter, packt es aus und … meldet, daß es nicht geht … ähmm… 🙁

Komisch, die Updates der Plugins, die funktionieren, die Themes auch.. da muß doch … nein, muß es nicht. Das Hauptupdate ist zwar nur 13 MB groß, aber ausgepackt bringt es 50 MB auf die Waage. Hmmm.. zusammen 63 MB + ein paar temporäre Dateien.. 2.950 MB belegt… von ??? Oh… 3.000 MB 😀  Das Rätsels Lösung: das Update paßte nicht mehr auf die Platte. Ein Accountupgrade mußte her. Jetzt sind es 5.000 MB und das wird bis Ende des Jahres reichen müssen.

Merke: Wenn WordPress beim Blog Update streikt, könnte auch einfach der Webspace voll sein 😉

WordPress: die vergessene mShot DOS Attacke

Alle guten Geschichten beginnen mit „Es war einmal..“ so auch meine heutige Geschichte eines längst vergessenen Dienstes, der zu einem DOS Angriffs mutiert ist. Wer WP betreibt, wird in diesem Artikel einige Denkeanstöße für seine eigene Instanz bekommen.

WordPress: die vergessene mShot DOS Attacke

Es war einmal ein Dienst der Firma AUTOMATTIC, Inc. die Ihres Zeichens nach WordPress.com betreibt. Wir schreiben die Prä-Neulandzeit. Der Dienst konnte Screenshots von Webseiten erzeugen und irgendwo einbasteln. Im Jahre der Merkel 2012 postete jemand eine Anfrage im WordPressforum, wo denn all die komischen Anfragen in seinem Blog herkommen würden, die „WordPress.com mShots“ im Useragent stehen haben.

Es wurde ihm folgendes mitgeteilt:

mShots was a third party extra feature that has been removed > mShots have been deactivated on all WordPress.com blogs, says a Happiness Engineer:
https://en.forums.wordpress.com/topic/does-using-zemanta-disable-mshots?replies=2#post-517481

Damit Ihr wisst um was es geht, hier ein exemplarischer Auszug aus einem Logfiles eines Kundenservers heute morgen, womit wir uns nebenbei +8 Jahre nach „Einstellung des Dienstes“ befinden:

192.0.100.186 – – [20/May/2020:08:51:12 +0200] „GET /trainer/ HTTP/1.1″ 301 20 „-“ „Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/69.0.3494.0 Safari/537.36 WordPress.com mShots
LOCALHOST – – [20/May/2020:08:51:21 +0200] „POST /trainer/wp-cron.php?doing_wp_cron=1589957481.2505230903625488281250 HTTP/1.1″ 200 20 „http://eine.wordpress.seite/trainer/wp-cron.php?doing_wp_cron=1589957481.2505230903625488281250″ „WordPress/5.3.3; https://eine.wordpress.seite/trainer
192.0.100.186 – – [20/May/2020:08:51:22 +0200] „GET /trainer/ HTTP/2.0″ 200 – „-“ „Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/69.0.3494.0 Safari/537.36 WordPress.com mShots

Damit der Spannungsbogen Euch nicht umbringt, hier eine erste Auflösung: der Dienst wurde nicht abgeschaltet 😉

Was sehen wir oben?

Wir haben den Zugriff vom WP Servercluster 192.0.100.186, dann einen Cronjob der von der WP Installation selbst stammt, und danach wieder ein Zugriff vom WP Cluster. Damit haben wir 3x PHP im Spiel, pro Aufruf.

Der Angriff aus dem Nichts

Jetzt gab es um 8:51:xx nicht nur Zugriffe auf diese eine WordPressinstanz, sondern über 100 haben gleichzeitig diese mShots Anfrage bekommen, mit dem Resultat das (am Ende) gleichzeitig hunderte PHP Prozesse liefen.

Jeder der sich mit Hosting auskennt, weiß, daß hunderte von PHP Prozessen jede Menge an Speicher, CPU Last und IO erzeugen, besonders wenn PHP nicht als Modul, sondern im sicheren CGI-Modus läuft. Jetzt wäre auch das nicht das Problem, wenn auf dem nur einige dieser WP Instanzen wären, waren sie aber nicht. Ein einziger Server hat diese Wucht abbekommen und der hatte auch nur 4 Kerne zur Verfügung.

Zufälle gibts, die gibt es gar nicht.

Um dem Ganzen oben noch die Krone aufzusetzen, hatte ein Mitarbeiter der für die WP Instanzen zuständigem Werbeagentur, kurz vorher ein Backup einer Präsenz gestartet. Zu den hunderten von PHP Prozessen lief also auch noch ein TAR/GZ Backup eines nicht kleinen Webdienstes mit 100% Leistung auf einem der vier Kerne.

Jetzt könnte man glauben, daß wäre ja schon Zufall genug, aber da lege ich jetzt noch einen drauf 🙂 Ich war nämlich heute morgen auch zufällig auf dem Server und wollte einer Meldung von letzter Nacht nachgehen, als ich aus Routine, aber wiederum zufällig, in TOP geschaut hatte, ob alles rund läuft. Dabei habe ich dann die ganzen PHP Prozesse im Aufbau eines Totalausfalls bemerkt und konnte gerade noch rechtzeitig „killall php-cgi“ eingeben, bevor es zum Kaskadenversagen durch CPU/IO/SWAP kam. Die Load war bereits auf dem Weg gen 75 😉

Die Suche nach der Ursache

Gefahr gebannt, aber was konnte das ausgelöst haben? So einen ähnlichen Vorfall hatten wir vor einigen Jahren auch mal, als ein Möchtegern-Hacker parallel allen WP-Instanzen ein paar unsinnige Anfragen geschickt hatte und das WP diese nicht beantwortbare Anfrage auch fleißig allen WP Plugins anbot, nur um dann doch 404 Seiten auszugeben, die wiederum im WP gelandet sind ( fast wärs eine Endloss-404-Schleife geworden ). Weil auch die 404 Seiten wiederum durch PHP liefen, hatte sich die Load auch unfreiwillig verdoppelt. Das haben wir damals dann geändert, so das 404 jetzt nur noch statische Webseiten sind, was die Performance des Servers stark verbessert hat.

Kein Hacker…

Umso mehr hatte mich dann gewundert, daß es wieder zu so einer DOSartigen Situation kam. Also schaute ich in die Logs und wurde schnell mit einer Reihe von IPs aus dem gleichen Block belohnt: Denen von WordPress.com.

192.0.100.186 – – [20/May/2020:08:51:12 +0200] „GET /trainer/ HTTP/1.1″ 301 20 „-“ „Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) HeadlessChrome/69.0.3494.0 Safari/537.36 WordPress.com mShots

Da dort merkwürdigerweise immer mShots stand habe ich dann Tante Google gefragt, aber die meinte ja, siehe oben, daß es das gar nicht mehr geben würde. Also habe ich vergleichende Forensik betrieben und danach auf anderen bekannten WP Instanzen in unserem Cluster gesucht. Fündig wurde ich aber nicht.

„Wie das gibt es doch nicht..“

Das Gespräch mit dem Kunden, der sein Server da gerade gedost worden war, war dann nach einer Weile des Rätselns doch von Erfolg gekrönt. Im Ausschlussverfahren haben wir dann ein Plugin identifiziert, daß dafür indirekt verantwortlich war: der Elementor!

Elementor ist ein Plugin-System mit dem man „schneller“ (haha) komplizierte Layouts in WordPress umsetzen kann, als wenn man an den Themes rumspielt. Es ist also eine Art Homepagebaukasten innerhalb von WordPress. Jetzt sind meine Ansprüche an eine Webseite nicht so hoch, daß ich da Elementor einsetzen würde, wenn ich schon WP habe, aber das sehen Werbeagenturen naturgemäß anders 😉

Die Auflösung

Jetzt hatten wir einen Verdacht, also gruben wir noch etwas tiefer und schauten uns die Zeiten an, als den Server die mShots in der Vergangenheit getroffen hatten. Dabei stellte sich ein unregelmäßiges Muster ein, anhand dessen der Kunden dann eingrenzen konnte, daß wann immer er selbst in der Elementor-Zentralinstanz bei Elementor eingeloggt war, so ein DOS Angriff statt gefunden hatte. Das hat er selbst nicht gemerkt, weil er ja anderswo beschäftigt gewesen war. Meistens gab es da auch keine laufenden Backupprozesse, so das die mShot Anfragen bislang unbemerkt geblieben waren. Elementor fragt nämlich beim Login WordPress.com:mShots von allen verbundenen Webseiten (>100 Stück) einen aktuellen Screenshot zu besorgen.

Fazit: Der Kunde hatte sich mit dem Login bei Elementor,  und dem laufenden Backup unwissentlich selbst gedost. Das erlebt man auch nicht alle Tage 🙂

Die Empfehlung

Jetzt meine Empfehlung an Euch:

Auch wenn etwas bei der Anzahl 1, 2 oder 3 zügig reagiert, ist das bei 100+ nicht mehr der Fall.

Wenn Ihr also irgendein Programm baut, geht nicht davon aus, daß es ja nur die paar Testfälle verkraften muß, die Ihr hattet, sondern überlegt immer, was passieren kann, wenn hundert, tausend oder gar Millionen Abfragen involviert sind 🙂

Unser Kunde fragt derzeit bei Elementor an, ob man die Screenshots abschalten kann, das solltet Ihr auch abschalten, wenn Ihr so viele Instanzen auf einem einzigen Server habt. Glücklicherweise kam das Plugin nur bei den knapp über 100 WP Instanzen zum Einsatz, auf dem Server sind aber noch hunderte andere Instanzen untergebracht 😉

Wie wichtig das mit dem Einplanen nur „Millionen“ Anfragen sein kann, würde Euch ein anderer Feuerwehr-Fall zeigen, aber leider reden wir nicht über Kundenfälle, außer wir haben die Erlaubnis dazu, was aber hier der Fall ist.

 

WordPress Security-GAU in iOS App

In der WordPress iOS App klaffte 2 Jahre eine dicke Sicherheitslücke, die die Authentifizierungstokens der eigenen WordPressinstallation an Dritte übermittelt hat.  „Dritte“ meint hier z.b. Bildhoster wie Flickr, Imgur usw. .

Wer also sein WP Blog mit der iOS App bedient hat, sollte jetzt mal sein Adminpasswort ändern, denn jetzt werden die mit dem Token beglückten Webseiten mal die Logs durchforschen, ob sie das was tolles finden können 😉

Quelle: thehackernews.com/2019/04/wordpress-ios-security.html

WordPress 5.1.1 Multisites mit DB-Updateproblem

Nächste Warnung: Wer eine WordPress Multisite betreibt und von 5.0 auf 5.1.1 aktualisiert wird, der könnte ein Problem haben, ohne es zu wissen.

Datenbankupdate nicht ausgeführt

Die Fehler reichen von Logmeldungen wie dieser:

WordPress-Datenbank-Fehler Table ‚db466398.wp_blogmeta‘ doesn’t exist für Abfrage SELECT blog_id, meta_key, meta_value FROM wp_blogmeta WHERE blog_id IN (6) ORDER BY meta_id ASC von include(‚wp-load.php‘), require_once(‚wp-config.php‘), require_once(‚wp-settings.php‘), require(‚wp-includes/ms-settings.php‘), ms_load_current_site_and_network, get_site_by_path, get_sites, WP_Site_Query->query, WP_Site_Query->get_sites, _prime_site_caches, update_site_cache, update_sitemeta_cache, update_meta_cache

bis hin zu 500er Fehlern, wenn man die Webseiten aufruft.

Das Problem wurde vor 4 Wochen bereits bekannt, konnte aber nicht zuverlässig reproduziert werden von den Devs, tritt aber so oft auf, daß es kein Zufall mehr ist, ich habs ja auch gehabt 😉

Lösung:

Einloggen in die Datenbank und das hier ausführen:

CREATE TABLE `wp_blogmeta` (
`meta_id` bigint(20) unsigned NOT NULL AUTO_INCREMENT,
`blog_id` bigint(20) NOT NULL DEFAULT 0,
`meta_key` varchar(255) DEFAULT NULL,
`meta_value` longtext DEFAULT NULL,
PRIMARY KEY (`meta_id`),
KEY `meta_key` (`meta_key`),
KEY `blog_id` (`blog_id`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8

Dann hören die Meldungen im Errorlog des Apachen auf. Ob das auch den 500er behebt, kann ich nicht sagen, da er mir nicht passiert ist. Wer sich jetzt fragt wo ich die Struktur her habe, es gibt in WP eine Datei, in der die DB Schemata drinstehen, da bekommt man das her.

 

Ihr habt WordPress und FastCGI im Einsatz?

Dann wird Euch sicher interessieren, wie man das reaktiver bekommt.

Das Problem

Wenn eine Seite mit FASTCGI läuft, wird PHP als CGI ausgeführt, also EXTERN vom Apache aus gesehen. Daher kann der Apache nur für native Files die GZIP Komprimierung übernehmen, nicht aber für die Webseiten selbst. PHP muß das tun, da es für den Datenstrom selbst zuständig ist.

Damit es das tut, fügen wir eine eigene php.ini mit diesem Inhalt im Hauptpfad ein:

zlib.output_compression = On
zlib.output_compression_level = 6

z.b. so “ echo ‚zlib.output_compression = On‘ > php.ini; echo ‚zlib.output_compression_level = 6‘ >> php.ini
Das wars. Fertig. Jetzt werden die PHP Seiten mit GZIP vom Server komprimiert und z.b. im Mobilfunknetz schneller übertragen. Alle werden es Euch danken 😉

Classic Editor is back

Ich hab es wirklich versucht, aber der neue Editor „Gutenberg“ von WordPress ist eine Qual. Das tut in der Seele weh. Wie kommt man nur auf sowas? Alleine schon die Optik hat mit Texte schreiben nichts zu tun. Diese Blocktechnik ist was für Facebook-Timelime-Kids u.V. .

Classic Editor reaktivieren

Da mit Gutenberg jeder seine eigenen schlimmen Erfahrungen gemacht hat oder noch machen wird, wenden wir uns produktiveren Dingen: Wie wird man ihn los?

Das ist zum Glück ganz einfach!

Im Dashboard unter Plugins „Installieren“ auswählen und in das Suchfeld „Editor“ eingeben. Kommt als erster Treffer mit über 1 Million Installationen „Classic Editor“ 😀 Alles mit OK bestätigen und Fertig.

Ich habe so das Gefühl, daß wird mit weitem Abstand das beliebteste Plugin werden.

Meine wenig positive Meinung  werde ich hier nicht zurückhalten: WP werdet die Typen los, die das verbrochen haben!

Die Aussichten bis 2020

Da die Menschheit ja bei wichtigen Entscheidungen immer die schlechtere Option wählt, haben besorgte Blogschreiber WP geforkt und lassen es ohne Gutenberg weiter laufen. GGF. muß man das in Zukunft als Option wählen, wenn man einfach nur Blogs schreiben will. Im Gutenberg habe ich nicht mal die Rechtschreibkontrolle gefunden, und das viele unnötige rumgeklickte um substanzielle Funktion zu erreichen. Wo es doch vorher super funktioniert hat. Das kommt bestimmt aus der Ecke der Handy und Tablelike-Benutzer mit Minibildschirmen. Als wenn das die Hauptgruppe der Blogschreiber wäre. Das wäre mir viel zu anstrengend mit den virtuellen Tastaturen. Wobei, „Diktieren“ ist ganz nett, führt aber meiner Erfahrung nach zu schlechtem Satzbau, so daß man viel editieren muß.

WordPress DOS – wp-admin Verzeichnis schützen

Die Hacker News berichten von einem Angriff auf WordPress, der von Seiten der Entwickler als „nicht-unsere-Baustelle“ abgeschmettert wurde, aber ganz leicht abgewehrt werden kann.

Der Angriff

Im wp-admin Verzeichnis gibt es ein Script namens „load-scripts.php„, das auf Zuruf, und liegt das Problem, alle Javascripte der Installation, zu einer gemeinsamen Javascriptseite zusammenbaut, damit der Browser nicht jede einzeln laden muß. Das Problem daran ist, jeder kann die Seite aufrufen. Wenn man dann noch die gesamten Javascripte eines WordPress zusammenstellen läßt, reichen wenige Aufrufe, bis die Webseite offline ist.

Das liegt daran, daß bei der Zusammenstellung sehr viel IO entsteht, was den Webserver belastet. Dadurch wird alles langsamer, bis es bei genug Anfragen zum faktischen Stillstand kommt. Dazu kommt eine erhöhte Rechenleistung während die Scripte Ihren Job tun.

Was meint WordPress dazu ?

Die sagen, daß ein Admin diese Seite aufrufen können muß, wenn er noch nicht als Admin erkennbar ist. Also muß es jeder können. Man solle doch das Problem irgendwo anders löschen, nur nicht bei Ihnen.

„However, the company refused to acknowledge the issue, saying that this kind of bug „should really get mitigated at the server end or network level rather than the application level,“ which is outside of WordPress’s control.“ (Zitat von THN )

Das ist natürlich peinlich, weil jemand das in WordPress gefixt hat und einen Fork davon bereitstellt. Es ist also scheinbar leicht möglich es zu beheben.

Eine Lösung des Problems

Wenn Ihr Zugriff auch Euren Webserver habt, erstellt Ihr einfach für wp-admin eine .htaccess Datei . Das kann man über eine Weboberfläche lösen, so wie hier :

Wenn man die HT-Accessabfrage mit  Usernamen und Passwort anlegt, fragt einen der Browser nach den Zugangsdaten, aber merkt sich die auch, so daß man selbst recht unproblematisch wieder ins Backend gelangt. ( Die 5.6 Version von PHP ist wohl beim Testen hängen geblieben und wurde bereinigt 😉 ).

Nach dem Anlegen zeigt meine Oberfläche dann auch an, daß dort eine HTAccess mit Benutzernamen liegt :

Admin-Weboberfläche nach dem Anlegen des Benutzers

Nach dem Anlegen des Benutzers

Wenn man das alles von Hand machen muß, geht das so :

In die Datei wp-admin/.htaccess  kommt dieser Inhalt, bei dem Ihr den Pfad anpassen müßt:

AuthType Basic
AuthName "Das ist mein WordPress!"
AuthUserFile /path_to_wp/wp-admin/.htpasswd
Require valid-user

danach gibt man in der Bash ein :

htpasswd -bc  /path_to_wp/wp-admin/.htpasswd username password

Das war es dann schon. Jetzt noch im Browser wp-admin/ aufrufen und die neuen Zugangsdaten eingeben und auf Speichern drücken.

WordPress Kommentarvorschaufunktion abschalten

Liebe Mitblogger,

seid auch Ihr es leid, daß Ihr beim Durchsehen von Spamkommentaren zufällig die per MouseOver() ausgelöste Preview einer Spammerwebseite nicht abschalten könnt ?

Falls Ihr jetzt hofft, daß Euch das per neuer Funktion im heute rausgekommenen Update auf 4.9 möglich wäre, leider nein. Wieso Askimet den Usern diese Funktion nicht zur Verfügung stellt, bleibt mir ein Rätsel. Besonders gut wäre es, wenn die Preview nur bei SPAMS abgeschaltet würde, weil andere Webseitenlinks sind ja vielleicht sogar gewollt.

Aber laßt Eure Köpfe nicht hängen, es gibt eine Lösung 😉

Hier ist die Lösung

In der Datei /wp-content/plugins/akismet/_inc/akismet.js in Zeile 277 ersetzt Ihr diese Anweisung:

$( '#the-comment-list' ).on( 'mouseover', mshotEnabledLinkSelector, function () {
clearTimeout( mshotRemovalTimer );

durch diese hier:

$( '#the-comment-list' ).on( 'mouseover', mshotEnabledLinkSelector, function () {
 return;
 clearTimeout( mshotRemovalTimer );

und bis zum nächsten Update seid Ihr die Kommenturlpreview los!

 

WordPress Traffic Stats Widget defekt

Wer in seinem WordPress Blog das „Traffic Stats Widget“ einsetzt, der könnte ein Problem haben. Seit dem 20.9. hat unser Plugin nichts mehr in die Logdatenbank geschrieben und damit sind fälschlicherweise meine Zugriffszahlen für September und Oktober leicht rückläufig, um nicht zu sagen, nicht mehr vorhanden 😉

Der Fix dafür ist recht einfach:

In der Datei „wp-content/plugins/traffic-stats_widget/wp-traffic-stats-widget.php“ Zeile 174, ersetzt man:

 $data = array (
 'IP' => $ip,
 'Time' => time(),
 'IS_BOT'=> tsw_is_bot(),
 'IS_HIT'=> is_hit($ip)
 );
 $format = array ('%s','%d', '%b','%b');
 $wpdb->insert( $table_name, $data, $format );

mit :

if (!$user_count) {
    $wpdb->query("INSERT INTO $table_name set IP='".$ip."', Time='".time()."', IS_BOT ='". tsw_is_bot() ."', IS_HIT='". is_hit($ip)."'");
}

Damit werden die Zugriffe wieder in die Datenbank eingetragen und die Stats zeigen in einigen Tagen wieder normale Werte an 😀