xorl %eax, %eax

CVE-2009-1086: NLnet Labs ldns Remote Heap Overflow

with one comment

On 2 February 2009, Stefan Kaltenbrunner reported this vulnerability which affects ldns 1.4 branch. Here I’ll be using ldns 1.4.1 release. The vulnerable function is part of rr.c which contains routines responsible for DNS RR (Resource Records). Here it is:

83 /*
84  * trailing spaces are allowed
85  * leading spaces are not allowed
86  * allow ttl to be optional
87  * class is optional too
88  * if ttl is missing, and default_ttl is 0, use DEF_TTL
89  * allow ttl to be written as 1d3h
90  * So the RR should look like. e.g.
91  * miek.nl. 3600 IN MX 10 elektron.atoom.net
92  * or
93  * miek.nl. 1h IN MX 10 elektron.atoom.net
94  * or
95  * miek.nl. IN MX 10 elektron.atoom.net
96  */
97 static ldns_status
98 ldns_rr_new_frm_str_internal(ldns_rr **newrr, const char *str,
99                              uint32_t default_ttl, ldns_rdf *origin,
100                             ldns_rdf **prev, bool question)
101 {


This function clearly is being used to format/parse an RR DNS record. However, here is what is going on:

108         char  *owner;
109         char  *ttl;
110         ldns_rr_class clas_val;
111         char  *clas;
112         char  *type = NULL;
113         char  *rdata;
     ...
138         owner = LDNS_XMALLOC(char, LDNS_MAX_DOMAINLEN + 1);
139         ttl = LDNS_XMALLOC(char, 21);
140         clas = LDNS_XMALLOC(char, 11);
141         rdata = LDNS_XMALLOC(char, LDNS_MAX_PACKETLEN + 1);
     ...
146         if (!new || !owner || !ttl || !clas || !rdata || !rr_buf || !rd_    146 buf || !rd || !b64 ) {
147                 return LDNS_STATUS_MEM_ERR;
148         }




Before moving on, the macro used at lines 138-141 for dynamic allocation is defined at ldns/util.h.in like this:

39
40 #define LDNS_XMALLOC(type, count)       ((type *) malloc((count) * sizeof(type)))


This means that ttl and clas allocate 21 and 11 bytes respectively. Now, let’s move on with the code of ldns_rr_new_frm_str_internal():

181         ttl_val = (uint32_t) strtol(ttl, NULL, 10);
182
183         if (strlen(ttl) > 0 && !isdigit((int) ttl[0])) {
     ...
204         } else {
205                 if (ldns_bget_token(rr_buf, clas, "\t\n ", LDNS_SYNTAX_DATALEN) == -1) {
     ...
208                         LDNS_FREE(clas);
     ...
215                 }
     ...
255                 return NULL;
256                 */
257         }


At line 205, it invokes ldns_bget_token(). This routine is part of parse.c and its prototype is this:

194 ssize_t
195 ldns_bget_token(ldns_buffer *b, char *token, const char *delim, size_t limit)


This is being used to retrieve the requested token. It iterates through a while loop and parses the characters. However, apart from specific delimiter characters, it uses its last parameter, limit as a boundary. The way its being called at line 205 this limit will be:

19 #define LDNS_SYNTAX_DATALEN 16
20 #define LDNS_TTL_DATALEN    21
21 #define LDNS_RRLIST_INIT    8


So 16, but if we go back to line 140 we’ll notice that we only have 11 bytes on this pointer. Unfortunately, bget_token() writes to this buffer and leads to a nice overflow. The patch was:

-         ttl = LDNS_XMALLOC(char, 21);
-         clas = LDNS_XMALLOC(char, 11);
+         ttl = LDNS_XMALLOC(char, LDNS_TTL_DATALEN);
+         clas = LDNS_XMALLOC(char, LDNS_SYNTAX_DATALEN);

Written by xorl

April 8, 2009 at 22:41

Posted in bugs

One Response

Subscribe to comments with RSS.

  1. the limit parameter in ldns_bget_token() is not used exactly as you think; note the places where a zero is passed for that parameter.

    It’s a bit of fun to check out the xref’s; although theyve been reported and will probably get killed soon :/

    someone

    August 10, 2010 at 22:42


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s