[zeromq-dev] ZMTP3.0 authentication protocol bug with ZeroMQ4.0?

Pieter Hintjens ph at imatix.com
Thu Oct 2 23:34:25 CEST 2014


Hi Hugo,

The downgrade attack has been reported and fixed in the 4.x stable
release (so for 4.0.5).

The error handling has been quite heavily modified in libzmq master
(so for 4.1.0).

Would you be able to retest against the two github masters?

-Pieter

On Thu, Oct 2, 2014 at 10:24 PM, Hugo Landau <hlandau at devever.net> wrote:
> I've identified what appear to be two issues; one with how ZeroMQ (v4.0.4)
> implements ZMTP/3.0, and the other with the ZMTP/3.0 specification itself.
>
> When a client attempts to connect to a ZeroMQ server, and the client is
> configured to use NULL authentication but the server is configured to use PLAIN
> authentication, the server will send a READY command and wait for the client to
> send HELLO, even though according to ZMTP/3.0 it should close the connection.
> The specification doesn't specify exactly when the connection should be
> terminated in the event of authentication mismatch but I think it's implied
> that it should be done immediately, and there's no need to postpone closure.
>
> What follows is a protocol dump indicating this issue. Client and server source
> code are at the end of this message.
>
>     SERVER
>     00000000  ff 00 00 00 00 00 00 00  01 7f                   ........ ..
> CLIENT
> 00000000  ff 00 00 00 00 00 00 00  01 7f 03                ........ ...
>     SERVER
>     0000000A  03 00 50 4c 41 49 4e 00  00 00 00 00 00 00 00 00 ..PLAIN. ........
>     0000001A  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ........ ........
>     0000002A  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ........ ........
>     0000003A  00 00 00 00 00 00                                ......
> CLIENT
> 0000000B  00 4e 55 4c 4c 00 00 00  00 00 00 00 00 00 00 00 .NULL... ........
> 0000001B  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ........ ........
> 0000002B  00 00 00 00 00 00 00 00  00 00 00 00 00 00 00 00 ........ ........
> 0000003B  00 00 00 00 00                                   .....
>     SERVER
>     00000040  04 19 05 52 45 41 44 59  0b 53 6f 63 6b 65 74 2d ...READY .Socket-
>     00000050  54 79 70 65 00 00 00 03  52 45 50                Type.... REP
> CLIENT
> 00000040  04 08 05 48 45 4c 4c 4f  00 00                   ...HELLO ..
> (connection closed)
>
> The ZMTP/3.0 specification also seems flawed in how it outlines how
> authentication errors are to be dealt with. It clearly states that
> mechanism-specific authentication errors (i.e., those occurring after mechanism
> negotiation) should result in an ERROR command, which ensures that reconnects
> are not attempted. But mechanism mismatches just result in the connection being
> closed, which is indistinguishable from some lower-level issue (such as a loss
> of network connectivity).
>
> The end result of this is that the client keeps trying to connect perpetually,
> hammering the server even though connection is impossible due to the mechanism
> mismatch. This is what actually happens with ZeroMQ 4.0.4; the client just
> keeps hammering the server at approximately half-second intervals.
>
> It would be better if the ZMTP specification made provision for mechanism
> mismatches to inhibit reconnection just as mechanism-specific errors do.
>
> The ZMTP/3.0 specification also specifies that an increasing reconnection
> interval should be used, but ZMQ_RECONNECT_IVL_MAX is disabled by default.
>
>     /* CLIENT */
>     #include <zmq.h>
>     #include <stdio.h>
>     #include <assert.h>
>
>     int main(int argc, char **argv) {
>       void *ctx  = zmq_ctx_new();
>       void *req = zmq_socket(ctx, ZMQ_REQ);
>       int rc = zmq_connect(req, "tcp://127.0.0.1:1234");
>       assert(rc == 0);
>
>       char buf[64] = {};
>       zmq_send(req, "Request#1", 9, 0);
>       zmq_recv(req, buf, 64, 0);
>       printf("RX: %s\n", buf);
>
>       return 0;
>     }
>
>     /* SERVER */
>     #include <zmq.h>
>     #include <stdio.h>
>     #include <assert.h>
>     #include <czmq.h>
>     #include <stdbool.h>
>
>     int main(int argc, char **argv) {
>       zctx_t *ctx  = zctx_new();
>       assert(ctx);
>
>       zauth_t *auth = zauth_new(ctx);
>       assert(auth);
>       zauth_set_verbose(auth, true);
>
>       void *resp = zsocket_new(ctx, ZMQ_REP);
>       zsocket_set_zap_domain(resp, "a");
>       zsocket_set_plain_server(resp, true);
>       zauth_configure_plain(auth, "*", "passwords.txt");
>
>       int rc = zmq_bind(resp, "tcp://*:1234");
>       assert(rc == 0);
>
>       printf("Ready\n");
>       for (;;) {
>         char buf[64] = {};
>         rc = zmq_recv(resp, buf, 64, 0);
>         if (rc < 0)
>           break;
>         printf("RX: %s\n", buf);
>         zmq_send(resp, "(response)", 10, 0);
>       }
>
>       return 0;
>     }
> _______________________________________________
> zeromq-dev mailing list
> zeromq-dev at lists.zeromq.org
> http://lists.zeromq.org/mailman/listinfo/zeromq-dev



More information about the zeromq-dev mailing list