Lucene search
K

OpenBSD 6.0 httpd Content-Length DoS Exploit

🗓️ 02 Feb 2017 00:00:00Reported by Pierre KimType 
zdt
 zdt
🔗 0day.today👁 121 Views

OpenBSD httpd Content-Length DoS Exploit Fi

Related
Code
Log message:
Reimplement httpd's support for byte ranges.

The previous implementation loaded all the output into a single output buffer and used its size to determine the Content-Length of the body.

The new implementation calculates the body length first and writes the individual ranges in an async way using the bufferevent mechanism.

This prevents httpd from using too much memory and applies the watermark and throttling mechanisms to range requests.

Problem reported by Pierre Kim (pierre.kim.sec at gmail.com)

Patch:
===================================================================
RCS file: /cvs/src/usr.sbin/httpd/server_http.c,v
retrieving revision 1.111
retrieving revision 1.112
diff -u -r1.111 -r1.112
--- src/usr.sbin/httpd/server_http.c 2017/01/31 12:21:27 1.111
+++ src/usr.sbin/httpd/server_http.c 2017/01/31 14:39:47 1.112
@@ -1,7 +1,7 @@
-/* $OpenBSD: server_http.c,v 1.111 2017/01/31 12:21:27 reyk Exp $ */
+/* $OpenBSD: server_http.c,v 1.112 2017/01/31 14:39:47 reyk Exp $ */

/*
- * Copyright (c) 2006 - 2015 Reyk Floeter <[email protected]>
+ * Copyright (c) 2006 - 2017 Reyk Floeter <[email protected]>
*
* Permission to use, copy, modify, and distribute this software for any
* purpose with or without fee is hereby granted, provided that the above
@@ -604,6 +604,101 @@

done:
server_close(clt, "last http chunk read (done)");
+ return;
+ fail:
+ server_close(clt, strerror(errno));
+}
+
+void
+server_read_httprange(struct bufferevent *bev, void *arg)
+{
+ struct client *clt = arg;
+ struct evbuffer *src = EVBUFFER_INPUT(bev);
+ size_t size;
+ struct media_type *media;
+ struct range_data *r = &clt->clt_ranges;
+ struct range *range;
+
+ getmonotime(&clt->clt_tv_last);
+
+ if (r->range_toread > 0) {
+ size = EVBUFFER_LENGTH(src);
+ if (!size)
+ return;
+
+ /* Read chunk data */
+ if ((off_t)size > r->range_toread) {
+ size = r->range_toread;
+ if (server_bufferevent_write_chunk(clt, src, size)
+ == -1)
+ goto fail;
+ r->range_toread = 0;
+ } else {
+ if (server_bufferevent_write_buffer(clt, src) == -1)
+ goto fail;
+ r->range_toread -= size;
+ }
+ if (r->range_toread < 1)
+ r->range_toread = TOREAD_HTTP_RANGE;
+ DPRINTF("%s: done, size %lu, to read %lld", __func__,
+ size, r->range_toread);
+ }
+
+ switch (r->range_toread) {
+ case TOREAD_HTTP_RANGE:
+ if (r->range_index >= r->range_count) {
+ if (r->range_count > 1) {
+ /* Add end marker */
+ if (server_bufferevent_printf(clt,
+ "\r\n--%llu--\r\n",
+ clt->clt_boundary) == -1)
+ goto fail;
+ }
+ r->range_toread = TOREAD_HTTP_NONE;
+ break;
+ }
+
+ range = &r->range[r->range_index];
+
+ if (r->range_count > 1) {
+ media = r->range_media;
+ if (server_bufferevent_printf(clt,
+ "\r\n--%llu\r\n"
+ "Content-Type: %s/%s\r\n"
+ "Content-Range: bytes %lld-%lld/%zu\r\n\r\n",
+ clt->clt_boundary,
+ media->media_type, media->media_subtype,
+ range->start, range->end, r->range_total) == -1)
+ goto fail;
+ }
+ r->range_toread = range->end - range->start + 1;
+
+ if (lseek(clt->clt_fd, range->start, SEEK_SET) == -1)
+ goto fail;
+
+ /* Throw away bytes that are already in the input buffer */
+ evbuffer_drain(src, EVBUFFER_LENGTH(src));
+
+ /* Increment for the next part */
+ r->range_index++;
+ break;
+ case TOREAD_HTTP_NONE:
+ case 0:
+ break;
+ }
+
+ if (clt->clt_done)
+ goto done;
+
+ if (EVBUFFER_LENGTH(EVBUFFER_OUTPUT(clt->clt_bev)) > (size_t)
+ SERVER_MAX_PREFETCH * clt->clt_sndbufsiz) {
+ bufferevent_disable(clt->clt_srvbev, EV_READ);
+ clt->clt_srvbev_throttled = 1;
+ }
+
+ return;
+ done:
+ (*bev->errorcb)(bev, EVBUFFER_READ, bev->cbarg);
return;
fail:
server_close(clt, strerror(errno));

References:

http://marc.info/?l=openbsd-cvs&m=148587359420912&w=2
http://cvsweb.openbsd.org/cgi-bin/cvsweb/src/usr.sbin/httpd/server_http.c
http://seclists.org/oss-sec/2017/q1/248



#  0day.today [2018-04-09]  #

Data

Build on a solid foundation with Vulners data

We provide the essential building blocks for cybersecurity solutions with comprehensive, structured, and constantly updated vulnerability and exploits data

Api

Power your application with Vulners API

The Vulners REST API offers reliable, high-performance access to vulnerability intelligence, with 99.9% SLA uptime and CDN-backed data delivery for seamless global access

App

Assess and manage vulnerabilities with Vulners tools

Built on top of Vulners' database and SDK, end-user solutions give security professionals and developers lightweight and powerful tools for vulnerability remediation