I’m intending to apply a patch adding DNSSEC support to Smack, a XMPP client library, in the near feature. And since DNSSEC support in application protocol libraries is still uncommon, I thought it might be a good idea to share the principles how the API was designed.
DNSSEC authenticates DNS answers, positive and negative ones. This means that if a DNS response secured by DNSSEC turns out to be authentic, then you can be sure that the domain either exists, and that the returned resource records (RRs) are the ones the domain owner authorized, or that the domain does not exists and that nobody tried to fake its non existence.
The tricky part is that an application using DNSSEC can not determine whether a domain uses DNSSEC, does not use DNSSEC or if someone downgraded your DNS query using DNSSEC to a response without DNSSEC.
I like to keep APIs I design as simple as possible to use for the
user. Thus Smack’s DNSSEC API simply extends the already existing
ConnectionConfiguration
used to – you guessed it – configure XMPP
connections by a single method:
.setDnssecMode(DnssecMode dnssecMode); ConnectionConfiguration
where DnssecMode
is an enum defined as follows:
enum DnssecMode {
,
disabled,
needsDnssec,
needsDnssecAndDane}
The user simply calls config.setDnssecMode(DnssecMode.needsDnssec)
and Smack will only connect to an XMPP service if all involved DNS
resource recordes could be verified using DNSSEC.
You may noticed the ...AndDane
variant of the enum. If this mode is
used, then Smack will not only require DNSSEC, but also require
DANE (RFC 6598) in order to
verify the service’s TLS certificate.
The issue with the DnssecMode
API exposed by Smack is that an
application should never have to ask the end-user if it’s XMPP account
is secured by DNSSEC. There should be no questionare, checkbox or
whatever about this feature. The best UI regarding a option is if
there is none, i.e., if it just works out of the box.
So what should applications do? The answer is simple and similar to
“HTTP Strict Transport Security” (HSTS, RFC 6797)
used for HTTP(S) connections. Instead of asking the user if DNSSEC is
available, they should check for DNSSEC support on every connection
attempt. Once DNSSEC support has been discovered, the application uses
the needsDnssec
mode for all future connection attempts.
Of course this scheme is not without drawbacks. First, it is possible that an attacker downgrades the DNS responses to non-DNSSEC. Depending on where the attacker sits in the path between the user and its service, this may always be possible for the attacker or only if the user’s device uses a certain network. The downgrade attack also becomes impossible with this scheme after the application was at least once able to connect to the service using DNSSEC.
Furthermore, if the user’s service needs to drop DNSSEC support for whatever reason (technical, political, …), then the user possible gets a message that the connection failed because something named “DNSSEC” was not avaialble. As with most security concepts, it is hard for the average user to asses situation and take the approbiate action. Of course, the application could ask the user to contact the service provider and ask if DNSSEC was indeed disabled before continuing the connection attempt.
But ideally, service providers would never drop DNSSEC support and the application would simply start a new connection attempt after a failed one caused by the lack of DNSSEC. This is similar to how most applications would (or should) treat a STARTTLS downgrade attack: Simply retry until the demanded security gurantees are fullfiled. Then the user doesn’t have to deal with technical error messages.
Note that the exact same scheme can be used with the
needsDnssecAndDane
mode. Once DNSSEC and a TLSA RR has been
discovered for the service and was successfully used to verify the TLS
connection, the application should always use the needsDnssecAndDane
mode.
The attentive reader may wonder why I did not implement the described mechanism in Smack, instead of having the application deal with it. I’d really love to do so, but Smack has no API and mechanism for saving a connection state to persistent storage. This would be required for the described scheme. Such a mechanism planned to come with Smack 4.3 though.
]]>The recent issue (2016-14 page 78 ff.) of the German computer magazine c’t has an interesting article about security issues in alarm systems. I was a bit surprised that in 2016 we still have systems online which are vulnerable because of a default password or passwords like ‘1234’. The c’t had articles about similar issues before. Obviously the industry has much to learn about securing the Internet of Things (IoT).
What caught my attention was an XMPP message that is, according to the article, used by the alarm system to confirm the user PIN with a central server in order to disarm the system. The article describes a security flaw where sending the same message without the PIN would erroneously disarm the system. The message stanza looks like this
message
< id="n0000-000000"
to="<unique-id-of-alarm-system-central>@climax-home-portal"
type="chat"
from="security_ admin@climax-home-portal/Smack">
body> 4150795OqiESNX2RCHC/ :;MODA:1,0, 1234 </body>
<message> </
This demonstrates nicely a few XMPP-for-IoT Anti-Patterns I’d like to discuss.
Using XMPP without properly secured TLS. What made it easy to have a direct look at the used XMPP stanzas, was that the alarm system used an unencrypted connection. This revealed the PIN position and made it possible to inject spoofed stanzas.
Abusing <body/>
to carry machine data.
RFC 6121 § 5.2.3
defines the <body/>
content as “human-readable XML character
data”. I guess this contributed a bit to the security flaw, where a
message stanza without the PIN would disarm the system, because
parsing that particular body content format doesn’t seem easy.
But even if my guess is wrong, abusing the <body/>
element in
such a way will eventually snap back to you once your IoT
environment grows.
Allowing the client to determine the resource. Depending on the services policy on resource conflicts, this could lead to reconnect loops until the old connection using the same resource finally timeouts. Hardcoded resource strings also make it easy for an attacker to guess a resource. If the client does not protect itself against unsolicited stanzas send, e.g. by using XEP-0016 Privacy Lists, then this could at least allow an attacker to drain a mobile clients battery or allow him to access unprotected IQ interfaces.
Using ‘chat’ type messages. Often done because “we don’t know better”. OK, I’m just guessing that ‘chat’ was used because of this reason. But I see it often that people just use ‘chat’ for no obvious reason, ‘normal’ would be the better choice in this case. And since it is the default type, you can omit it, saving a few bytes over the wire.
SSLContext sc = Java7Pinning
.forPin("SHA256:e3b1812d945da1a2a2c5fa28029d2fe34c7c...");
= XMPPTCPConnectionConfiguration
XMPPTCPConnectionConfiguration conf .builder()
.setUsernameAndPassword("user", "pass")
.setXmppDomain("example.org")
.setCustomSSLContext(sc)
.build();
<disarm xmlns='namespace:of:vendor'/>
extension element:message
< id="n0000-000000"
to="<unique-id-of-alarm-system-central>@climax-home-portal"
from="security_ admin@climax-home-portal/ba7971ca-a887-404b-8c48">
disarm xmlns='namespace:of:vendor'>
<data>4150795OqiESNX2RCHC/</data>
<mode foo='true' bare='false'>MODA</mode>
<pin>1234</pin>
<disarm>
</message> </
Let the server assign a resource. You usually want to do this independently of your use-case for XMPP (e.g. also when using XMPP for Instant Messaging). Since this is not IoT specific, but true for general XMPP usage, the XMPP Wiki also mentions this as guideline for IM developers also providing a rationale.
Use a fitting message type. XMPP provides a variety of message types, each with different semantics. Sadly those types are named after their common use-case and not after their semantic, so people assume that they are just useful for that. For example ‘chat’ for chatting purposes and ‘headline’ for headlines. But in the end, you should choose the message type depending on your use-case. Primarily the message type affects the routing rules of the message stanzas. There is no reason you would want to use ‘chat’ in IoT. Use ‘normal’ and omit the ‘type’ attribute completely, since ‘normal’ is the default. Messages of type ‘headline’ also provide some nice properties for the IoT use-case (fan-out to all available resources of the recipient).
Note that this list of patterns is not comprehensive. Also some points are not exclusive to XMPP-for-IoT, but apply to XMPP usage in general.
I really encourage vendors to discuss their ideas, designs and approaches build upon XMPP with the XMPP community. I have encountered a lot of IoT specifications and implementations using XMPP which had, not only minor, but also serious design flaws. Fixing the ones which are already in production is an enormous effort. Thus I can only strongly recommend to get a peer review for your design early.
The XMPP community is very friendly, especially when it comes to supporting open standards and potentially subsequent open-source implementations. Usually you will find people willing to help you design and review your XMPP usage. Just join the xsf@muc.xmpp.org chat or post your XMPP related questions to the standards@mail.jabber.org mailing list.
]]>Rene just tagged MiniDNS 0.2.0-alpha3 and pushed it to Maven Central. This release includes experimental support for DNSSEC.
MiniDNS is an open-source and highly portable DNS resolver written in Java for Android and Java SE runtimes. MiniDNS aims to be lightweight and modular, which makes it different from similar projects like dnsjava.
It is triple licensed. Users can choose the license terms they like from: Apache License 2.0, LGPL 2.1 and WTFPL.
The fastest way to get familiar with MiniDNS is by playing around with its built-in Read-Evaluate-Print-Loop (REPL). Pleaes note that proper support for CNAME / DNAME is not yet implemented.
The new DNSSEC (DNS Security Extensions) support was added through a Google Summer of Code (GSOC) project in 2015 under the umbrella of the XMPP Standards Foundation (XSF). We would like to thank our skilled student Marvin and Google for making this possible.
DNSSEC has multiple benefits, it not only allows the verification of DNS responses (data origin authentication), but also helps making protocols like HTTP, SMTP, IMAP and XMPP more secure by using DANE.
Multiple open source projects already expressed interested in MiniDNS’s DNSSEC feature: Also Smack, the XMPP client library for Android and Java SE I maintain, will provide experimental support for DANE using MiniDNS soon. Daniel, the author of the popular Android XMPP client Conversations, already a MiniDNS user, also expressed interest in adding support for DANE. And last but not least, Vincent and Dominik of OpenKeychain fame are looking forward to adding support for the OPENPGPKEY record as defined in draft-ietf-dane-openpgpkey.
Other projects are of course welcome as well. But please contact me before using the DNSSEC features of MiniDNS: Again, this is highly experimental code. I will keep you updated about the current state of MiniDNS in this very blog.
The MiniDNS code has not yet received an extensive security review. As an understaffed open source project without any funding, we don’t have the necessary resources to pay for such a review.
But even if we had the funds, we first need to find someone capable of actually performing such a review. Maybe you know someone or how to help?
Feel free to contact me if you want to help.
With DNSSEC support in the ‘master’ branch, the only killer feature missing is support for the Kitchen Sink Resource Record (KS RR). The KS RR allows “to put complex, bulky, and/or obscurely structured data into the Domain Name System (DNS)”. Combined with DNSSEC this allows signing arbitrary data of any size, allowing for a broad range of possible use cases. Unlike most other pending features in open source projects, we are able to give an exact date when this feature will arrive: 2017-04-01. Stay tuned.
]]>