-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
package/minidlna: fix CallStranger a.k.a. CVE-2020-12675
No MINIDLNA_IGNORE_CVES entry is added as no CVE has been assigned to minidlna. Indeed, CallStranger vulnerability affect(ed) most of the UPnP stacks (e.g. gupnp, libupnp) Signed-off-by: Fabrice Fontaine <[email protected]> Signed-off-by: Thomas Petazzoni <[email protected]>
- Loading branch information
1 parent
c1c9c18
commit 9ab9118
Showing
1 changed file
with
133 additions
and
0 deletions.
There are no files selected for viewing
133 changes: 133 additions & 0 deletions
133
package/minidlna/0002-upnphttp.c-fix-CallStranger-a.k.a.-CVE-2020-12695.patch
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,133 @@ | ||
From 51bfbee51fd0376b5a66c944134af3e9972d8592 Mon Sep 17 00:00:00 2001 | ||
From: Fabrice Fontaine <[email protected]> | ||
Date: Sun, 6 Sep 2020 11:22:48 +0200 | ||
Subject: [PATCH] upnphttp.c: fix CallStranger a.k.a. CVE-2020-12695 | ||
|
||
Import CheckCallback function from miniupnpd source code: | ||
https://github.com/miniupnp/miniupnp/commit/0d9634658860c3c8c209e466cc0ef7002bad3b0a | ||
|
||
IPv6 code was kept even if minidlna does not support it currently. | ||
|
||
This code is licensed under BSD-3-Clause like minidlna. | ||
|
||
Signed-off-by: Fabrice Fontaine <[email protected]> | ||
[Upstream status: | ||
https://sourceforge.net/p/minidlna/support-requests/71] | ||
--- | ||
upnphttp.c | 92 ++++++++++++++++++++++++++++++++++++++++++++++++------ | ||
1 file changed, 82 insertions(+), 10 deletions(-) | ||
|
||
diff --git a/upnphttp.c b/upnphttp.c | ||
index 974434e..3be793e 100644 | ||
--- a/upnphttp.c | ||
+++ b/upnphttp.c | ||
@@ -742,6 +742,70 @@ check_event(struct upnphttp *h) | ||
return type; | ||
} | ||
|
||
+/** | ||
+ * returns 0 if the callback header value is not valid | ||
+ * 1 if it is valid. | ||
+ */ | ||
+static int | ||
+checkCallbackURL(struct upnphttp * h) | ||
+{ | ||
+ char addrstr[48]; | ||
+ int ipv6; | ||
+ const char * p; | ||
+ int i; | ||
+ | ||
+ if(!h->req_Callback || h->req_CallbackLen < 8) | ||
+ return 0; | ||
+ if(memcmp(h->req_Callback, "http://", 7) != 0) | ||
+ return 0; | ||
+ ipv6 = 0; | ||
+ i = 0; | ||
+ p = h->req_Callback + 7; | ||
+ if(*p == '[') { | ||
+ p++; | ||
+ ipv6 = 1; | ||
+ while(*p != ']' && i < (sizeof(addrstr)-1) | ||
+ && p < (h->req_Callback + h->req_CallbackLen)) | ||
+ addrstr[i++] = *(p++); | ||
+ } else { | ||
+ while(*p != '/' && *p != ':' && i < (sizeof(addrstr)-1) | ||
+ && p < (h->req_Callback + h->req_CallbackLen)) | ||
+ addrstr[i++] = *(p++); | ||
+ } | ||
+ addrstr[i] = '\0'; | ||
+ if(ipv6) { | ||
+ struct in6_addr addr; | ||
+ if(inet_pton(AF_INET6, addrstr, &addr) <= 0) | ||
+ return 0; | ||
+#ifdef ENABLE_IPV6 | ||
+ if(!h->ipv6 | ||
+ || (0!=memcmp(&addr, &(h->clientaddr_v6), sizeof(struct in6_addr)))) | ||
+ return 0; | ||
+#else | ||
+ return 0; | ||
+#endif | ||
+ } else { | ||
+ struct in_addr addr; | ||
+ if(inet_pton(AF_INET, addrstr, &addr) <= 0) | ||
+ return 0; | ||
+#ifdef ENABLE_IPV6 | ||
+ if(h->ipv6) { | ||
+ if(!IN6_IS_ADDR_V4MAPPED(&(h->clientaddr_v6))) | ||
+ return 0; | ||
+ if(0!=memcmp(&addr, ((const char *)&(h->clientaddr_v6) + 12), 4)) | ||
+ return 0; | ||
+ } else { | ||
+ if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr))) | ||
+ return 0; | ||
+ } | ||
+#else | ||
+ if(0!=memcmp(&addr, &(h->clientaddr), sizeof(struct in_addr))) | ||
+ return 0; | ||
+#endif | ||
+ } | ||
+ return 1; | ||
+} | ||
+ | ||
static void | ||
ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) | ||
{ | ||
@@ -759,17 +823,25 @@ ProcessHTTPSubscribe_upnphttp(struct upnphttp * h, const char * path) | ||
* - respond HTTP/x.x 200 OK | ||
* - Send the initial event message */ | ||
/* Server:, SID:; Timeout: Second-(xx|infinite) */ | ||
- sid = upnpevents_addSubscriber(path, h->req_Callback, | ||
- h->req_CallbackLen, h->req_Timeout); | ||
- h->respflags = FLAG_TIMEOUT; | ||
- if (sid) | ||
- { | ||
- DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid); | ||
- h->respflags |= FLAG_SID; | ||
- h->req_SID = sid; | ||
- h->req_SIDLen = strlen(sid); | ||
+ /* Check that the callback URL is on the same IP as | ||
+ * the request, and not on the internet, nor on ourself (DOS attack ?) */ | ||
+ if(checkCallbackURL(h)) { | ||
+ sid = upnpevents_addSubscriber(path, h->req_Callback, | ||
+ h->req_CallbackLen, h->req_Timeout); | ||
+ h->respflags = FLAG_TIMEOUT; | ||
+ if (sid) | ||
+ { | ||
+ DPRINTF(E_DEBUG, L_HTTP, "generated sid=%s\n", sid); | ||
+ h->respflags |= FLAG_SID; | ||
+ h->req_SID = sid; | ||
+ h->req_SIDLen = strlen(sid); | ||
+ } | ||
+ BuildResp_upnphttp(h, 0, 0); | ||
+ } else { | ||
+ DPRINTF(E_WARN, L_HTTP, "Invalid Callback in SUBSCRIBE %.*s", | ||
+ h->req_CallbackLen, h->req_Callback); | ||
+ BuildResp2_upnphttp(h, 412, "Precondition Failed", 0, 0); | ||
} | ||
- BuildResp_upnphttp(h, 0, 0); | ||
} | ||
else if (type == E_RENEW) | ||
{ | ||
-- | ||
2.28.0 | ||
|