
Report on nasd DOS attacks from Luigi Auriemma (Sun, 4 Mar 2007)

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


Ok, I have adjusted and updated the proof-of-concept for the NAS
vulnerabilities (the link is the same of the previous mail) and the
following are the details I promised to you:

----------------------------------------------------------
A] accept_att_local buffer overflow through USL connection
----------------------------------------------------------

A stack based buffer-overflow is located in the function which receives
the connection over the USL socket allowing the writing of 255 bytes in
the path buffer of 64.
Note that this socket is not enabled by default.

from server/os/connection.c:

static int
accept_att_local(void)
{
    int newconn;
    int read_in;
    char length;
    char path[64];

    /*
     * first get device-name
     */
    if ((read_in = read(ptsFd, &length, 1)) <= 0) {
        Error("audio server: Can't read slave name length from USL
client connection"); return (-1);
    }

    if ((read_in = read(ptsFd, path, length)) <= 0) {
        Error("audio server: Can't read slave name from USL client
connection"); return (-1);
    }

    path[length] = '\0';
    ...


----------------------------------------------------------
B] server termination through unexistent ID in AddResource
----------------------------------------------------------

An unexistent client ID forces the termination of the server.

from server/dia/resource.c:

Bool
AddResource(AuID id, RESTYPE type, pointer value)
{
    int client;
    register ClientResourceRec *rrec;
    register ResourcePtr res, *head;

    client = CLIENT_ID(id);
    rrec = &clientTable[client];
    if (!rrec->buckets) {
        ErrorF("AddResource(%x, %x, %x), client=%d \n",
               id, type, (unsigned long) value, client);
        FatalError("client not in use\n");
    }
    ...


---------------------------------------------------------------
C] bcopy crash caused by integer overflow in ProcAuWriteElement
---------------------------------------------------------------

An integer overflow in ProcAuWriteElement allows the crash of the NAS
server through a too long max_samples value set by the client during
the connection and the subsequent writing of too much bytes in the
destination buffer.
In my tests wasn't possible to cause worst damages than a crash since
is not possible to control the amount of bytes to write.

from server/dia/audispatch.c:

int
ProcAuWriteElement(ClientPtr client)
{
    ...
    if (stuff->num_bytes > c->dataSize - currentSize)
        AU_ERROR(AuBadValue, stuff->num_bytes);

    if (stuff->num_bytes) {
        s = (AuUint8 *) & stuff[1];
        d = c->write;
        n = aumin(stuff->num_bytes, c->dataEnd - d);
        bcopy(s, d, n);

        /* wrap if necessary */
        if (n != stuff->num_bytes)
            bcopy(s + n, c->data, stuff->num_bytes - n);
            ...


----------------------------------------------------------------------
D] invalid memory pointer through big num_actions in ProcAuSetElements
----------------------------------------------------------------------

In ProcAuSetElements num_actions is used for incrementing the pointer
of the el structure which is located in the stuff buffer (the buffer
containing the data of the client).
If a client sends one or more big num_action values will force the
server to use (through el) the data outside the stuff buffer.

from server/dia/audispatch.c:

#define ADD_VAR
#(n)                                                            \
{                                                               \
    AuUint8 *_t = (AuUint8 *)el;                                \
    varLen +=(n);                                               \
    _t +=                                                       \
    el = (auElement *) _t; \
}

#define COMP_ACTIONS
#(num)                                                      \
{                                                           \
    numActions += (num) ? (num) : numDefaultActions[el->type]; \
    ADD_VAR((num) * sizeof(auElementAction));                  \
}
...

int
ProcAuSetElements(ClientPtr client)
{
fprintf(stderr, "XXX ProcAuSetElements\n");
    REQUEST(auSetElementsReq);
    FlowPtr flow;
    int len, i, varLen, numActions, status;
    auElement *el;

    ...

    el = (auElement *) & stuff[1];
    /* compute length of variable data and do some error checking */
    for (i = varLen = numActions = 0; i < stuff->numElements; i++, el++)
        switch (el->type) {
        case AuElementTypeImportClient:
            COMP_ACTIONS(el->importclient.actions.num_actions);
            ...


------------------------------------------
E] invalid memory pointer in compileInputs
------------------------------------------

Another crash is possible through an invalid memory pointer caused by
the AuCompileFlow function using a too big input value (then passed to
compileInputs as inputNum).

from server/dia/auutil.c:

static int
compileInputs(ClientPtr client, FlowElementPtr elements,
              CompiledFlowOutputPtr output, AuUint32 inputNum,
              AuFixedPoint multiplyConstant, AuFixedPoint addConstant,
              AuUint8 numTracks, AuUint8 * inTracks, AuUint8
firstOutTrack, AuBool recompile, AuUint32 * inputCnt)
{
    auElement *el = elements[inputNum].raw;
    int status = AuSuccess;
    AuBool compiled = elements[inputNum].compiled, compileInput =
AuFalse; AuUint32 nextInput;
    AuUint8 inputTracks[auMaxTracks];

    /* XXX - need to check for loops */

    /* indicate that we've compiled this element */
    elements[inputNum].compiled = AuTrue;
    ...


----------------------------------------------
F] NULL pointer caused by too much connections
----------------------------------------------

A NULL pointer crash can be exploited very easily and without any type
of authentication from both local and remote sockets through many
simultaneous connections (at least 120).

from server/os/io.c:

int
ReadRequestFromClient(client)
ClientPtr client;
{
    OsCommPtr oc = (OsCommPtr) client->osPrivate;
    register ConnectionInputPtr oci = oc->input;
    ...


I wait your reply


BYEZ


--- 
Luigi Auriemma
http://aluigi.org
http://mirror.aluigi.org
