Bugtraq mailing list archives

Re: Linux Slapper Worm


From: Ajai Khattri <ajai () bitblit net>
Date: Wed, 18 Sep 2002 12:50:13 -0400

Not seeing any announcement from my vendor (and not wanting to compile SSL from source), I set out to see if there was some way of avoiding being infected in the first place. I decided to hack my Apache (1.3.26) source code to send a bogus Server: header (seeing as this is how Slapper detects what web software is running). There is no way of disabling this header or controlling exactly what is included in the string, so I hacked. This is really quite easy to do:

In src/include/httpd.h I added an extra value to the server_token_type enumeration and an extra #define:

#define SERVER_BASEVENDOR   "Apache Group"
#define SERVER_BASEPRODUCT  "Apache"
#define SERVER_BASEREVISION "1.3.26"
#define SERVER_BASEVERSION  SERVER_BASEPRODUCT "/" SERVER_BASEREVISION

#define SERVER_PRODUCT  SERVER_BASEPRODUCT
#define SERVER_REVISION SERVER_BASEREVISION
#define SERVER_VERSION  SERVER_PRODUCT "/" SERVER_REVISION
#define SERVER_HIDE "A p @ c h e"

enum server_token_type {
    SrvTk_MIN,          /* eg: Apache/1.3.0 */
    SrvTk_OS,           /* eg: Apache/1.3.0 (UNIX) */
    SrvTk_FULL,         /* eg: Apache/1.3.0 (UNIX) PHP/3.0 FooBar/1.2b */
    SrvTk_PRODUCT_ONLY, /* eg: Apache */
    SrvTk_SECURE        /* To fool Slapper */
};

(Note SERVER_HIDE and SrvTk_SECURE. Of course, SERVER_HIDE can be anything you want it to be).

Next, I looked at src/main/http_core.c, in the function set_serv_tokens():

static const char *set_serv_tokens(cmd_parms *cmd, void *dummy, char *arg)
{
    const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
    if (err != NULL) {
        return err;
    }

    if (!strcasecmp(arg, "OS")) {
        ap_server_tokens = SrvTk_OS;
    }
    else if (!strcasecmp(arg, "Min") || !strcasecmp(arg, "Minimal")) {
        ap_server_tokens = SrvTk_MIN;
    }
    else if (!strcasecmp(arg, "Full")) {
        ap_server_tokens = SrvTk_FULL;
    }
    else if (!strcasecmp(arg, "Prod") || !strcasecmp(arg, "ProductOnly")) {
        ap_server_tokens = SrvTk_PRODUCT_ONLY;
    }
    else if (!strcasecmp(arg, "Secure")) {
        ap_server_tokens = SrvTk_SECURE;
    }
    else {
        return ap_pstrcat(cmd->pool, "Unrecognised ServerTokens keyword: ",
                          arg, NULL);
    }
    return NULL;
}

So, when parsing the config file, it looks for a value of "Secure" for the ServerTokens config directive. Here I set it to SrvTk_SECURE which I defined in the src/include/httpd.h earlier.

Finally, in src/main/http_main.c, in the function ap_set_version() I added an extra else if clause:

/*
 * This routine adds the real server base identity to the version string,
 * and then locks out changes until the next reconfig.
 */
static void ap_set_version(void)
{
    if (ap_server_tokens == SrvTk_PRODUCT_ONLY) {
        ap_add_version_component(SERVER_PRODUCT);
    }
    else if (ap_server_tokens == SrvTk_MIN) {
        ap_add_version_component(SERVER_BASEVERSION);
    }
    else if (ap_server_tokens == SrvTk_SECURE) {
        ap_add_version_component(SERVER_HIDE);
    }
    else {
        ap_add_version_component(SERVER_BASEVERSION " (" PLATFORM ")");
    }
    /*
     * Lock the server_version string if we're not displaying
     * the full set of tokens
     */
    if (ap_server_tokens != SrvTk_FULL) {
        version_locked++;
    }
}

That's it - now you can make and make install as usual. Before restarting, edit your httpd.conf file and set ServerTokens to Secure by adding the line:

ServerTokens Secure

Now you can restart and test with a fake HTTP HEAD request to port 80 - you should see your custom string (SERVER_HIDE).

As an added precaution, you may want to rename your gcc binary. I also blocked port 2002 on my firewall for good measure.


Hope this is useful for people still waiting for vendor updates ;-)

--
Aj.
Systems Administrator / Developer


Current thread: