5585 Total CVEs
26 Years
GitHub
README.md
Rendering markdown...
POC / server-curve.c C
/* 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 <zmq.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <sys/syscall.h>

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);
    }
}