Lucene search

K
securityvulnsSecurityvulnsSECURITYVULNS:DOC:16652
HistoryApr 11, 2007 - 12:00 a.m.

Details about the hlfreeze/hl-headnut/csdos bugs

2007-04-1100:00:00
vulners.com
22

#######################################################################

Title: Details about the hlfreeze/hl-headnut/csdos bugs
Author: Luigi Auriemma
e-mail: [email protected]
web: aluigi.org

#######################################################################

This short text is an idea I have had during the patching of the so
called csdos.pl bug since there were a lot of things unclear.

I will try to be much clear as I can… but I already know I will fail
eh eh eh.

I will refer specifically to csdos (found and released by Firestorm in
the 2006) but the problem is the SAME of hlfreeze/hl-headnut (found by
Delikon in the far 2003) with the following differences:

  • csdos works also versus servers protected by password
  • csdos works also versus recent versions since hlfreeze/hl-headnut
    was fixed "after" version 1.1.1.0
  • they use two different ways for reaching the piece of code which
    enters in endless loop, csdos an additional backslash while
    hlfreeze/hl-headnut the absence of player informations
  • hlfreeze/hl-headnut is older 8-)

The following are the links to the code about I refer:
http://aluigi.org/fakep/hlfill.zip (can test both the attacks)
http://packetstormsecurity.org/0304-exploits/hl-headnut.c
http://downloads.securityfocus.com/vulnerabilities/exploits/csdos.pl

First a small info for understanding the functions about I refer.
The connection string is the data sent by the client to the server and
which starts with the usual "яяяяconnect" header.
Info_ValueForKey is a function used for reading a specific value from a
connection string though its parameter name, example:

\parameter\value\parameter\value\…\parameter\value

Info_SetValueForKey does the "write" operation, if the string already
contains a parameter with the same name it will be deleted and the new
one will be appended to string.
Info_ValueForKey reads, Info_SetValueForKey writes, stop.

The effect of the bug is visible through an endless loop in the
function SV_CheckForDuplicateNames which has the job of looking for
duplicated player names when a new client joins and adds a number in
front to his name if another homonym already exists.
This function should look "similar" (I have not tested it and I can't
know if it's the same) to the following code:

duplicated = 0;
val = (char *)Info_ValueForKey (cl->userinfo, "name");
while (1) {
    for (i=0, client = svs.clients ; i < MAX_CLIENTS; i++, client++) {
        if ( !client->active || !client->spawned || client == cl)
            continue;
        if (!Q_stricmp(client->name, val))
            break;
    }
    if( i < MAX_CLIENTS) {
        p = val;
        if (val[0] == '(') {
            if (val[2] == ')')
                p = val + 3;
            else if (val[3] == ')')
                p = val + 4;
        }
        snprintf(newname, sizeof( newname ), "(%d)%-0.*s", dupc++, 28, p);
        Info_SetValueForKey (cl->userinfo, "name", newname, MAX_INFO_STRING);
        val = (char *)Info_ValueForKey (cl->userinfo, "name");
        duplicated = 1;
    } else {
        break;
    }
}
return duplicated;

As already said here is where we see the effect of the problem but the
bug is located somewhere else.

When a client joins the server this one reads his name with
Info_ValueForKey, if the name is not available in the connection string
(Info_ValueForKey returns "") the client will be kicked with an error
message, while if it's invalid will be replaced by "unnamed".
Then the nick (unnamed or the original one) will be readded to the
string with Info_SetValueForKey.
Now take a look here:

original connection string:
яяяяconnect 47 12345678
"\prot\2\unique\0\raw\00000000000000000000000000000000"
"\name\mynickname\topcolor\0"

after Info_SetValueForKey:
яяяяconnect 47 12345678
"\prot\2\unique\0\raw\00000000000000000000000000000000"
"\topcolor\0\name\mynickname"

OK, now redo the same operation with a backslash char appended to our
(we are the client/attacker) original connection string:

original connection string:
яяяяconnect 47 12345678
"\prot\2\unique\0\raw\00000000000000000000000000000000"
"\name\mynickname\topcolor\0\"

after Info_SetValueForKey:
яяяяconnect 47 12345678
"\prot\2\unique\0\raw\00000000000000000000000000000000"
"\topcolor\0\\name\mynickname"

the additional backslash char is WRONG because it "says" that a new
parameter is beginning but in reality there is nothing and
Info_ValueForKey returns "" if it handles a string with a malformed
format like this one.

So the first check made by the server at the beginning of the
connection has been bypassed since the nickname seems to exist but the
subsequent operations on the string will fail and will lead to the
endless loop which freezes the server.

At least two players with the same "empty" name are needed for
exploiting this bug since the server must enter in the second part of
the SV_CheckForDuplicateNames function.

#######################################################################