diff --git a/ctf.css b/ctf.css index 22d08d4..b9aa22b 100644 --- a/ctf.css +++ b/ctf.css @@ -64,6 +64,10 @@ th, td { vertical-align: top; } +.scoreboard { + background: #222; +} + .scoreboard td { height: 400px; } diff --git a/kevin/Makefile b/kevin/Makefile index bd3b0ef..1368a11 100644 --- a/kevin/Makefile +++ b/kevin/Makefile @@ -10,7 +10,7 @@ kevin.tce: target target: kevin.py run log.run $(INSTALL) -D kevin.py target/usr/bin/kevin.py - $(INSTALL) --owner=100 -d target/var/lib/ctf/kevin/tokens + $(INSTALL) --owner=100 -d target/var/lib/kevin/tokens $(INSTALL) -d target/var/service/kevin $(INSTALL) run target/var/service/kevin/run diff --git a/kevin/run b/kevin/run index 16e3a92..f66c966 100755 --- a/kevin/run +++ b/kevin/run @@ -2,4 +2,4 @@ [ -f /var/lib/ctf/disabled/kevin ] && exit 0 -exec envuidgid ctf /usr/bin/kevin.py --victims=/var/lib/ctf/kevin/victims.txt --tokens=/var/lib/ctf/kevin/tokens +exec envuidgid ctf /usr/bin/kevin.py --victims=/var/lib/kevin/victims.txt --tokens=/var/lib/kevin/tokens diff --git a/pwnables/Makefile b/pwnables/Makefile new file mode 100644 index 0000000..661ed8f --- /dev/null +++ b/pwnables/Makefile @@ -0,0 +1,28 @@ +CGI = cat.cgi + +TARGET = $(CURDIR)/target + +FAKE = fakeroot -s $(CURDIR)/fake -i $(CURDIR)/fake +INSTALL = $(FAKE) install + +all: target + +target: + $(INSTALL) -d $(TARGET) + $(MAKE) -C daemons TARGET=$(TARGET) install + + $(INSTALL) -D init/networking $(TARGET)/var/service/networking/run + $(INSTALL) -D init/telnetd $(TARGET)/var/service/networking/run + $(INSTALL) -D init/tftpd $(TARGET)/var/service/networking/run + $(INSTALL) -d $(TARGET)/usr/lib/www + + $(INSTALL) $(CGI) $(TARGET)/usr/lib/www + + $(INSTALL) -D flag $(TARGET)/var/lib/tftp/flag + $(INSTALL) -D flag $(TARGET)/var/lib/notes/flag + $(INSTALL) -D flag $(TARGET)/var/lib//flag + $(INSTALL) -D flag $(TARGET)/var/lib/tftp/flag + + +clean: + rm -rf target diff --git a/pwnables/cat.cgi b/pwnables/cat.cgi new file mode 100755 index 0000000..de8c66f --- /dev/null +++ b/pwnables/cat.cgi @@ -0,0 +1,6 @@ +#! /bin/sh + +echo 'Content-type: text/plain' +echo +cat .$PATH_INFO + diff --git a/pwnables/daemons/Makefile b/pwnables/daemons/Makefile new file mode 100644 index 0000000..c0f972f --- /dev/null +++ b/pwnables/daemons/Makefile @@ -0,0 +1,21 @@ +SBIN = in.fingerd in.noted +BIN = notecli + +TARGET ?= $(CURDIR)/target +FAKE = fakeroot -s $(CURDIR)/fake -i $(CURDIR)/fake +INSTALL = $(FAKE) install + +all: $(SBIN) $(BIN) + +install: all + $(INSTALL) -d $(TARGET)/usr/sbin + $(INSTALL) -s $(SBIN) $(TARGET)/usr/sbin + + $(INSTALL) -d $(TARGET)/usr/bin + $(INSTALL) -s $(BIN) $(TARGET)/usr/bin + + $(INSTALL) -d $(TARGET)/var/service/fingerd + $(INSTALL) run.fingerd $(TARGET)/var/service/fingerd/run + + $(INSTALL) -d $(TARGET)/var/service/noted + $(INSTALL) run.noted $(TARGET)/var/service/noted/run diff --git a/pwnables/daemons/in.fingerd.c b/pwnables/daemons/in.fingerd.c new file mode 100644 index 0000000..c51cc13 --- /dev/null +++ b/pwnables/daemons/in.fingerd.c @@ -0,0 +1,44 @@ +#include +#include + +int +main(int argc, char *argv) +{ + char user[256]; + char path[512]; + char *data; + FILE *f; + size_t count; + int i; + char *peer = getenv("REMOTEADDR"); + + openlog("in.fingerd", LOG_PID, LOG_USER); + if (NULL == gets(user)) { + return 0; + } + for (data = user; *data; data += 1) { + if ('\r' == *data) { + *data = 0; + } + } + if (peer) { + syslog(LOG_INFO, "%s requests %s", peer, user); + } + if (0 == user[0]) { + printf("Nobody's home.\n"); + return 0; + } + + sprintf(path, "/home/%s/.plan", user); + f = fopen(path, "r"); + if (NULL == f) { + printf("No such user.\n"); + return 0; + } + + data = path; + while (count = fread(data, sizeof(*data), 1, f)) { + fwrite(data, count, 1, stdout); + } + return 0; +} diff --git a/pwnables/daemons/in.noted.c b/pwnables/daemons/in.noted.c new file mode 100644 index 0000000..33b611f --- /dev/null +++ b/pwnables/daemons/in.noted.c @@ -0,0 +1,55 @@ +#include +#include + +void +readntrim(char *s) +{ + gets(s); + for (; *s; s++) { + switch (*s) { + case '\n': + case '\r': + *s = 0; + } + } +} + +int +main(int argc, char *argv) +{ + int cmd; + char line[4096]; + char note[512]; + FILE *f = NULL; + char *peer = getenv("REMOTEADDR"); + + openlog("in.noted", LOG_PID, LOG_USER); + switch (getc(stdin)) { + case EOF: + return 0; + case 'r': + readntrim(note); + if (peer) { + syslog(LOG_INFO, "%s read %s", peer, note); + } + f = fopen(note, "r"); + while (fgets(line, sizeof(line), f)) { + fputs(line, stdout); + } + fclose(f); + break; + case 'w': + readntrim(note); + if (peer) { + syslog(LOG_INFO, "%s write %s", peer, note); + } + f = fopen(note, "w"); + while (gets(line)) { + fputs(line, f); + } + fclose(f); + break; + } + + return 0; +} diff --git a/pwnables/daemons/notecli.c b/pwnables/daemons/notecli.c new file mode 100644 index 0000000..752f3c0 --- /dev/null +++ b/pwnables/daemons/notecli.c @@ -0,0 +1,90 @@ +#include +#include +#include +#include +#include +#include + +int +open_connection(char *host, int port) +{ + struct sockaddr_in addr; + struct hostent *h; + int fd; + + if (! inet_aton(host, &(addr.sin_addr))) { + if (!(h = gethostbyname(host))) { + return -1; + } else { + memcpy(&(addr.sin_addr), h->h_addr, h->h_length); + } + } + fd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP); + if (fd == -1) { + return -1; + } + addr.sin_family = AF_INET; + addr.sin_port = htons(port); + if (connect(fd, (struct sockaddr *)&addr, sizeof(addr))) { + close(fd); + return -1; + } + + return fd; +} + +void +clean(char *s) +{ + for (; *s; s++) { + switch (*s) { + case '/': + case '.': + *s = '_'; + } + } +} + +int +main(int argc, char *argv[]) +{ + int fd; + char s[4096]; + ssize_t len; + + if (4 != argc) { + printf("Usage: %s HOST NOTE COMMAND\n", argv[0]); + printf("\n"); + printf(" COMMAND must be 'r' (read) or 'w' (write).\n"); + printf(" For w, input is taken from stdin.\n"); + return 1; + } + + fd = open_connection(argv[1], 4000); + clean(argv[2]); + switch (argv[3][0]) { + case 'r': + write(fd, "r", 1); + write(fd, argv[2], strlen(argv[2])); + write(fd, "\n", 1); + do { + len = read(fd, s, sizeof(s)); + write(1, s, len); + } while (len); + break; + case 'w': + write(fd, "w", 1); + write(fd, argv[2], strlen(argv[2])); + write(fd, "\n", 1); + do { + len = read(0, s, sizeof(s)); + write(fd, s, len); + } while (len); + break; + default: + printf("I don't understand that command.\n"); + break; + } + + return 0; +} diff --git a/pwnables/daemons/run.fingerd b/pwnables/daemons/run.fingerd new file mode 100755 index 0000000..4088271 --- /dev/null +++ b/pwnables/daemons/run.fingerd @@ -0,0 +1,3 @@ +#! /bin/sh + +exec tcpsvd 0 79 /usr/sbin/in.fingerd diff --git a/pwnables/daemons/run.noted b/pwnables/daemons/run.noted new file mode 100755 index 0000000..5dcb91f --- /dev/null +++ b/pwnables/daemons/run.noted @@ -0,0 +1,4 @@ +#! /bin/sh + +cd /var/lib/notes +exec tcpsvd 0 4000 /usr/sbin/in.noted diff --git a/pwnables/init/networking b/pwnables/init/networking new file mode 100755 index 0000000..5946c70 --- /dev/null +++ b/pwnables/init/networking @@ -0,0 +1,14 @@ +#! /bin/sh -e + +# busybox's dc doesn't support i :< +# Its awk does support 0xa0 as an int, but gawk doesn't. This only works on busybox. +lastd=awk -F ':' '{for (i=1; i