Bug 66037 - Latent write beyond bounds in h2_util_header_print() [zhbug_httpd_104]
Summary: Latent write beyond bounds in h2_util_header_print() [zhbug_httpd_104]
Status: RESOLVED FIXED
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_http2 (show other bugs)
Version: 2.5-HEAD
Hardware: All All
: P2 normal (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2022-04-27 17:33 UTC by generalbugs
Modified: 2022-04-28 10:58 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description generalbugs 2022-04-27 17:33:06 UTC
There is a write-beyond-bounds bug in h2_util_header_print() (modules/http2/h2_util.c) in httpd 2.4.53+. [1]

The bug appears to be latent in httpd 2.4.53 because nothing seems to call h2_util_header_print().

The bug is caused by using the condition |offset < maxlen; ... ++offset| in various |for| loops when indexing a buffer, then following the loops with |buffer[offset] ='\0';| . Thus sufficiently-long data causes |offset| to become == |maxlen| after a |for| loop, causing the |'\0'| to be written beyond bounds and the out-of-bounds value of |offset| to be returned to the caller:

   79: size_t h2_util_header_print(char *buffer, size_t maxlen,
   80:                             const char *name, size_t namelen,
   81:                             const char *value, size_t valuelen)
   82: {
   83:     size_t offset = 0;
   84:     size_t i;
   85:     for (i = 0; i < namelen && offset < maxlen; ++i, ++offset) {
   86:         buffer[offset] = name[i];
   87:     }
   88:     for (i = 0; i < 2 && offset < maxlen; ++i, ++offset) {
   89:         buffer[offset] = ": "[i];
   90:     }
   91:     for (i = 0; i < valuelen && offset < maxlen; ++i, ++offset) {
   92:         buffer[offset] = value[i];
   93:     }
   94:     buffer[offset] = '\0';
   95:     return offset;
   96: }

You can demonstrate the bug by copying the function into a scratch file, then calling in thusly:

   char buf[20];
   const char name[]="0123456789";
   const char val[]="0123456789";

   size_t s = h2_util_header_print(buf, sizeof(buf), name, strlen(name), val, strlen(val));

and stepping h2_util_header_print() in a debugger, watching |buf| for the overwrite.

Note also that the function can create a malformed |buffer| if, e.g., |namelen >= maxlen| (|buffer| will contain only |name| followed by '\0').

[1] The security team has asked me to file "hardening" (latent) bugs publicly.
Comment 1 Stefan Eissing 2022-04-28 10:58:09 UTC
Fixed in r1900356 in trunk, proposed backport to 2.4.x.

Thanks for finding this!