WordPress mit verschiedenen Datenbanknutzern absichern

WordPress ist nicht gerade ein Stück Software, das für sein herausragendes Sicherheitskonzept bekannt ist. Viele Dinge muss man erst mühsam im Alleingang nachbessern.

So hat es mich schon immer gestört, dass Nutzer, die sich meinen Blog ansehen, im Hintergrund den gleichen Datenbanknutzer verwenden, wie ich als Administrator, der die Seite konfiguriert und neue Bloginhalte bereitstellt. Wenn es möglich wäre, wenigstens für diese zwei stark gegenteiligen Nutzungsszenarien verschiedene Datenbanknutzer zu verwenden, wäre schon viel erreicht. Aus diesem Grund habe ich mich heute einmal hingesetzt und genau das implementiert. Alle Änderungen, die ich vornehmen mussten, sind so konzipiert, dass sie ein Update der WordPress-Installation überleben. Das heißt, dass keine Core-Files angerührt werden müssen. :)

Das größte Problem, das zu lösen war, ist, dass der Datenbanknutzer schon relativ früh beim Einlesen der "wp-config.php" gewählt wird. Die Information, dass man eingeloggt ist, steht jedoch erst viel später zur Verfügung. Es musste also ein Weg gefunden werden, diese Information bereits früher bereitzustellen. Meine Lösung ist es, beim erfolgreichen Login einfach eine Session-Variable zu schreiben und diese nach einem Logout wieder zu löschen. Das erledige ich mit einem Plugin:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
<?php
  /*
    Plugin Name: LoginSession
    Plugin URI: http://weizenspr.eu/
    Description: Generates a reusable PHP session when logged in.
    Version: 0.1c3
    Author: Kevin Niehage
    Author URI: http://weizenspr.eu/

    this code is based on http://wordpress.org/support/topic/using-session-in-wordpress
  */


  /* STOP EDITING HERE IF YOU DO NOT KNOW WHAT YOU ARE DOING */

  define("LOGINSESSION_LOGGEDIN", "loginsession_loggedin");
  define("LOGINSESSION_STARTED",  "loginsession_started");

  function loginsession_start() {
    $started = false;

    // check if session already exists
// will work starting with PHP 5.4.0:
//    if (PHP_SESSION_NONE === session_status()) {
    if ("" === session_id()) {
      $started = session_start();
    }

    // session should exist now
// will work starting with PHP 5.4.0:
//    if (PHP_SESSION_ACTIVE === session_status()) {
    if ("" !== session_id()) {
      // prevent session fixation
      session_regenerate_id(true);

      $_SESSION[LOGINSESSION_LOGGEDIN] = true;
      $_SESSION[LOGINSESSION_STARTED]  = $started;
    }
  }

  function loginsession_stop() {
    // check if session still exists
// will work starting with PHP 5.4.0:
//    if (PHP_SESSION_ACTIVE === session_status()) {
    if ("" !== session_id()) {
      // prevent session fixation
      session_regenerate_id(true);

      // remove loggedin value from session
      if (isset($_SESSION[LOGINSESSION_LOGGEDIN])) {
        unset($_SESSION[LOGINSESSION_LOGGEDIN]);
      }

      // check if we started the session
      if (isset($_SESSION[LOGINSESSION_STARTED])) {
        if ($_SESSION[LOGINSESSION_STARTED]) {
          // destroy the session if we did
          session_unset();
          session_destroy();

          // unset the session cookie
          if (isset($_COOKIE[session_name()])) {
            $params = session_get_cookie_params();
            setcookie(session_name(), "", time()-3600, $params["path"], $params["domain"], $params["secure"], $params["httponly"]);
          }
        } else {
          // remove started value from session if we did not
          unset($_SESSION[LOGINSESSION_STARTED]);
        }
      }
    }
  }

  add_action("wp_login",  "loginsession_start");
  add_action("wp_logout", "loginsession_stop");
?>

Anschließend bedarf es noch einer Änderung in der "wp-config.php". Dort werden statt einem Datenbanknutzer (bestehend aus DB_USER und DB_PASSWORD) nun zwei Datenbanknutzer definiert. Der mit den umfangreichen Rechten wird nur noch dann genutzt, wenn entweder der Wert "loginsession_loggedin" in der Session auf TRUE gesetzt ist oder wenn die Konstante "DOING_CRON" definiert ist. Das eine ist der Fall, wenn der WordPress-Nutzer eingeloggt ist, das andere ist der Fall, wenn das Script "wp-cron.php" ausgeführt wird:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
$loginsession_evaluated = false;
// open the session if there is one
if ((isset($_COOKIE[session_name()])) || (isset($_GET[session_name()]))) {
  session_start();

  if ((isset($_SESSION["loginsession_loggedin"])) &&
      ($_SESSION["loginsession_loggedin"])) {
    $loginsession_evaluated = true;
  }
}

// select user dependent on loginsession
if (($loginsession_evaluated) || (defined("DOING_CRON"))) {
  define("DB_USER",     "<ADMIN USER>");
  define("DB_PASSWORD", "<ADMIN PASSWORD>");
} else {
  define("DB_USER",     "<GUEST USER>");
  define("DB_PASSWORD", "<GUEST PASSWORD>");
}

Damit das ganze ordentlich funktioniert, müsst ihr natürlich noch den Datenbanknutzer für eure Gäste anlegen. Dazu verbindet ihr euch mit eurer Datenbank (wahrscheinlich MySQL) und führt dort ein paar Befehle aus. Ich gehe davon aus, dass eure Datenbank "wordpress" heißt und ihr den Präfix "wp_" verwendet habt.

1
2
3
4
5
6
7
8
CREATE USER '<GUEST USER>'@'%' IDENTIFIED BY '<GUEST PASSWORD>';
GRANT SELECT ON wordpress.* TO '<GUEST USER>'@'%';
GRANT INSERT ON wordpress.wp_commentmeta TO '<GUEST USER>'@'%';
GRANT INSERT ON wordpress.wp_comments TO '<GUEST USER>'@'%';
GRANT UPDATE ON wordpress.wp_commentmeta TO '<GUEST USER>'@'%';
GRANT UPDATE ON wordpress.wp_comments TO '<GUEST USER>'@'%';
GRANT DELETE ON wordpress.wp_commentmeta TO '<GUEST USER>'@'%';
GRANT DELETE ON wordpress.wp_comments TO '<GUEST USER>'@'%';

Mit dieser Grundausrüstung können eure Gäste weiterhin alles lesen, jedoch nur noch Kommentare erstellen. Sie können hingegen keine Nutzeraccounts mehr manipulieren, keine Blogbeiträge mehr manipulieren und auch keine Konfigurationseinstellungen mehr manipulieren. So schnell habt ihr euren WordPress-Blog vor jeder Menge Zero-Day-Exploits abgesichert.

Mit diesen restriktiven Einstellungen funktioniert eins jedoch (offenbar) nicht mehr: das Verwenden des WordPress-Cronjobs. Dieser wird typischerweise regelmäßig durch die Besucher des Blogs gestartet. Das ganze Problem kann jedoch wie folgt umgangen werden. Zuerst einmal muss in die "wp-config.php" noch eine weitere Zeile aufgenommen werden:

1
define("DISABLE_WP_CRON", true);

Anschließend richtet ihr in eurem System einen echten Cronjob ein, der in regelmäßigen Abständen folgenden Befehl aufruft. Achtet darauf, dass der Cronjob seltener läuft, als ein PHP-Script bei euch laufen darf. Damit verhindert ihr Locksituationen.

1
wget -q -O - http://<BLOGURL>/wp-cron.php?doing_wp_cron >/dev/null 2>&1

Je nachdem, was ihr sonst noch so für Plugins betreibt, kann es notwendig sein, dass ihr dem Account "<GUEST USER>" weitere Rechte in eurer Datenbank einräumt - zum Beispiel, wenn ihr ein Nutzertracking verwendet. Da dies jedoch davon abhängt, was ihr sonst noch alles so für Plugins verwendet, kann dies nicht Teil dieses Blogbeitrags sein. ;)

Zum Schluss noch etwas Rechtliches:
Der Autor dieses Programms haftet nicht für Schäden an Soft- oder Hardware oder Vermögensschäden, die durch das Benutzen des Programms entstehen, es sei denn, diese beruhen auf einem grob fahrlässigen oder vorsätzlichen Handeln des Autors, seiner Erfüllungsgehilfen oder seiner gesetzlichen Vertreter.

Absichernde Grüße, Kenny

Amazon erweitert Amazon Prime um Videostreaming

Dies ist ein honorierter Werbeartikel.

Amazon Instant Video Einführung

Amazon Instant Video Einführung

Die Überraschung war groß: Amazon erweitert ab heute sein Angebot Amazon Prime um die Video on Demand Funktion von Lovefilm.de. Damit haben alle Prime-Kunden eine Online Videothek an der Hand, über die sie Filme, Serien, Kinohits und Blockbuster auf ihrem TV, ihrer Playstation 3 (PS3) und Playstation 4 (PS4), ihrem Kindle Fire HD und Kindle Fire XHD, ihrer XBOX One und XBOX 360, sowie anderer Computer und Mobilgeräte sehen können.

Das ganze nennt sich dann Prime Instant Video und ist ein weiterer Teil des Prime-Angebotes - neben dem bekannten, kostenlosen Premiumversand und der Kindle-Leihbücherei, die bereits jetzt Teil des Angebotes sind.

Für Leute, die Amazon Prime bereits nutzen, gilt der alte Preis von 29€/Jahr noch bis zur nächsten Beitragszahlung, bei der der Preis dann auf die neuen 49€/Jahr angehoben wird. So erhielt ich gestern von Amazon eine E-Mail mit folgendem Inhalt:

[...] wir freuen uns, Ihnen wichtige Verbesserungen und Neuerungen zu Ihrer Mitgliedschaft bei Amazon Prime mitteilen zu können. Seit 2007 haben wir die Auswahl an Produkten, die über Amazon Prime mit Premiumversand bestellbar sind, auf mehrere Millionen ausgebaut. Zudem stehen Ihnen mehr als 500.000 Bücher in der Kindle-Leihbücherei kostenlos zur Verfügung. Und jetzt wird Amazon Prime noch besser.
Ab dem 26. Februar umfasst Ihre Amazon Prime-Mitgliedschaft auch Amazons neuen Video Streaming Service Prime Instant Video.
Mit Prime Instant Video haben Sie künftig unbegrenzten Zugang zu über 12.000 digitalen Filmen und Serienepisoden. Ab dem 26. Februar können Sie überall und so oft Sie möchten Ihre Lieblingsfilme und -serien über Prime Instant Video sehen, und das auf vielen beliebten Endgeräten, wie dem Kindle Fire, iPhone und iPad sowie Smart-TVs, Blu-ray Player und Spielekonsolen.
Das neue Prime bietet Ihnen unbegrenzten Zugriff auf Serienhits wie [...].
Als Prime-Mitglied können Sie ab dem 26. Februar den Video Streaming Service ohne zusätzliche Kosten in Anspruch nehmen. Die Gebühr für Amazon Prime bleibt bis zur nächsten Verlängerung Ihrer Mitgliedschaft am [...] unverändert. Danach beträgt die jährliche Mitgliedschaftsgebühr nur 49 EUR. Im Vergleich zu zwei separaten Mitgliedschaften bei Prime und dem Streaming Service Lovefilm bedeutet dies eine jährliche Ersparnis von 63 EUR. Darüber hinaus genießen Sie natürlich weiterhin alle Vorteile von Prime.
Es gelten die neuen Allgemeinen Geschäftsbedingungen.
Sollten Sie noch weitere Fragen haben, stehen wir Ihnen gerne zur Verfügung. Sie erreichen uns per E-Mail, Telefon oder im Chat über den Hilfe-Bereich auf Amazon.de.
Vielen Dank für Ihr Vertrauen in Amazon Prime.
Ihr Amazon Prime-Team

Wie schon in der E-Mail zu lesen ist: Bisher zahlte man für Amazon Prime 29€/Jahr, der LoveFilm Video on Demand Service war ab 6,99€/Monat zu haben - beide zusammen kosteten also 63,88€/Jahr mehr, als man nun für das neue Amazon Prime inklusive Amazon Instant Video ausgeben muss.

Amazon Instant Video

Amazon Instant Video

Im Zuge der Einführung des neuen Angebotes überarbeitet Amazon offenbar auch das LoveFilm-Angebot. So gibt es die Möglichkeit, Amazon Instant Video auch in einem monatlichen Abo zu nutzen; dann jedoch zu einem Preis von 7,99€/Monat - das entspricht einer Preiserhöhung des alten LoveFilm Video on Demand von 1€/Monat. Gegenüber dem Angebot im Jahresabo ist das Monatsabo knapp 50% teurer.

Im Bereich LoveFilm gibt es derzeit einige Ungereimtheiten, vor allem dann, wenn die Nutzer gleichzeitig Prime-Kunden sind. Hier wird sich hoffentlich in den nächsten Tagen klären, wie die Zukunft des DVD-Verleih-Service aussehen wird. Es gibt jedenfalls bereits einige Bewegung in der Nutzerschaft - die einen kündigen LoveFilm, um auf Amazon Prime zu wechseln. Die anderen wiederum kündigen Amazon Prime, da sie Nutzer eines anderen Streaming-Anbieters sind. Es wird spannend sein, zu sehen, ob sich die Zusammenlegung der Dienste für Amazon am Ende lohnt.

Amazon Instant Video PIN

Amazon Instant Video PIN

Ich werde in den nächsten Tagen den neuen Amazon Video Service einmal ausgiebig testen. Positiv aufgefallen ist mir bereits, dass es eine PIN gibt, die man definieren kann, um sich vor dem versehentlichen, kostenpflichtigen Ausleihen von Filmen und Serien zu schützen. Bei meinem alten Video on Demand Anbieter musste ich mir solch eine Lösung selber zusammenbasteln.

Abschließend: Amazon Prime kann man 30 Tage kostenlos testen. Damit hat man dann Zugriff auf den kostenlosen Premium-Versand, die Kindle-Leihbücherei und Amazon Instant Video. Sollte euch das Angebot trotz allem nicht überzeugen, könnt ihr es relativ einfach wieder kündigen.

Wie seht ihr die Neuerungen bei Amazon Prime? Seid ihr bereits Nutzer dieses Angebotes? Wollt ihr es jetzt bestellen? Oder habt ihr es gar gekündigt?

On-Demand-Grüße, Kenny

Blog Marketing Blog-Marketing ad by hallimash

WordPress Version verstecken

Es hat mich schon immer genervt, dass WordPress relativ gesprächig ist, wenn es um Interna des Systems geht. So wird mit Freuden für jede geladene JavaScript-Datei die Versionsnummer angegeben, es werden interne URL-Strukturen verraten und selbst die Version der eigentlichen Software findet sich hier und dort wieder.

Ich hatte deshalb damals angefangen, die URL-Struktur meines Blogs zu verbergen. Nach mehreren Jahren kann ich sagen, dass dies viele Angriffe verhindert hat (vor allem in letzter Zeit, wo die Angriffe auf WordPress-Blogs stark zunahmen).

Doch auch mit der Versionnummer, die sich im Generator-Tag im HTML-Quelltext und im RSS-Feed findet, lässt sich einiges anfangen. Auch diese Informationsquelle wollte ich potentiellen Angreifern gern entziehen. Zum Glück gibt es z.B. auf wpbeginner.com alles, was man wissen muss - es muss nur noch in ein Plugin überführt werden. Aktivieren. Fertig.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
  /*
    Plugin Name: HideVersion
    Plugin URI: http://weizenspr.eu/
    Description: Hides the WordPress version from generated pages.
    Version: 0.1c1
    Author: Kevin Niehage
    Author URI: http://weizenspr.eu/

    this code is based on http://www.wpbeginner.com/wp-tutorials/the-right-way-to-remove-wordpress-version-number/
  */


  /* STOP EDITING HERE IF YOU DO NOT KNOW WHAT YOU ARE DOING */

  // remove generator from HTML head
  remove_action("wp_head", "wp_generator");

  // remove generator from RSS
  function hideversion_returnempty() {
    return "";
  }
  add_filter("the_generator", "hideversion_returnempty");
?>

Auf Seiten wie z.B. isitwp.com kann man dann einfach mal ausprobieren, ob einfache Analyser noch Erfolg haben. Es wäre natürlich großartig, wenn diese bei der Erkennung einfach komplett versagen. Das Ergebnis beim Einsatz von HideStructure und HideVersion sieht jedenfalls so aus:

Is it WordPress?

Is it WordPress?

Der ein oder andere mag natürlich der Überzeugung sein, dass es relativ sinnlos ist, verschleiern zu wollen, welches CMS man auf einem privaten Blog einsetzt. Dahinter steht jedoch einiges mehr. Das unnötige Verraten von internen Strukturen bezeichnet man hinlänglich als Information Leakage. Es mag auf den ersten Blick nicht immer ersichtlich sein, wofür solche Informationen genutzt werden, aber ein Nutzen ist jedenfalls gegeben. So kann ein Angreifer z.B. durch das regelmäßige Prüfen der Versionsnummer herausfinden, wie lange der Betreiber in der Regel benötigt, um auf eine aktuelle Version zu wechseln.

Wenn wir als Beispiel den neuen "sicheren" E-Mail-Dienst mailbox.org nehmen, sehen wir relativ schnell, dass der Dienst tatsächlich WordPress verwendet.

Zum Schluss noch etwas Rechtliches:
Der Autor dieses Programms haftet nicht für Schäden an Soft- oder Hardware oder Vermögensschäden, die durch das Benutzen des Programms entstehen, es sei denn, diese beruhen auf einem grob fahrlässigen oder vorsätzlichen Handeln des Autors, seiner Erfüllungsgehilfen oder seiner gesetzlichen Vertreter.

Versionierte Grüße, Kenny

Neue Schriftart, neue Logos: 5blocks

Vor 5 Jahren musste schnell ein Logo her - nach ein bisschen Recherche entschied ich mich dafür, eine eher verspielte, "gekritzelt" wirkende Schriftart namens "Pigae" zu verwenden - das WeizenSpr.eu Logo war geboren!

WeizenSpr.eu Logo seit 5 Jahren

WeizenSpr.eu Logo seit 5 Jahren

In den letzten Tagen kam mir die Idee, für meine Webseiten einheitliche Logos einzuführen, um die Zusammengehörigkeit der Projekte zu unterstreichen. Um den ganzen eine eigene Note zu verpassen, wollte ich die Schriftart jedoch selbst gestalten. Sie sollte einer klaren Symmetrie unterliegen und leicht reproduzierbar sein - mitunter sogar händisch. Das Ergebnis: 5blocks.

5blocks Font

5blocks Font

Das Grundprinzip ist relativ einfach: Jeder Buchstabe bestehlt in der Regel aus einer 5x5 großen Box aus Pixeln. Nach unten ausbrechende Buchstaben (f, g, j, p, q), nach oben ausbrechende Buchstaben (b, d, f, h, i, j, k, l, t) und seitlich ausbrechende Buchstaben (m, w) haben dafür nochmal jeweils zwei angrenzende Pixel Platz. Nach Möglichkeit verlaufen Linien über die gesamte Breite der Box. Schräge Linien bestehen aus 1,5 Pixel hohen Elementen. Voila!

Da sich das ganze relativ einfach als Vektorgrafik realisieren lässt, brauche ich jedes Logo nur noch einmal zu erstellen und kann diese dann beliebig skalieren. Ich finde, meine Logos sahen noch nie so gut aus. :D

5blocks Logos

5blocks Logos

5blocks Logos

5blocks Logos

Eine Besonderheit in den Logos ist der Punkt. Meine Projektnamen basieren auf den Domainnamen des jeweiligen Projektes. Um zu visualieren, dass der Punkt der Domain ein integraler Bestandteil des Projektnamens ist, habe ich ihn kurzerhand in den ersten Buchstaben der jeweiligen Top-Level-Domain integriert. So unterbricht er nicht den Lesefluss, ist aber trotzdem vorhanden. :)

Ich hoffe, euch gefallen die neuen Logos. :)

Artige Grüße, Kenny

5 Jahre WeizenSpr.eu

Kaum zu glauben, aber es ist inzwischen 5 Jahre her, dass ich am 02.02.2009 den ersten Artikel hier im Blog veröffentlicht habe. Seitdem hat sich nicht nur WeizenSpr.eu verändert, sondern auch mein Leben.

Der Blog lief anfangs auf einem Shared Hosting Server eines kleinen Unternehmens, bevor ich ihn zum Shared Hosting von Hetzner umzog. Von da an zog er erst zu einem virtuellen Server, dann zu einem schwachen dedizierten Server und abschließend zum derzeitigen dedizierten Server mit 16GB RAM, Quad-Core und 3TB RAID-1.

Ähnlich verlief es auch in meinem Leben. Vom dualen Studium in Mannheim und meinem Eintritt in die Piratenpartei zog ich nach Berlin, um dort meinen ersten Job anzutreten und die Gründung der Hellersdorfer Ortsgruppe der Piratenpartei anzustoßen. Inzwischen habe ich meinen Arbeitgeber gewechselt und bin wieder aus der Piratenpartei ausgetreten - die tollen Kontakte dort sind geblieben. Inzwischen beschäftige ich mich weniger Politik und dafür mehr mit der Entwicklung von Sicherheitshardware. Über letzteres gibt es auch einige Artikel hier im Blog zu lesen.

Ich bin gespannt, was die nächsten 5 Jahre bringen werden. Vielleicht wird bloggen ja wieder so cool, wie es zu der Zeit war, als ich damit anfing. Leider sind viele Blogger zum reinen Mikroblogging gewechselt. Dabei könnte Deutschland noch spannende Blogs mit persönlicher Note gebrauchen.

An dieser Stelle vor allem einen Dank an meine Leser. Einige von euch begleiten mich seit den Anfängen, andere sind mit der stärkeren Fokussierung auf Technikthemen dazu gekommen. Ich freue mich immer wieder, wenn Leute mich wegen Artikeln anschreiben und tiefgründigere Fragen oder Anmerkungen zu ihnen haben. Das ist der Grund, weshalb ich blogge: Erfahrungsaustausch. :)

Also dann! Bis demnächst!

Bloggende Grüße, Kenny

Seite 3 von 78« Erste...234...Letzte »