Skip to content
This repository has been archived by the owner on Feb 12, 2019. It is now read-only.
This repository has been archived by the owner on Feb 12, 2019. It is now read-only.

Stringprep calls may reveal random memory #85

Open
@xnyhps

Description

When a bind iq comes in, the following happens:

  1. c2s/c2s.c#L285 grabs the bytes of the chosen resource. If the resource was > 1023 bytes, only the first 1023 bytes are copied.

  2. That calls jid_reset_components, which eventually ends up in jid_prep_pieces.

  3. That calls stringprep_xmpp_resourceprep(resource, 1024). However, the stringprep functions from libidn require the input to be valid UTF8. Nothing has checked whether the resource is still UTF8 after trimming it to 1023 characters.

  4. If the resource ends with just a part of a multi-byte character (so is not valid UTF-8) then stringprep skips over the terminating NULL-byte. This means data past the resource buffer will be also read as if they are part of the resource.

    The libidn documentation claims "This function will not read or write to characters outside that size." about the length of the buffer that needs to be specified, but this is not true, it will continue reading until it finds a terminating NULL-byte. It will only not write outside that size. Therefore it is possible to cause the data after the resource buffer to become part of the result. By including some characters that should be removed according to the XMPP resource stringprep profile, it is possible to make sure random data in the server's memory ends up in the returned resource.

For example:

C: <iq type='set' id='bind'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><resource>\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200D\u200DAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAрф</resource></bind></iq>

\u200D shown here escaped, it is mapped to nothing by the stringprep profile. The string is exactly long enough such that the ф gets cut into two when taking the first 1023 bytes.

S: <iq xmlns='jabber:client' id='bind' type='result'><bind xmlns='urn:ietf:params:xml:ns:xmpp-bind'><jid>test@localhost.localdomain/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAррlocalhost.localdomain</jid></bind></iq>

The data in this case is harmless as it is the domain, but the same trick likely works for the domain and node parts of a JID. Different compilers and different architectures may also lead to different results.

What should happen is making sure the different components are valid UTF-8 before calling any of the stringprep functions.

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions