[zeromq-dev] Message source identification/authentication
Eric Hill
eric at ijack.net
Sun May 12 05:59:01 CEST 2013
> But what prevents one peer from
> impersonating another? Absolutely nothing, because by the time the
> message gets to the application layer the authentication information
> has been lost.
The thing that prevents one peer from impersonating another is each peer
should have a unique secret shared only with the server. Any other client
that attempts to send a message with a bogus client id will fail because it
cannot authenticate the message (HMAC, etc) because it doesn't have the
key. Client C sends message M to server S with key K using MC+HMAC(MC, K)
-> S. This means the client sends the message M and client identity C
along with the HMAC of the message M and client C using key K to the server
S. Ok so far?
Now, replay attacks are another problem. Client C sends message M to
server S, and jerk J sees the message on the line. If J re-sends M to S, S
cannot tell that the message didn't originate from C. I think this is the
problem you're trying to explain.
So what is one way to solve it? Time.
When client C sends a message, we add time T to the message: MCT+HMAC(MCT,
K) -> S
Once the server receives the message, it verifies the HMAC of MCT to
authenticate the message, then verifies the time T is within +/-whatever
seconds of "now". If a time stamp on a message deviates more than however
many seconds/minutes/whatever from the server time, we assume the message
is a replay and discard it.
Another method is an integer sequence I. For every message M the client
sends, it increments the counter. I++, then MCI+HMAC(MCI, K) -> S
The server maintains a dictionary D of counters by client C. We'll call
this D[C] = I
When the server S receives a message M from the client C, it can check D[C]
<= I to see if the last seen counter is less than or equal to the received
messages' I. If so, discard the message as a replay. If not, save D[C] =
I for the next time we receive a message from the client.
An advantage to using time is that you don't have to hold a dictionary on
the server. However if a replay could happen in sub-millisecond time, you
may not be able to reliably use that method.
Hope this helps.
On Sat, May 11, 2013 at 2:14 PM, Randall Nortman <rnzmq at wonderclown.net>wrote:
> I know this has been discussed before on this list and there are some
> RFC's related to secure authentication, but I have not yet seen any
> reasonable solutions, because of a limitation in the libzmq API. The
> encryption/authentication built into ZMTPv3.0 doesn't seem to fix the
> problem, because the problem is at the API level. Let me start by
> illustrating the problem with a simple example:
>
> Let's say we have a server which maintains some data for
> clients/peers. Let's call the data "files" for this example, but it
> could be anything. The files are owned by particular clients (which
> are peers with respect to the protocol, but clients with respect to
> the file service). Clients are somehow known to the server
> (previously shared keys), and they can store and retrieve their own
> files, but should not be able to access the files of other clients.
>
> Let's say you do something smart like put the whole thing on a VPN
> using client certificates to authenticate clients and assign them a
> static IP on the VPN. The VPN makes sure that the private IP
> addresses cannot be spoofed. So if I were writing a server based on
> traditional sockets rather than ZMQ, I'd just trust that if I get a
> packet from 10.0.0.96, then that is definitely from the client
> assigned that address and no additional authentication is required.
> You could also do it with SSL using client certificates, and then my
> SSL-based server would just query the SSL library for the identity of
> the client connected to the socket and everything would be great.
>
> Now let's say you've got ZMQ running on top of the same kind of VPN or
> SSL setup. Or you're using the CurveCP/CurveZMQ underlying transport
> or the SASL mechanism in the ZMTPv3.0 spec. Great, you at least know
> that anybody that connects to you is a known peer. But when you get a
> message, you don't know what peer sent it, because zmq_recv has no way
> of communicating that to you. So your protocol of course will need to
> have the client ID in each message. But what prevents one peer from
> impersonating another? Absolutely nothing, because by the time the
> message gets to the application layer the authentication information
> has been lost.
>
> So now you *have* to put authentication on top of ZMQ, at the
> application level, and sign each message. So now each ZMQ application
> needs to implement crypto, and it is way, way too easy to get that
> wrong to have it happening at the application layer. (The
> pubsub-security draft at http://www.zeromq.org/topics:pubsub-security
> nicely illustrates how easy it is to get this stuff terribly, horribly
> wrong, because nothing in that protocol stops replay attacks, as has
> already been pointed out in the comments.)
>
> Furthermore, it seems like unnecessary overhead, given that the
> underlying layers may already have authenticated the peer (if auth at
> the ZMTP layer is being used, for example, or CurveCP/TLS/VPN
> underneath that).
>
> Could the API simply provide a way to identify the sender of each
> message somehow? The "identity" could be handled as a blob whose
> interpretation is dependent on the underlying transport, anything from
> an IP address up to the CN from the peer's X509 certificate. This
> does not do a whole lot to help in the case of multi-hop
> (routed/proxied) messages, but it at least gives you single-hop
> authentication, which is good enough for a large number of
> applications. And it could perhaps serve as the basis for end-to-end
> multi-hop authentication as well. If end-to-end auth is going to be
> done by signing each message (a reasonable way to do it), then that
> *must* be part of the ZMQ spec and the libzmq implementation, because
> you simply cannot leave it up to each application to design and
> implement crypto properly.
>
> Am I missing something? Has this been handled somehow already?
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.zeromq.org/pipermail/zeromq-dev/attachments/20130511/298264e9/attachment.htm>
More information about the zeromq-dev
mailing list