Ebat Advisory #01 ----------------- NULL Pointer dereference Denial of Service in Thy httpd ---- date: 15/06/04 author: jethro - securirynerds - docisland - ebat ---- Overview: --------- Thy is a lightweight and fast http daemon. A denial of service condition can occur when the daemon is sent a crafted request. A manual restart is needed in order to recover the denial of service. homepage: http://bonehunter.rulez.org/Thy.phtml Vulnerable versions: -------------------- All versions prior to 0.9.2 are vulnerable. Severity: --------- The Dos condition is fairly easy to achieve, but no threat of code execution upon exploitation of this vulnerability has been raised. Recommandation: --------------- Upgrade to thy 0.9.2 or apply this fix: --- src/session.c +++ src/session.c @@ -127,7 +127,7 @@ free (session->request->host); session->request->host = bhc_strdup (&tmp1[7]); free (session->request->url); - session->request->url = NULL; + session->request->url = bhc_strdup ("/"); } } Technical Details: ------------------ The vulnerability is triggered in session.c, through session_update(): (from src/session.c) void session_update (session_t *session) { session->request = (request_t *)bhc_malloc (sizeof (request_t)); session->result = http_request_parse (session->request, session->body.buffer); if (session->request->url) { asprintf (&session->absuri, "http%s://%s%s", (session->ssl) ? "s" : "", session->request->host, session->request->url); _session_parse_absoluteuri (session); urldecode (session->request->url); <--- cgi_setup (session); <--- session->request->file = fabs_urlmap (session->request->url, session->request->host, session->absuri); [...] having a look at _session_parse_absoluteuri, we can spot the problem: (from src/session.c) static void _session_parse_absoluteuri (session_t *session) { char *tmp1, *tmp2; if (!session->request->url) return; if (strncmp ("http://", session->request->url, 7)) return; tmp1 = strstr (session->request->url, "http://"); tmp2 = bhc_strdup (strchr (&tmp1[7], '/')); <---- if (tmp2) { size_t l = strlen (tmp1); tmp1[l - strlen (tmp2)] = 0; free (session->request->host); session->request->host = bhc_strdup (&tmp1[7]); free (session->request->url); session->request->url = tmp2; } else { free (session->request->host); session->request->host = bhc_strdup (&tmp1[7]); free (session->request->url); session->request->url = NULL; } } thy does expect a trailing / when parsing an absolute uri, and if no one is set, tmp2 will feed session->request->url with a NULL value. Later on, in urldecode (from src/misc.c) /** Decode URL in-place. */ void urldecode (char *url) { char *p = url; while (*p) <---- { if (*p == '%') { *url = _misc_hextochar ((int)*(p+1), (int)*(p+2)); p += 2; } else *url = *p; p++; url++; } *url = '\0'; } if url is undefined, then *p won't be either, so while (*p) will cause thy to segv. Disclosure Timeline: -------------------- 14/06 - 18h - found the vuln in the RER (train for the suburbs near paris) while trying some fancy tool I just wrote. 14/06 - 19h - went on #debian so as to find some clues about reporting incidents to the debian project 14/06 - 19h30 - dropped an email to security officer team @ debian .org 12/06 - 19h35 - got an answer by mdz, redirecting me to debian maintainer and upstream author 14/06 - 20h - starting idling on #thy @ oftc.net, waiting for algernon. 15/06 - 00h - finaly cought up with algernon, told him about the vuln, and stuff. 15/06 - 01h - after a few more investigation, writing of this advisory. Thanks to algernon for his quickness. About Ebat: ----------- E-bat is a non profit organisation which aims at helping clueless amongst us feeling less stupid. Thanks to oci@, ski@, tfo@, lbe@, and others. We have no official website to provide you with anything, but who cares. We'll keep the arm in the concrete!