diff --git a/src/im-factory.c b/src/im-factory.c index 8e0d3bbe1..84ad820bc 100644 --- a/src/im-factory.c +++ b/src/im-factory.c @@ -217,6 +217,23 @@ im_factory_message_cb ( gboolean create_if_missing; gboolean sent; + /* CVE-2017-5589+ verification */ + if (wocky_node_get_child_ns (wocky_stanza_get_top_node (message), "received", NS_CARBONS) + || wocky_node_get_child_ns (wocky_stanza_get_top_node (message), "sent", NS_CARBONS)) + { + if ((from = wocky_stanza_get_from (message)) != NULL) + { + TpBaseConnection *conn = TP_BASE_CONNECTION (fac->priv->conn); + TpHandleRepoIface *handles = tp_base_connection_get_handles (conn, + TP_HANDLE_TYPE_CONTACT); + TpHandle from_handle = tp_handle_ensure (handles, from, NULL, NULL); + TpHandle self_handle = tp_base_connection_get_self_handle (conn); + + if (from_handle != self_handle) + return FALSE; + } + } + if (!gabble_message_util_parse_incoming_message (message, &from, &to, &stamp, &msgtype, &id, &body, &state, &send_error, &delivery_status, &delivery_token, &sent)) return TRUE; diff --git a/src/muc-factory.c b/src/muc-factory.c index d53519b18..0a2fddcc9 100644 --- a/src/muc-factory.c +++ b/src/muc-factory.c @@ -782,6 +782,23 @@ muc_factory_message_cb ( TpDeliveryStatus delivery_status; gboolean sent; + /* CVE-2017-5589+ verification */ + if (wocky_node_get_child_ns (wocky_stanza_get_top_node (message), "received", NS_CARBONS) + || wocky_node_get_child_ns (wocky_stanza_get_top_node (message), "sent", NS_CARBONS)) + { + if ((from = wocky_stanza_get_from (message)) != NULL) + { + TpBaseConnection *conn = TP_BASE_CONNECTION (priv->conn); + TpHandleRepoIface *handles = tp_base_connection_get_handles (conn, + TP_HANDLE_TYPE_CONTACT); + TpHandle from_handle = tp_handle_ensure (handles, from, NULL, NULL); + TpHandle self_handle = tp_base_connection_get_self_handle (conn); + + if (from_handle != self_handle) + return FALSE; + } + } + /* FIXME: handle sent? */ if (!gabble_message_util_parse_incoming_message (message, &from, &to, &stamp, &msgtype, &id, &body, &state, &send_error, &delivery_status, &delivery_token, &sent)) diff --git a/tests/twisted/text/test-carbons.py b/tests/twisted/text/test-carbons.py index 7c4f8257d..c844db784 100644 --- a/tests/twisted/text/test-carbons.py +++ b/tests/twisted/text/test-carbons.py @@ -5,7 +5,7 @@ from gabbletest import XmppXmlStream, exec_test, elem, acknowledge_iq from servicetest import (EventPattern, wrap_channel, assertEquals, assertLength, - assertContains) + assertContains, TimeoutError) import constants as cs NS_CARBONS = 'urn:xmpp:carbons:2' @@ -172,6 +172,57 @@ def test(q, bus, conn, stream): assert body['content-type'] == 'text/plain', body assert body['content'] == u'goodbye', body + # Verify source protection + msg = elem('message', type='chat', from_='smith@matrix.org/agent712')( + elem(NS_CARBONS, 'received')( + elem(NS_FORWARD, 'forwarded')( + elem('jabber:client','message', id=id, from_='foo@bar.com/Pidgin', type='chat')( + elem('body')('Mr. Anderson!') + ) + ) + ) + ) + stream.send(msg) + # This is a nasty test but we need to make sure spoofed message is ignored + try: + q.timeout = 2 + message_received = q.expect('dbus-signal', signal='MessageReceived') + assert not message_received, message_received.args + except TimeoutError as e: + pass + + # And MUC - demo attack vector + msg = elem('message')( + elem(NS_CARBONS, 'received')( + elem(NS_FORWARD, 'forwarded')( + elem('jabber:client','message', id=sent_token, from_='foo@bar.com/Pidgin', to='test@localhost')( + elem('body')('oh btb') + ) + ) + ), + elem('jabber:x:conference', 'x', jid='room@localhost') + ) + stream.send(msg) + event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info', to='room@localhost') + + # MUC Invite Attack execution + msg = elem('message', from_='smith@matrix.org/agent712')( + elem(NS_CARBONS, 'received')( + elem(NS_FORWARD, 'forwarded')( + elem('jabber:client','message', id=sent_token, from_='foo@bar.com/Pidgin', to='test@localhost')( + elem('body')('Nice party here, really') + ) + ) + ), + elem('jabber:x:conference', 'x', jid='crimescene@set.up') + ) + stream.send(msg) + try: + event = q.expect('stream-iq', iq_type='get', query_ns='http://jabber.org/protocol/disco#info') + assert not event, event.stanza + except TimeoutError as e: + pass + if __name__ == '__main__': exec_test(test, protocol=CarbonStream, params={'message-carbons':True})