[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]

[tor-bugs] #19281 [Core Tor/Tor]: Potential heap corruption via `write_escaped_data` in control.c



#19281: Potential heap corruption via `write_escaped_data` in control.c
------------------------------+-----------------------------------------
     Reporter:  asn           |      Owner:
         Type:  defect        |     Status:  new
     Priority:  Medium        |  Milestone:  Tor: 0.2.???
    Component:  Core Tor/Tor  |    Version:  Tor: unspecified
     Severity:  Normal        |   Keywords:  029-proposed tor-bug-bounty
Actual Points:                |  Parent ID:
       Points:  0.5           |   Reviewer:
      Sponsor:                |
------------------------------+-----------------------------------------
 Here follows another bug report by guido from hackerone.

 We think this is safe to list on trac, because the `write_escaped_data`
 function is only called from the control API, and we believe it's not
 possible to force the control API to write enough amounts of data to
 trigger this bug (since descriptors, dir documents, and cells are all
 capped in size, and this bug requires message lengths close to `INT_MAX`).

 Bug report follows:

 ----

 {{{
 /** Given a <b>len</b>-character string in <b>data</b>, made of lines
  * terminated by CRLF, allocate a new string in *<b>out</b>, and copy the
  * contents of <b>data</b> into *<b>out</b>, adding a period before any
 period
  * that appears at the start of a line, and adding a period-CRLF line at
  * the end. Replace all LF characters sequences with CRLF.  Return the
 number
  * of bytes in *<b>out</b>.
  */
 STATIC size_t
 write_escaped_data(const char *data, size_t len, char **out)
 {
   size_t sz_out = len+8;
   char *outp;
   const char *start = data, *end;
   int i;
   int start_of_line;
   for (i=0; i<(int)len; ++i) {
     if (data[i]== '\n')
       sz_out += 2; /* Maybe add a CR; maybe add a dot. */
   }
   *out = outp = tor_malloc(sz_out+1);
   end = data+len;
   start_of_line = 1;
   while (data < end) {
     if (*data == '\n') {
       if (data > start && data[-1] != '\r')
         *outp++ = '\r';
       start_of_line = 1;
     } else if (*data == '.') {
       if (start_of_line) {
         start_of_line = 0;
         *outp++ = '.';
       }
     } else {
       start_of_line = 0;
     }
     *outp++ = *data++;
   }
   if (outp < *out+2 || fast_memcmp(outp-2, "\r\n", 2)) {
     *outp++ = '\r';
     *outp++ = '\n';
   }
   *outp++ = '.';
   *outp++ = '\r';
   *outp++ = '\n';
   *outp = '\0'; /* NUL-terminate just in case. */
   tor_assert((outp - *out) <= (int)sz_out);
   return outp - *out;
 }
 }}}

 There are two potential vulnerabilities lurking here:

 1. If the input size (`len`) >= 0x80000000, then this loop will not
 execute at all:

 {{{
   for (i=0; i<(int)len; ++i) {
     if (data[i]== '\n')
       sz_out += 2; /* Maybe add a CR; maybe add a dot. */
   }
 }}}

 Because the condition `i<(int)len` is effectively `i<(negative number)`
 and `i` is intialized to 0, this can never be true. As a result of this,
 the output buffer (whose size is based on sz_out)
 is too small to hold the result for an input buffer containing '\n'
 characters.
 Triggering this is typically only feasible on a 64-bit system, because if
 the input buffer is >= 0x80000000 bytes, then sz_out is set to 0x80000008
 bytes, and allocating such an amount twice (one for the
 input buffer, and one for the output buffer) is not possible on a 32-bit
 system.

 2. If the equation (number of '\n' characters in input buffer * 2 + size
 of input buffer) exceeds 0xFFFFFFFF, then this will cause heap corruption
 on a 32-bit system, because sz_out overflows.

--
Ticket URL: <https://trac.torproject.org/projects/tor/ticket/19281>
Tor Bug Tracker & Wiki <https://trac.torproject.org/>
The Tor Project: anonymity online
_______________________________________________
tor-bugs mailing list
tor-bugs@xxxxxxxxxxxxxxxxxxxx
https://lists.torproject.org/cgi-bin/mailman/listinfo/tor-bugs