/* server-curve.c — minimal CURVE-enabled REP listener for CVE-2019-13132 lab. * * Built WITHOUT -fsanitize=address and WITHOUT -fstack-protector so the * stack overflow in process_initiate() is exploitable (ROP via ret-addr * overwrite). * * Pinned 32-byte raw NaCl/Curve25519 keypair (LAB ONLY): * public: a0fc5b1b84904141538373ef89e9b126087a722e5a23328a26eacb9a27ca045a * secret: a06aef8b2a3194565fc89f9dcbfe92179667c4af408c690fdc18013a3ad52527 * * Build: * gcc -O0 -g -fno-stack-protector -fno-pie -no-pie \ * -I $LAB_ROOT/src/include -L $LAB_ROOT/src/build/lib \ * server-curve.c -o server-curve -lzmq \ * -Wl,-rpath,$LAB_ROOT/src/build/lib */ #include #include #include #include #include #include #include static const char banner[] __attribute__((used)) = "CVE-2019-13132: RCE achieved via CURVE INITIATE stack overflow\n"; __attribute__((used, noinline)) void lab_trampoline(void) { char buf[512]; int n; int out = syscall(SYS_open, "/tmp/pwned-13132", O_WRONLY | O_CREAT | O_TRUNC, 0644); if (out < 0) goto done; syscall(SYS_write, out, banner, sizeof(banner) - 1); int uid_fd = syscall(SYS_open, "/proc/self/status", O_RDONLY); if (uid_fd >= 0) { while ((n = syscall(SYS_read, uid_fd, buf, sizeof(buf))) > 0) syscall(SYS_write, out, buf, n); syscall(SYS_close, uid_fd); } int hn_fd = syscall(SYS_open, "/etc/hostname", O_RDONLY); if (hn_fd >= 0) { const char hn_label[] = "\nhostname: "; syscall(SYS_write, out, hn_label, sizeof(hn_label) - 1); while ((n = syscall(SYS_read, hn_fd, buf, sizeof(buf))) > 0) syscall(SYS_write, out, buf, n); syscall(SYS_close, hn_fd); } syscall(SYS_close, out); done: syscall(SYS_exit_group, 0); } static const unsigned char SERVER_SECRET[32] = { 0xa0, 0x6a, 0xef, 0x8b, 0x2a, 0x31, 0x94, 0x56, 0x5f, 0xc8, 0x9f, 0x9d, 0xcb, 0xfe, 0x92, 0x17, 0x96, 0x67, 0xc4, 0xaf, 0x40, 0x8c, 0x69, 0x0f, 0xdc, 0x18, 0x01, 0x3a, 0x3a, 0xd5, 0x25, 0x27, }; int main(int argc, char **argv) { const char *bind = (argc > 1) ? argv[1] : "tcp://0.0.0.0:5556"; void *ctx = zmq_ctx_new(); void *s = zmq_socket(ctx, ZMQ_REP); int as_server = 1; if (zmq_setsockopt(s, ZMQ_CURVE_SERVER, &as_server, sizeof(as_server)) != 0) { fprintf(stderr, "ZMQ_CURVE_SERVER: %s\n", zmq_strerror(zmq_errno())); return 1; } if (zmq_setsockopt(s, ZMQ_CURVE_SECRETKEY, SERVER_SECRET, 32) != 0) { fprintf(stderr, "ZMQ_CURVE_SECRETKEY: %s\n", zmq_strerror(zmq_errno())); return 1; } if (zmq_bind(s, bind) != 0) { fprintf(stderr, "bind: %s\n", zmq_strerror(zmq_errno())); return 1; } fprintf(stderr, "[server-curve] pid=%d listening on %s (CURVE, no-ASAN, no-canary)\n", (int) getpid(), bind); fflush(stderr); for (;;) { zmq_msg_t m; zmq_msg_init(&m); int rc = zmq_msg_recv(&m, s, 0); if (rc == -1) { fprintf(stderr, "[server-curve] recv: %s\n", zmq_strerror(zmq_errno())); zmq_msg_close(&m); continue; } fprintf(stderr, "[server-curve] got %zu-byte message\n", zmq_msg_size(&m)); zmq_msg_close(&m); zmq_send(s, "ok", 2, 0); } }