Apache Backdoor Modul

From C4 Wiki
Revision as of 20:53, 24 October 2011 by 87.79.236.180 (talk) (TODO until thursday)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)
Jump to: navigation, search

TODO until thursday

  • Logging abschalten (siehe Log-Hook-> setzen einer Node)
  • GET und POST gleichzeitig ermöglichen (-> Präprozessordirektiven) --> DONE
  • Obfuscate in eigene Funktion auslagern
  • Outputbytes (buf_len) variabel machen --> DONE (realloc verwendet)

Roadmap

  • Modul bauen und auf Apache laufen lassen [done]
  • Daten an Apache senden und empfangen
  • Sachen, die das Modul können soll
    • Request-Manipulation (Logs, usw.)
    • Request auslesen/verarbeiten (ist das für mich?)
    • Commands ausführen (Prozesse spawnen, fest verdrahtete Befehle (wie ist mein Status?))
    • Evtl. Prozessmanagment oder sowas --> Prozess spawnen und später wieder abfragen. ...
    • Persistence (Daten ablegen/holen)
  • Schnittstellen definieren.
  • Einen Client bauen, der mit dem Modul kommunizieren kann und eine komfortable API bereitstellt.

Hello, world

Hier scheint ein brauchbares Tutorial für die erste Erfahrung zu liegen: http://www.penguinpowered.org/documentation/apache2_modules.html

Werde das jetzt mal durcharbeiten und meine Erfahrungen hier dokumentieren.

Webserver aufsetzen

Für dieses Beispiel habe ich einen Ubuntu Server frisch aufgesetzt. Bei abweichender Ausgangslage bitte entsprechend improvisieren.

Nach der Installation brauchen wir erstmal einen Apache2. Damit wir an das apxs-Kommando aus dem Tutorial kommen holen wir uns noch ein Zusatzpaket:

hund@surfer:~$ sudo apt-get install apache2 apache2-threaded-dev

Je nach verwendetem MPM scheint man statt apache2-threaded-dev auch apache2-prefork-dev verwenden zu können.

Die Standardkonfiguration vom Apachen sollte erstmal genügen --> Websites liegen in /var/www
Zuerst empfiehlt sich ein kurzer Blick in die Manpage.

hund@surfer:~$ man apxs2 

Modul bauen

Zunächst erstelle ich eine Datei mod_hello.c in meinem home-Directory. Der Quellcode ist im Tutorial zu finden. Leider ist dieser fehlerhaft, hier die korrigierte und leicht gekürzte Fassung:

#include "httpd.h" 
#include "http_config.h" 
#include "http_core.h" 
#include "http_log.h" 
#include "http_main.h" 
#include "http_protocol.h" 
#include "http_request.h" 
#include "util_script.h" 
#include "http_connection.h" 

/* This example just takes a pointer to the request record as its only 
* argument */ 
static int hello_handler(request_rec *r) 
{ 

        /* We decline to handle a request if hello-handler is not the value 
         * of r->handler */ 
        if (strcmp(r->handler, "hello-handler")) { 
                return DECLINED; 
        } 

        /* The following line just prints a message to the errorlog */ 
        ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_NOTICE, 0, r->server, 
        "mod_hello: %s", "Before content is output"); 

        /* We set the content type before doing anything else */ 
        ap_set_content_type(r, "text/html"); 

        /* If the request is for a header only, and not a request for 
         * the whole content, then return OK now. We don't have to do 
         * anything else. */ 
        if (r->header_only) { 
                return OK; 
        } 

        /* Now we just print the contents of the document using the 
         * ap_rputs and ap_rprintf functions. More information about 
         * the use of these can be found in http_protocol.h */ 
        ap_rputs("<HTML>\n", r);
	ap_rputs("\t<HEAD>\n", r);
	ap_rputs("\t\t<TITLE>\n\t\t\tHello There\n\t\t</TITLE>\n", r);
	ap_rputs("\t</HEAD>\n\n", r);
	ap_rputs("<BODY BGCOLOR=\"#FFFFFF\>"\n" ,r);
	ap_rputs("<H1>Hello </H1>\n", r);
	ap_rputs("Hello world\n", r);
	ap_rprintf(r, "<br>A sample line generated by ap_rprintf<br>\n");
	ap_rputs("</BODY></HTML>\n" ,r); 

        /* We can either return OK or DECLINED at this point. If we return 
        * OK, then no other modules will attempt to process this request */ 
        return OK; 
} 


/* Each function our module provides to handle a particular hook is 
* specified here. See mod_example.c for more information about this 
* step. Suffice to say that we need to list all of our handlers in 
* here. */ 
static void x_register_hooks(apr_pool_t *p) 
{ 
        ap_hook_handler(hello_handler, NULL, NULL, APR_HOOK_MIDDLE); 
} 


/* Module definition for configuration. We list all callback routines 
* that we provide the static hooks into our module from the other parts 
* of the server. This list tells the server what function will handle a 
* particular type or stage of request. If we don't provide a function 
* to handle a particular stage / callback, use NULL as a placeholder as 
* illustrated below. */ 
module AP_MODULE_DECLARE_DATA hello_module = 
{ 
        STANDARD20_MODULE_STUFF, 
        NULL, /* per-directory config creator */ 
        NULL, /* directory config merger */ 
        NULL, /* server config creator */ 
        NULL, /* server config merger */ 
        NULL, /* command table */ 
        x_register_hooks, /* other request processing hooks */ 
}; 


Jetzt können wir das Modul erstellen:

hund@surfer:~$ sudo apxs2 -c -i -a mod_hello.c

Das kompiliert unseren Code zu einem Modul, kopiert die fertige .so-Datei an den richtigen Ort, aktualisiert die Apache2-Konfiguration und aktiviert das neue Modul. Für den späteren Produktiveinsatz werden diese Schritte manuell übernommen. Wenn alles gutgeht, sehen wir etwa das:

...
chmod 644 /usr/lib/apache2/modules/mod_hello.so
[preparing module `hello' in /etc/apache2/mods-available/hello.load]
Enabling module hello.
Run '/etc/init.d/apache2 restart' to activate new configuration!

Unser fertiges Modul liegt nun unter /usr/lib/apache2/modules/mod_hello.so. Was hat das Programm sonst noch gemacht?

Das Modul wurde aktiviert:

hund@surfer:~$ ls -l /etc/apache2/mods-enabled/ | grep hello
lrwxrwxrwx 1 root root 28 2011-10-05 21:11 hello.load -> ../mods-available/hello.load

Und der Pfad wie oben beschrieben festgelegt:

hund@surfer:~$ cat /etc/apache2/mods-available/hello.load 
LoadModule hello_module       /usr/lib/apache2/modules/mod_hello.so

Testlauf

Bevor wir unser Modul nun benutzen können, müssen wir noch den Handler aktiv schalten. Das können wir in einem beliebigen VirtualHost festlegen. Für dieses Beispiel habe ich /etc/apache2/sites-enabled/000-default verwendet.

Ich möchte, dass das neue Modul aufgerufen wird, wenn die Ressource /hello vom Apache erfragt wird. Dazu füge ich folgenden Knoten

<Location /hello>
         SetHandler hello-handler
</Location>

...hinzu. Anschließend wird der Apache neu gestartet:

hund@surfer:~$ sudo /etc/init.d/apache2 restart

Wenn ich jetzt im Browser http://ip_vom_apache/hello abrufe, bekomme ich den generierten Text vom Modul ausgegeben. Greife ich auf andere Ressourcen zu, verhält sich Apache wie sonst auch. Nur bei der von uns festgelegten Ressource wird das Modul aktiv. Warum dieses Verhalten?

Im Quellcode des Moduls haben wir festgelegt, dass der Name des Handlers hello-handler ist.

/* We decline to handle a request if hello-handler is not the value 
  * of r->handler */
  if (strcmp(r->handler, "hello-handler")) {
      return DECLINED;
  }

In /etc/apache2/modules-enabled wird unser Modul geladen. Von nun an sind also alle Handler dieses Moduls verfügbar. Wenn wir nun in einem VHost diesen Handler verwenden möchten, müssen wir ihn nur noch beim Namen nennen. Das passiert im Location-Knoten von oben:

SetHandler hello-handler

Gratulation, wir haben jetzt ein funktionierendes Modul!

Übrigens wurde auch der Logaufruf aus dem Code ausgeführt:

hund@surfer:~$ tail /var/log/apache2/error.log 
...
[Wed Oct 05 23:00:02 2011] [notice] mod_hello: Before content is output


lama

Sammeln und Seltenes

Rechte zu verschiedenen Zeiten

Rechte in folgenden Hoods überprüfen:

  • test_config
  • optional_fn_retrieve
  • pre_config
  • post_config
  • open_logs
  • pre_mpm
  • child_init

vgl: Nick Kew: The Apache Modules Book, Prentice Hall 2007, S. 268

darth