CVE-2016-3178: Out-of-bounds Read (CWE-125)
value: The processRequest function in minissdpd.c in MiniSSDPd 1.2.20130907-3 allows local users to cause a denial of service (out-of-bounds memory access and daemon crash) via vectors involving a negative length value.
CWE description: The product reads data past the end, or before the beginning, of the intended buffer.
CVSS v3 base score: 5.5
Published: 2017-03-24T15:59Z
Repository: https://github.com/miniupnp/miniupnp
Language: C
Files changed: minissdpd/Changelog.txt, minissdpd/minissdpd.c, minissdpd/testminissdpd.c
Commit date: 2016-03-01 19:15:11 +0100
Commit message: minissdpd: Fix broken overflow test (p+l > buf+n) thanks to Salva Piero

Diff: diff --git a/minissdpd/Changelog.txt b/minissdpd/Changelog.txt
index c4d5e39..e66f052 100644
--- a/minissdpd/Changelog.txt
+++ b/minissdpd/Changelog.txt
@@ -1,6 +1,9 @@
-$Id: Changelog.txt,v 1.43 2015/08/06 14:05:49 nanard Exp $
+$Id: Changelog.txt,v 1.45 2016/03/01 18:06:46 nanard Exp $
+
+2016/03/01:
+	Fix broken overflow test (p+l > buf+n) thanks to Salva Piero
 
 VERSION 1.5:
 
 2016/01/13:
 	add "notification" mode (command 5)
diff --git a/minissdpd/minissdpd.c b/minissdpd/minissdpd.c
index 51f8273..df304cd 100644
--- a/minissdpd/minissdpd.c
+++ b/minissdpd/minissdpd.c
@@ -1,6 +1,6 @@
-/* $Id: minissdpd.c,v 1.50 2015/08/06 14:05:49 nanard Exp $ */
+/* $Id: minissdpd.c,v 1.53 2016/03/01 18:06:46 nanard Exp $ */
 /* vim: tabstop=4 shiftwidth=4 noexpandtab
  * MiniUPnP project
  * (c) 2007-2016 Thomas Bernard
  * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
  * This software is subject to the conditions detailed
@@ -845,11 +845,11 @@ void processRequest(struct reqelem * req)
 	}
 	t = time(NULL);
 	type = buf[0];
 	p = buf + 1;
 	DECODELENGTH_CHECKLIMIT(l, p, buf + n);
-	if(p+l > buf+n) {
+	if(l > (unsigned)(buf+n-p)) {
 		syslog(LOG_WARNING, "bad request (length encoding l=%u n=%u)",
 		       l, (unsigned)n);
 		goto error;
 	}
 	if(l == 0 && type != MINISSDPD_SEARCH_ALL
@@ -967,11 +967,11 @@ void processRequest(struct reqelem * req)
 		if(p >= buf + n) {
 			syslog(LOG_WARNING, "bad request (missing usn)");
 			goto error;
 		}
 		DECODELENGTH_CHECKLIMIT(l, p, buf + n);
-		if(p+l > buf+n) {
+		if(l > (unsigned)(buf+n-p)) {
 			syslog(LOG_WARNING, "bad request (length encoding)");
 			goto error;
 		}
 		if(containsForbiddenChars(p, l)) {
 			syslog(LOG_ERR, "bad request (usn contains forbidden chars)");
@@ -985,11 +985,11 @@ void processRequest(struct reqelem * req)
 		}
 		memcpy(newserv->usn, p, l);
 		newserv->usn[l] = '\0';
 		p += l;
 		DECODELENGTH_CHECKLIMIT(l, p, buf + n);
-		if(p+l > buf+n) {
+		if(l > (unsigned)(buf+n-p)) {
 			syslog(LOG_WARNING, "bad request (length encoding)");
 			goto error;
 		}
 		if(containsForbiddenChars(p, l)) {
 			syslog(LOG_ERR, "bad request (server contains forbidden chars)");
@@ -1003,11 +1003,11 @@ void processRequest(struct reqelem * req)
 		}
 		memcpy(newserv->server, p, l);
 		newserv->server[l] = '\0';
 		p += l;
 		DECODELENGTH_CHECKLIMIT(l, p, buf + n);
-		if(p+l > buf+n) {
+		if(l > (unsigned)(buf+n-p)) {
 			syslog(LOG_WARNING, "bad request (length encoding)");
 			goto error;
 		}
 		if(containsForbiddenChars(p, l)) {
 			syslog(LOG_ERR, "bad request (location contains forbidden chars)");
diff --git a/minissdpd/testminissdpd.c b/minissdpd/testminissdpd.c
index a845272..0f9bf0a 100644
--- a/minissdpd/testminissdpd.c
+++ b/minissdpd/testminissdpd.c
@@ -1,6 +1,6 @@
-/* $Id: testminissdpd.c,v 1.12 2015/08/06 13:16:59 nanard Exp $ */
+/* $Id: testminissdpd.c,v 1.14 2016/03/01 17:49:51 nanard Exp $ */
 /* Project : miniupnp
  * website : http://miniupnp.free.fr/ or http://miniupnp.tuxfamily.org/
  * Author : Thomas BERNARD
  * copyright (c) 2005-2016 Thomas Bernard
  * This software is subjet to the conditions detailed in the
@@ -63,10 +63,11 @@ main(int argc, char * * argv)
 	char command3compat[] = "\x03\x00ssdp:all";
 	char command4[] = "\x04\x00test:test:test";
 	const char bad_command[] = { 0xff, 0xff };
 	const char overflow[] = { 0x01, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff };
 	const char command5[] = { 0x05, 0x00 };
+	const char bad_command4[] = { 0x04, 0x01, 0x60, 0x8f, 0xff, 0xff, 0xff, 0x7f};
 	int s;
 	int i;
 	void * tmp;
 	unsigned char * resp = NULL;
 	size_t respsize = 0;
@@ -178,9 +179,18 @@ main(int argc, char * * argv)
 
 	n = SENDCOMMAND(command5, sizeof(command5));
 	n = read(s, buf, sizeof(buf));
 	printf("Response received %d bytes\n", (int)n);
 	printresponse(buf, n);
+	if(n == 0) {
+		close(s);
+		s = connect_unix_socket(sockpath);
+	}
+
+	n = SENDCOMMAND(bad_command4, sizeof(bad_command4));
+	n = read(s, buf, sizeof(buf));
+	printf("Response received %d bytes\n", (int)n);
+	printresponse(buf, n);
 
 	close(s);
 	return 0;
 }

Vulnerable code: $Id: Changelog.txt,v 1.43 2015/08/06 14:05:49 nanard Exp $
/* $Id: minissdpd.c,v 1.50 2015/08/06 14:05:49 nanard Exp $ */
	if(p+l > buf+n) {
		if(p+l > buf+n) {
		if(p+l > buf+n) {
		if(p+l > buf+n) {
/* $Id: testminissdpd.c,v 1.12 2015/08/06 13:16:59 nanard Exp $ */
Fixed code: $Id: Changelog.txt,v 1.45 2016/03/01 18:06:46 nanard Exp $

2016/03/01:
	Fix broken overflow test (p+l > buf+n) thanks to Salva Piero
/* $Id: minissdpd.c,v 1.53 2016/03/01 18:06:46 nanard Exp $ */
	if(l > (unsigned)(buf+n-p)) {
		if(l > (unsigned)(buf+n-p)) {
		if(l > (unsigned)(buf+n-p)) {
		if(l > (unsigned)(buf+n-p)) {
/* $Id: testminissdpd.c,v 1.14 2016/03/01 17:49:51 nanard Exp $ */
	const char bad_command4[] = { 0x04, 0x01, 0x60, 0x8f, 0xff, 0xff, 0xff, 0x7f};
	if(n == 0) {
		close(s);
		s = connect_unix_socket(sockpath);
	}

	n = SENDCOMMAND(bad_command4, sizeof(bad_command4));
	n = read(s, buf, sizeof(buf));
	printf("Response received %d bytes\n", (int)n);
	printresponse(buf, n);