Skip to content
Commits on Source (4)
asterisk (1:13.14.1~dfsg-2+deb9u4) stretch-security; urgency=medium
* AST-2018-004 / CVE-2018-7284: Crash when receiving SUBSCRIBE request
(Closes: #891227)
* AST-2018-005 / CVE-2018-7286: Crash when large numbers of TCP connections
are closed suddenly (Closes: #891228)
* AST-2018-008 / CVE-2018-12227: PJSIP endpoint presence disclosure when using ACL
(Closes: #902954)
* AST-2018-009 / CVE-2018-17281: Remote crash vulnerability in HTTP websocket upgrade
(Closes: #909554)
-- Bernhard Schmidt <berni@debian.org> Sun, 30 Sep 2018 23:24:10 +0200
asterisk (1:13.14.1~dfsg-2+deb9u3) stretch-security; urgency=medium
[ Tzafrir Cohen ]
......
From 9fc59c223cc56c718b99b6cef2cb03dfcaf0a234 Mon Sep 17 00:00:00 2001
From: Richard Mudgett <rmudgett@digium.com>
Date: Mon, 30 Apr 2018 17:38:58 -0500
Subject: [PATCH] AST-2018-008: Fix enumeration of endpoints from ACL rejected addresses.
When endpoint specific ACL rules block a SIP request they respond with a
403 forbidden. However, if an endpoint is not identified then a 401
unauthorized response is sent. This vulnerability just discloses which
requests hit a defined endpoint. The ACL rules cannot be bypassed to gain
access to the disclosed endpoints.
* Made endpoint specific ACL rules now respond with a 401 unauthorized
which is the same as if an endpoint were not identified. The fix is
accomplished by replacing the found endpoint with the artificial endpoint
which always fails authentication.
ASTERISK-27818
Change-Id: Icb275a54ff8e2df6c671a6d9bda37b5d732b3b32
---
diff --git a/res/res_pjsip/pjsip_distributor.c b/res/res_pjsip/pjsip_distributor.c
index e056b60..19266df 100644
--- a/res/res_pjsip/pjsip_distributor.c
+++ b/res/res_pjsip/pjsip_distributor.c
@@ -666,6 +666,26 @@
ao2_unlock(unid);
}
+static int apply_endpoint_acl(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint);
+static int apply_endpoint_contact_acl(pjsip_rx_data *rdata, struct ast_sip_endpoint *endpoint);
+
+static void apply_acls(pjsip_rx_data *rdata)
+{
+ struct ast_sip_endpoint *endpoint;
+
+ /* Is the endpoint allowed with the source or contact address? */
+ endpoint = rdata->endpt_info.mod_data[endpoint_mod.id];
+ if (endpoint != artificial_endpoint
+ && (apply_endpoint_acl(rdata, endpoint)
+ || apply_endpoint_contact_acl(rdata, endpoint))) {
+ ast_debug(1, "Endpoint '%s' not allowed by ACL\n",
+ ast_sorcery_object_get_id(endpoint));
+
+ /* Replace the rdata endpoint with the artificial endpoint. */
+ ao2_replace(rdata->endpt_info.mod_data[endpoint_mod.id], artificial_endpoint);
+ }
+}
+
static pj_bool_t endpoint_lookup(pjsip_rx_data *rdata)
{
struct ast_sip_endpoint *endpoint;
@@ -684,6 +704,7 @@
ao2_unlink(unidentified_requests, unid);
ao2_ref(unid, -1);
}
+ apply_acls(rdata);
return PJ_FALSE;
}
@@ -743,6 +764,8 @@
ast_sip_report_invalid_endpoint(name, rdata);
}
}
+
+ apply_acls(rdata);
return PJ_FALSE;
}
@@ -826,16 +849,11 @@
ast_assert(endpoint != NULL);
- if (endpoint!=artificial_endpoint) {
- if (apply_endpoint_acl(rdata, endpoint) || apply_endpoint_contact_acl(rdata, endpoint)) {
- if (!is_ack) {
- pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 403, NULL, NULL, NULL);
- }
- return PJ_TRUE;
- }
+ if (is_ack) {
+ return PJ_FALSE;
}
- if (!is_ack && ast_sip_requires_authentication(endpoint, rdata)) {
+ if (ast_sip_requires_authentication(endpoint, rdata)) {
pjsip_tx_data *tdata;
struct unidentified_request *unid;
@@ -871,6 +889,10 @@
pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
return PJ_TRUE;
}
+ } else if (endpoint == artificial_endpoint) {
+ /* Uh. Oh. The artificial endpoint couldn't challenge so block the request. */
+ pjsip_endpt_respond_stateless(ast_sip_get_pjsip_endpoint(), rdata, 500, NULL, NULL, NULL);
+ return PJ_TRUE;
}
return PJ_FALSE;
From e6b0c4d27e0392a7b4b4b6717a6d1e0ea049b550 Mon Sep 17 00:00:00 2001
From: Sean Bright <sean.bright@gmail.com>
Date: Thu, 16 Aug 2018 11:45:53 -0400
Subject: [PATCH] AST-2018-009: Fix crash processing websocket HTTP Upgrade
requests
The HTTP request processing in res_http_websocket allocates additional
space on the stack for various headers received during an Upgrade request.
An attacker could send a specially crafted request that causes this code
to overflow the stack, resulting in a crash.
* No longer allocate memory from the stack in a loop to parse the header
values. NOTE: There is a slight API change when using the passed in
strings as is. We now require the passed in strings to no longer have
leading or trailing whitespace. This isn't a problem as the only callers
have already done this before passing the strings to the affected
function.
ASTERISK-28013 #close
Change-Id: Ia564825a8a95e085fd17e658cb777fe1afa8091a
---
res/res_http_websocket.c | 25 ++++++++++++++-----------
1 file changed, 14 insertions(+), 11 deletions(-)
diff --git a/res/res_http_websocket.c b/res/res_http_websocket.c
index 440bf41..0ff876b 100644
--- a/res/res_http_websocket.c
+++ b/res/res_http_websocket.c
@@ -736,7 +736,8 @@ static void websocket_bad_request(struct ast_tcptls_session_instance *ser)
int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instance *ser, const struct ast_http_uri *urih, const char *uri, enum ast_http_method method, struct ast_variable *get_vars, struct ast_variable *headers)
{
struct ast_variable *v;
- char *upgrade = NULL, *key = NULL, *key1 = NULL, *key2 = NULL, *protos = NULL, *requested_protocols = NULL, *protocol = NULL;
+ const char *upgrade = NULL, *key = NULL, *key1 = NULL, *key2 = NULL, *protos = NULL;
+ char *requested_protocols = NULL, *protocol = NULL;
int version = 0, flags = 1;
struct ast_websocket_protocol *protocol_handler = NULL;
struct ast_websocket *session;
@@ -755,16 +756,15 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
/* Get the minimum headers required to satisfy our needs */
for (v = headers; v; v = v->next) {
if (!strcasecmp(v->name, "Upgrade")) {
- upgrade = ast_strip(ast_strdupa(v->value));
+ upgrade = v->value;
} else if (!strcasecmp(v->name, "Sec-WebSocket-Key")) {
- key = ast_strip(ast_strdupa(v->value));
+ key = v->value;
} else if (!strcasecmp(v->name, "Sec-WebSocket-Key1")) {
- key1 = ast_strip(ast_strdupa(v->value));
+ key1 = v->value;
} else if (!strcasecmp(v->name, "Sec-WebSocket-Key2")) {
- key2 = ast_strip(ast_strdupa(v->value));
+ key2 = v->value;
} else if (!strcasecmp(v->name, "Sec-WebSocket-Protocol")) {
- requested_protocols = ast_strip(ast_strdupa(v->value));
- protos = ast_strdupa(requested_protocols);
+ protos = v->value;
} else if (!strcasecmp(v->name, "Sec-WebSocket-Version")) {
if (sscanf(v->value, "%30d", &version) != 1) {
version = 0;
@@ -778,7 +778,7 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
ast_sockaddr_stringify(&ser->remote_address));
ast_http_error(ser, 426, "Upgrade Required", NULL);
return 0;
- } else if (ast_strlen_zero(requested_protocols)) {
+ } else if (ast_strlen_zero(protos)) {
/* If there's only a single protocol registered, and the
* client doesn't specify what protocol it's using, go ahead
* and accept the connection */
@@ -799,9 +799,12 @@ int AST_OPTIONAL_API_NAME(ast_websocket_uri_cb)(struct ast_tcptls_session_instan
return 0;
}
- /* Iterate through the requested protocols trying to find one that we have a handler for */
- while (!protocol_handler && (protocol = strsep(&requested_protocols, ","))) {
- protocol_handler = ao2_find(server->protocols, ast_strip(protocol), OBJ_KEY);
+ if (!protocol_handler && protos) {
+ requested_protocols = ast_strdupa(protos);
+ /* Iterate through the requested protocols trying to find one that we have a handler for */
+ while (!protocol_handler && (protocol = strsep(&requested_protocols, ","))) {
+ protocol_handler = ao2_find(server->protocols, ast_strip(protocol), OBJ_KEY);
+ }
}
/* If no protocol handler exists bump this back to the requester */
--
2.7.4
......@@ -61,3 +61,5 @@ AST-2017-013.patch
AST-2018-004-13.diff
AST-2018-005-13.diff
AST-2018-008-13.18.diff
AST-2018-009-13.diff