We’ve recently been hit by several waves of DDOS attacks of various different kinds. Layer3/4 is obviously something that our hosting provider needs to deal with, but we need to defend ourselves against Layer 7. One pattern that frequently presents itself is WordPress pingback abuse. This is nothing new, there are in fact a couple of blog posts dating back as far as 2012, maybe even earlier than that, when the WordPress community in their infinite wisdom decided to enable XML-RPC by default for the sake of the WordPress App and some Jetpack features.

Now this opens the very interesting vector of bouncing requests off any WordPress installation that hasn’t explicitly disabled pingbacks (for example using the Disable xml rpc pingback plugin. For details as to what’s going on, you may wish to read Incapsula blogpost from April 30th, 2013 or the Akamai blogpost from March 31, 2014 on the same issue.

TL;DR: A single compromised attack zombie would issue a lot of requests to vulnerable WordPress sites that would ask them to send pingback verification requests to the intended target. This would camouflage the zombie’s IP address for anything that’s scanning traffic on the network level, as the traffic that’s hitting the target would originate from the WordPress sites, not from the zombie. Et voilà: Lots of fresh IPs available to the DDOS attack without even compromising these origins directly.

Only when inspecting the UserAgent would the target notice the nature of these requests – this UserAgent has the form WordPress/[version]; http://[wordpress-ip]; verifying pingback from [zombie-ip], so for example „WordPress/4.3.6; http://555.555.555.555; verifying pingback from 666.666.666.666“.

CloudFlare offers to block these requests altogether with rule number 100047WP, which is disabled by default and needs to be enabled in Firewall, Web Application Firewall, Package: CloudFlare Rule Set, Rule details, CloudFlare Specials and then enabling „Block WordPress User-Agent completely (Pingback attack)“ which is currently on page 9 of this long list of rules. If you have no WordPress installed and/or you don’t care about this pingback nonsense, there’s no good reason to not turn this on.

If you wish to block these requests on your Apache webserver, you could use the following Rewrite statements in your VirtualHost:

This would still allow WordPress UserAgents to read your RSS feed for example, but the pingback crap would be dropped. You’ll still be hit by the malicious requests though, and they may still make an impact by consuming traffic, filling the logs and taking up webserver resources until the Forbidden response, so doing this at any prior stage where it might be possible to apply some filtering on the UserAgent string would probably be beneficial.

If you wish to check if this is working, you could test this with a simple wget directly on your webserver:

If you haven’t got shell access, you can drop the header param and instead of http://127.0.0.1/ target your site directly, but please don’t test this with anything but your own website.

Oh, btw: If you’re reading this and you’re the one that is responsible for us digging around knee deep in our server logs and wasting lots and lots of time and effort just in order to keep our websites running – I’m quite fantastically curious about your motivation in all this. Maybe you could show us the courtesy to at least let us know somehow? That would be terrific!

Ab und an benötigt man einen Cronjob der auch unter einer Minute ausgeführt werden soll, ohne sich erst ein Bashscript mit Loop basteln zu müssen. Der Trick dabei ist der „sleep“-Befehl im crontab und dass man den Eintrag mehrfach vornehmen muss.

Möchte man ein Script alle 30 Sekunden ausführen, trägt man folgendes ein:

Möchte man ein Script alle 5 Sekunden ausführen lassen, wird es schon etwas umfangreicher – Bspw.:

Wenn man eigenen Text vor Laien(!) vor Kopieren schützen möchte, ohne den Rechtsklick zu deaktivieren, kann man die Zwischenablage auch manipulieren. Ich habe das auf meiner privaten Seite im Einsatz. Für Framework-Verächter anbei auch jeweils die Version mit normaler Dom-Manipulation.

Funktioniert in: Chrome 42+, Firefox 41+, IE 9+, Opera 29+, Safari X

Searchengineland haben getestet, was Google inzwischen alles an JavaScript verdaut – sehr interessanter Artikel. Sogar <meta>-Injektion funktioniert – so weit, so schön. Auf der anderen Seite dürfen wir davon ausgehen, dass das OnPage-Link-Shaping durch das Ersetzen von href-Links durch JavaScript nun auch nicht mehr funktioniert, da Google diesen Umweg einfach mitgeht. Ist Link-Shaping (bzw. eher das Kaschieren von aus SEO-Sicht überflüssigen Links) damit gestorben oder weicht man jetzt generell auf viele, viele POSTs aus? Ich fände letzteres ja superhässlich.

We Tested How Googlebot Crawls Javascript And Here’s What We Learned

Öffnet sich aufgrund von target-Attribut oder JS-Event ein neues Fenster für einen a-Link, so kann es schwierig sein, z.B. an die Netzwerk-Daten aus den Webdeveloper-Tools zu kommen, da es wohl keinen Weg gibt, die Developer-Tools automatisch auch für ein neues Fenster zu öffnen – und wenn man das im neuen Fenster manuell macht, ist es in der Regel zu spät.

Führ man das folgende Snippet in der Developer-Konsole aus, so wird das target-Attribut wieder auf _self gesetzt und der Link öffnet sich im selben Tab. Im Netzwerk-Tab muss man dann nur noch „Preserve Log“ aktivieren und presto – alles ist wieder gut.

Die OneBox ist für uns eine überaus wichtige Traffic-Quelle. Umso wichtiger ist es, dass unsere News-Artikel hier zeitnah auflaufen und auch angemessen ranken. Die Mechanismen für Google News sind selbstverständlich umgesetzt, neben dem Basis-Programm wird Google auch via Sitemap-Ping unmittelbar zur Veröffentlichung einer News informiert – wir haben bisweilen eine neue News innerhalb von 30 Sekunden nach Veröffentlichung in der OneBox gesehen.

Unser Problem mit der OneBox bei einer unserer Seiten betraf allerdings News, die schon ein paar Minuten alt waren. Dort hatte Google bisweilen das Datum der News in die Vergangenheit verlegt, so dass eine News, die gerade erst eine dreiviertel Stunde online war nun plötzlich als „vor drei Tagen“ in der OneBox auflief – wenn denn überhaupt, denn mit der vermeintlichen Altersschwäche der Artikel sank auch die Wahrscheinlichkeit, überhaupt in der OneBox zu ranken – kein Wunder, da es dem Artikel nach Googles Ansicht ja an „Freshness“ mangelte.
Weiterlesen

Veröffentlicht unter SEO.

Mitunter möchte man ein Abfrageergebnis nach einer vorgegebenen Liste von IDs sortieren, also weder alphabetisch nach Namen, noch numerisch nach Wert, sondern auf Basis einer konfigurierten Reihenfolge von Werten. Da man in PostgreSQL auch Funktions-Ergebnisse als Argumente für eine Sortierung verwenden kann, können wir eine Hilfsfunktion in der Datenbank deklarieren, über die sich diese Form der Sortierung umsetzen lässt:

Jetzt können wir die Funktion zur Sortierung einsetzen:

Das NULLS LAST stellt sicher, dass Werte die nicht in der Liste enthalten sind ans Ende des Ergebnisses sortiert werden.

Bei sehr umfangreichen Datenmengen kann die direkte Nutzung eines Index für die Funktion sinnvoll sein. Die ist aufgrund der IMMUTABLE-Deklaration auch möglich, allerdings nur für eine spezifische Werteliste, die damit Teil der Index-Deklaration werden muss. Im Normalfall genügt allerdings ein Index auf das verwendete Feld selbst.

In ColdFusion kann auch an dieser Stelle <cfqueryparam> für die Sortierung eingesetzt werden. Wichtig ist dabei, dass hier der richtige Datentyp für die Liste gewählt wird – z.B. wenn die Spalte vom Typ int8/bigInt ist. Auch einfache int-Arrays (cf_sql_integer) oder Text-Arrays (cf_sql_varchar) sind natürlich möglich.

Schönes kleines WTF am späten Nachmittag:

BLAM!

Element STRUCTDATA.DEALIDS is undefined in LOCAL.
The error occurred in /var/www/.../some.cfc: line 120
118 : while( local.objCursor.hasNext() ){
119 : local.structData = local.objCursor.next();
120 : if (structKeyExists(local.structData,'dealIds') && isArray(local.structData.dealIds)) {

Weiterlesen

Nur weil’s gerade einen Kollegen mal wieder gebissen hat: ColdFusion and Pass by Reference versus Value

Kurzfassung: In CF (wie auch in Perl) werden defaultmäßig nur Primitive als Werte zugewiesen, alles andere nur als Referenz. Wenn man z.B. einen Loop baut und den Elementen eines Arrays eine Structure zuweist, kann das dazu führen, dass Werte in anderen Elementen überschrieben werden. Wenn man statt der Referenz also die Werte benötigt, ist duplicate() erforderlich.

Java dagegen nutzt immer pass by value, bei C++ und C# ist das ebenfalls der Default, wobei die mit dem ref-Keyword auch pass by reference unterstützen.

Diese subtile kleine Besonderheit ist immer wieder gut für schöne Brainfuck-Bugs 😉