mod_dav is a module designed to provide DAV capabilities for a web server. A format string vulnerability in some implementations may permit a remote attacker to gain unauthorized access to a web server running mod_dav. Here is a brief primer for those unfamiliar with format string vulnerabilities:
A format string vulnerability occurs when a call to a function in the printf family is made with a format string under the control of an attacker. The most basic case arises when a programmer uses printf as follows:
\tprintf(s);
where s comes from the attacker's input. There are a variety of attacks based on this flaw, many of which can lead to the ability to execute code with the privileges of the vulnerable program. Most of the attacks leverage the %n conversion character, which has the somewhat unusual effect of writing to memory, as opposed to most conversion characters which only read from memory. If the attacker can cause the above printf statement to be issued as follows (by providing %n as input):
\tprintf("%n");
he can write to the stack, and by carefully choosing his input he can control what gets written, and where it goes.
David Litchfield found some problems in Oracle's 9iAS/9.0.2 implementation of mod_dav. Examination of Greg Stein's open source mod_dav (often used by Apache installations) suggested the problem may be broader than just Oracle's implementation. The following code is from the function dav_lookup_uri in the module dav_util:
if (strcasecmp(comp.scheme, scheme) != 0 || comp.port != port) { result.err.status = HTTP_BAD_GATEWAY; result.err.desc = ap_psprintf(r->pool, "Destination URI refers to different " "scheme or port (%s://hostname:%d)\" "(want: %s://hostname:%d)", comp.scheme ? comp.scheme : scheme, comp.port ? comp.port : port, scheme, port);
You can see that in at least one case, result.err.desc gets filled in with values under the control of the caller. Specifically, comp.scheme, comp.port, scheme, and port, can be influenced by an intruder. The result variable is returned to the function dav_method_copymove in the module mod_dav as "lookup":
lookup = dav_lookup_uri(dest, r); if (lookup.rnew == NULL) { 2: if (lookup.err.status == HTTP_BAD_REQUEST) { /* This supplies additional information for the default message. */ ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, 1: lookup.err.desc); return HTTP_BAD_REQUEST; }
You can see that on the line labeled "1:" if lookup.err.desc could be influenced by an intruder, a format string vulnerability would exist. However, that section of code only gets executed if lookup.err.status is HTTP_BAD_REQUEST and the dav_lookup_uri function sets err.status to be HTTP_BAD_GATEWAY, so this code doesn't get executed.
Based on these observations, we concluded that a format string vulnerability does not exist in the open source mod_dav. However, we believe that it would be more "correct" to include an explicit format string specifier in all calls to ap_log_error (and indeed any functions that ultimately use the printf family or other var_args-like functions). We recommended to Greg Stein that this change be made, though we see no immediate security concern -- just a future problem waiting to happen. Oracle is vulnerable because they allow the user to gain control of the format string through a minor change to their implementation of the mod_dav routines. Other vendors may have made similar changes.
Based on our recommendations, Greg Stein made the following change to revision 1.91 of mod_dav.c:
Code a bit more defensively. If dav_lookup_uri() ever placed user input into lookup.err.desc for the HTTP_BAD_REQUEST case, then we could have problems (via a format string attack). This change frees us from *future* worries.
Until you apply a patch from Oracle, you may consider disabling mod_dav functionality on Oracle 9iAS/9.0.2. If you are making use of another implementation of mod_dav, you may wish to make the changes to the source yourself. Here is an example: -\t ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, + ap_log_rerror(APLOG_MARK, APLOG_ERR | APLOG_NOERRNO, r, "%s", |