mirror of https://github.com/dirtbags/moth.git
Add tokencli, add nonce to token protocol
This commit is contained in:
parent
2f3634167b
commit
e730b0766d
|
@ -1,11 +1,15 @@
|
|||
Ideas for puzzles
|
||||
=================
|
||||
* Hide something in a .docx zip file
|
||||
|
||||
|
||||
Network treasure hunt
|
||||
---------------------
|
||||
* DHCP option
|
||||
* Single TCP RST with token in payload
|
||||
* Multiple TCP RST with different payloads
|
||||
*
|
||||
* Bootable image with FreeDOS, Linux, Inferno? HURD?
|
||||
* Bury puzzles in various weird locations within each OS
|
||||
* Maybe put some in the boot loader, too
|
||||
* Perhaps have some sort of network puzzle as well
|
||||
* Network treasure hunt
|
||||
* DHCP option
|
||||
* Single TCP RST with token in payload
|
||||
* Multiple TCP RST with different payloads
|
||||
* PXE boot some sort of points-gathering client
|
||||
* Init asks for a team hash, and starts awarding points
|
||||
* Broken startup scripts, when fixed award more points
|
||||
* Lots of remote exploits
|
||||
|
|
|
@ -1,11 +1,14 @@
|
|||
CFLAGS = -Wall -Werror
|
||||
TARGETS = in.tokend pointscli claim.cgi puzzler.cgi puzzles.cgi
|
||||
TARGETS = in.tokend tokencli claim.cgi
|
||||
TARGETS += puzzler.cgi puzzles.cgi
|
||||
TARGETS += pointscli
|
||||
|
||||
all: build
|
||||
|
||||
build: $(TARGETS)
|
||||
|
||||
in.tokend: in.tokend.o arc4.o common.o
|
||||
tokencli: tokencli.o arc4.o
|
||||
pointscli: pointscli.o common.o
|
||||
|
||||
puzzles.cgi: puzzles.cgi.o common.o
|
||||
|
|
23
src/common.c
23
src/common.c
|
@ -282,6 +282,29 @@ fgrepx(char const *needle, char const *filename)
|
|||
return found;
|
||||
}
|
||||
|
||||
int32_t
|
||||
my_random()
|
||||
{
|
||||
static int urandom = -2;
|
||||
int len;
|
||||
int32_t ret;
|
||||
|
||||
if (-2 == urandom) {
|
||||
urandom = open("/dev/urandom", O_RDONLY);
|
||||
srandom(time(NULL) * getpid());
|
||||
}
|
||||
if (-1 == urandom) {
|
||||
return (int32_t)random();
|
||||
}
|
||||
|
||||
len = read(urandom, &ret, sizeof(ret));
|
||||
if (len != sizeof(ret)) {
|
||||
return (int32_t)random();
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int
|
||||
my_snprintf(char *buf, size_t buflen, char *fmt, ...)
|
||||
{
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
#define __COMMON_H__
|
||||
|
||||
#include <stddef.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#define TEAM_MAX 40
|
||||
#define CAT_MAX 40
|
||||
|
@ -16,6 +17,7 @@ void cgi_error(char *fmt, ...);
|
|||
|
||||
|
||||
int fgrepx(char const *needle, char const *filename);
|
||||
int32_t my_random();
|
||||
int my_snprintf(char *buf, size_t buflen, char *fmt, ...);
|
||||
char *srv_path(char const *fmt, ...);
|
||||
int team_exists(char const *teamhash);
|
||||
|
|
|
@ -9,6 +9,7 @@
|
|||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <ctype.h>
|
||||
#include <sysexits.h>
|
||||
#include "common.h"
|
||||
#include "arc4.h"
|
||||
|
||||
|
@ -76,15 +77,12 @@ main(int argc, char *argv[])
|
|||
uint8_t key[256];
|
||||
size_t keylen;
|
||||
|
||||
/* Seed the random number generator. This ought to be unpredictable
|
||||
enough for a contest. */
|
||||
srand((int)time(NULL) * (int)getpid());
|
||||
|
||||
/* Read service name. */
|
||||
{
|
||||
ssize_t len;
|
||||
|
||||
len = read(0, service, sizeof(service));
|
||||
if (0 >= len) return 0;
|
||||
for (servicelen = 0;
|
||||
(servicelen < len) && isalnum(service[servicelen]);
|
||||
servicelen += 1);
|
||||
|
@ -97,13 +95,13 @@ main(int argc, char *argv[])
|
|||
|
||||
fd = open(srv_path("token.keys/%.*s", servicelen, service), O_RDONLY);
|
||||
if (-1 == fd) {
|
||||
write(1, "!nosvc", 6);
|
||||
perror("Open key");
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = read(fd, &key, sizeof(key));
|
||||
if (-1 == ret) {
|
||||
write(1, "!read", 5);
|
||||
perror("Read key");
|
||||
return 0;
|
||||
}
|
||||
keylen = (size_t)ret;
|
||||
|
@ -111,17 +109,27 @@ main(int argc, char *argv[])
|
|||
close(fd);
|
||||
}
|
||||
|
||||
/* Send a nonce, expect it back encrypted */
|
||||
{
|
||||
int32_t nonce = my_random();
|
||||
int32_t enonce = 0;
|
||||
|
||||
write(1, &nonce, sizeof(nonce));
|
||||
arc4_crypt_buffer(key, keylen, (uint8_t *)&nonce, sizeof(nonce));
|
||||
read(0, &enonce, sizeof(enonce));
|
||||
if (nonce != enonce) {
|
||||
write(1, ":<", 2);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create the token. */
|
||||
{
|
||||
uint8_t crap[itokenlen];
|
||||
int32_t crap = my_random();
|
||||
char digest[bubblebabble_len(itokenlen)];
|
||||
int i;
|
||||
|
||||
/* Digest some random junk. */
|
||||
for (i = 0; i < itokenlen; i += 1) {
|
||||
crap[i] = (uint8_t)random();
|
||||
}
|
||||
bubblebabble(digest, (char *)crap, itokenlen);
|
||||
bubblebabble(digest, (char *)&crap, itokenlen);
|
||||
|
||||
/* Append digest to service name. */
|
||||
tokenlen = (size_t)snprintf(token, sizeof(token),
|
||||
|
|
|
@ -0,0 +1,92 @@
|
|||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sysexits.h>
|
||||
#include <stdio.h>
|
||||
#include "arc4.h"
|
||||
|
||||
/* I don't feel compelled to put all the TCP client code in here
|
||||
* when it's so simple to run this with netcat or ucspi. Plus, using
|
||||
* stdin and stdout makes it simpler to test.
|
||||
*/
|
||||
|
||||
int
|
||||
read_key(char *filename, uint8_t *key, size_t *keylen)
|
||||
{
|
||||
int fd = open(filename, O_RDONLY);
|
||||
int len;
|
||||
|
||||
if (-1 == fd) {
|
||||
perror("open");
|
||||
return EX_NOINPUT;
|
||||
}
|
||||
|
||||
len = read(fd, key, *keylen);
|
||||
if (-1 == len) {
|
||||
perror("read");
|
||||
return EX_NOINPUT;
|
||||
}
|
||||
*keylen = (size_t)len;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int
|
||||
main(int argc, char *argv[]) {
|
||||
uint8_t skey[200];
|
||||
size_t skeylen = sizeof(skey);
|
||||
char token[200];
|
||||
size_t tokenlen;
|
||||
int ret;
|
||||
|
||||
if (argc != 3) {
|
||||
fprintf(stderr, "Usage: %s SERVICE SERVICEKEY 3>TOKENFILE\n", argv[0]);
|
||||
fprintf(stderr, "\n");
|
||||
fprintf(stderr, "SERVICEKEY is a filenames.\n");
|
||||
fprintf(stderr, "Tokens are written to file descriptor 3.\n");
|
||||
return EX_USAGE;
|
||||
}
|
||||
|
||||
/* read in keys */
|
||||
ret = read_key(argv[2], skey, &skeylen);
|
||||
if (0 != ret) return ret;
|
||||
|
||||
/* write service name */
|
||||
write(1, argv[1], strlen(argv[1]));
|
||||
|
||||
/* read nonce, send back encrypted version */
|
||||
{
|
||||
uint8_t nonce[80];
|
||||
int noncelen;
|
||||
|
||||
noncelen = read(0, nonce, sizeof(nonce));
|
||||
if (0 >= noncelen) {
|
||||
perror("read");
|
||||
return EX_IOERR;
|
||||
}
|
||||
arc4_crypt_buffer(skey, skeylen, nonce, (size_t)noncelen);
|
||||
write(1, nonce, (size_t)noncelen);
|
||||
}
|
||||
|
||||
/* read token */
|
||||
{
|
||||
int len;
|
||||
|
||||
len = read(0, token, sizeof(token));
|
||||
if (0 >= len) {
|
||||
perror("read");
|
||||
return EX_IOERR;
|
||||
}
|
||||
tokenlen = (size_t)len;
|
||||
}
|
||||
|
||||
/* decrypt it */
|
||||
arc4_crypt_buffer(skey, skeylen, (uint8_t *)token, tokenlen);
|
||||
|
||||
/* write it to fd 3 */
|
||||
write(3, token, tokenlen);
|
||||
|
||||
return 0;
|
||||
}
|
8
test.sh
8
test.sh
|
@ -88,8 +88,8 @@ fi
|
|||
mkdir -p $CTF_BASE/token.keys
|
||||
echo -n '0123456789abcdef' > $CTF_BASE/token.keys/tokencat
|
||||
|
||||
# in.tokend uses a random number generator
|
||||
echo -n 'tokencat' | src/in.tokend > /dev/null
|
||||
mkfifo $CTF_BASE/nancy
|
||||
src/tokencli tokencat $CTF_BASE/token.keys/tokencat < $CTF_BASE/nancy 3>$CTF_BASE/t | src/in.tokend > $CTF_BASE/nancy
|
||||
|
||||
if ! grep -q 'tokencat:x....-....x' $CTF_BASE/tokens.db; then
|
||||
die "in.tokend didn't write to database"
|
||||
|
@ -103,11 +103,11 @@ if src/claim.cgi t=$hash k=tokencat:xanax-xanax | grep -q success; then
|
|||
die "claim.cgi gave points for a bogus token"
|
||||
fi
|
||||
|
||||
if ! src/claim.cgi t=$hash k=$(cat $CTF_BASE/tokens.db) | grep -q success; then
|
||||
if ! src/claim.cgi t=$hash k=$(cat $CTF_BASE/t) | grep -q success; then
|
||||
die "claim.cgi didn't give me any points"
|
||||
fi
|
||||
|
||||
if src/claim.cgi t=$hash k=$(cat $CTF_BASE/tokens.db) | grep -q success; then
|
||||
if src/claim.cgi t=$hash k=$(cat $CTF_BASE/t) | grep -q success; then
|
||||
die "claim.cgi gave me points twice for the same token"
|
||||
fi
|
||||
|
||||
|
|
Loading…
Reference in New Issue