Bug 64297 - mod_md uninitialized variable
Summary: mod_md uninitialized variable
Status: NEW
Alias: None
Product: Apache httpd-2
Classification: Unclassified
Component: mod_md (show other bugs)
Version: 2.5-HEAD
Hardware: All All
: P2 critical (vote)
Target Milestone: ---
Assignee: Apache HTTPD Bugs Mailing List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2020-04-01 06:30 UTC by toan.sec
Modified: 2020-04-01 14:45 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description toan.sec 2020-04-01 06:30:54 UTC
Hi,
When auditing httpd I caught this bug,
https://github.com/apache/httpd/blob/trunk/modules/md/md_acme.c#L170
static apr_status_t inspect_problem(md_acme_req_t *req, const md_http_response_t *res)
{
    const char *ctype;
    md_json_t *problem; (1)
    
    ctype = apr_table_get(req->resp_hdrs, "content-type");
    if (ctype && !strcmp(ctype, "application/problem+json")) {
        /* RFC 7807 */
        md_json_read_http(&problem, req->p, res); (2)
        if (problem) { (3)
            const char *ptype, *pdetail;


----
https://github.com/apache/httpd/blob/trunk/modules/md/md_json.c#L1160
apr_status_t md_json_read_http(md_json_t **pjson, apr_pool_t *pool, const md_http_response_t *res)
{
    apr_status_t rv = APR_ENOENT;
    const char *ctype = apr_table_get(res->headers, "content-type");
    if (ctype && res->body (4) && (strstr(ctype, "/json") || strstr(ctype, "+json"))) {
        rv = md_json_readb(pjson, pool, res->body);
    }
    return rv;
Variable problem uninitialized at (1) and pass as a pointer to md_json_read_http at (2), if res->body is null at (4) it will return APR_ENOENT without init pjson( or problem ).
At (3) use [problem] without any check on return value of md_json_read_http so [problem] never get init.


It look like if attacker can control authority server he can exploit this bug.
Comment 1 Stefan Eissing 2020-04-01 14:03:56 UTC
Thanks for your report.

I agree that md_json_read_http() should NULL the pointer if the response is not of a json content type. I will fix the code accordingly.

As for an attack, the function is only called when a "json" content type has been detected. I fail to see how an uninitialized *problem could be accessed. Maybe I am not seeing something?
Comment 2 toan.sec 2020-04-01 14:45:47 UTC
Hi Stefan,
Yeah indeed I think you right, so I dive in md_json_readb and see this

apr_status_t md_json_readd(md_json_t **pjson, apr_pool_t *pool, const char *data, size_t data_len)
{
    json_error_t error;
    json_t *j;
    
    j = json_loadb(data, data_len, 0, &error); (5)
    if (!j) {
        return APR_EINVAL;
    }
    *pjson = json_create(pool, j);
    return APR_SUCCESS;
}

so If we go to the branh:
rv = md_json_readb(pjson, pool, res->body);

it will trigger (5) with data is res->body under attacker control and I guess can make it return 0 and it will keep pjson ( our *problem ) uninit as well.