README.md
Rendering markdown...
/* 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);
}
}