Start trying to get token distribution working

This commit is contained in:
Neale Pickett 2010-09-27 21:03:10 -06:00
parent 5fba528be5
commit e002f16618
24 changed files with 139 additions and 35 deletions

View File

@ -4,12 +4,6 @@
#define swap(a, b) do {int _swap=a; a=b, b=_swap;} while (0) #define swap(a, b) do {int _swap=a; a=b, b=_swap;} while (0)
struct arc4_ctx {
uint8_t S[256];
uint8_t i;
uint8_t j;
};
void void
arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen) arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen)
{ {

View File

@ -4,7 +4,11 @@
#include <stdint.h> #include <stdint.h>
#include <stdlib.h> #include <stdlib.h>
struct arc4_ctx; struct arc4_ctx {
uint8_t S[256];
uint8_t i;
uint8_t j;
};
void arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen); void arc4_init(struct arc4_ctx *ctx, uint8_t const *key, size_t keylen);
uint8_t arc4_pad(struct arc4_ctx *ctx); uint8_t arc4_pad(struct arc4_ctx *ctx);

View File

@ -29,14 +29,36 @@ CPU, or something that carries a high risk of local exploit. The token
server listens on TCP port 1, issuing tokens encrypted with ARC4 server listens on TCP port 1, issuing tokens encrypted with ARC4
(symmetric encryption). Here's how the transaction goes: (symmetric encryption). Here's how the transaction goes:
C: category C: category
S: nonce (4 bytes) S: nonce (4 bytes)
C: nonce encrypted with symmetric key C: nonce encrypted with symmetric key
S: token encrypted with symmetric key S: token encrypted with symmetric key
Token client Token client
------------ ------------
The token client (in package "tokencli") runs as a daemon, requesting a The token client (in package "tokencli") runs as a daemon, requesting a
new token every minute for each puzzle. new token every minute for each puzzle. Because we want you to have
multiple puzzles within a category, and the server only knows about
categories, each puzzle needs to be associated with a category.
Additionally, tokens are encrypted before being written to the local
filesystem, with a different key for each puzzle.
The token client thus needs a 4-tuple for each puzzle:
(puzzle name, puzzle key, category, category key)
In the interest of making things easy to administer and code, this
4-tuple is stored in files and directories:
/opt/packagename/tokencli/puzzle_name/enc.key
/opt/packagename/tokencli/puzzle_name/category.key
/opt/packagename/tokencli/puzzle_name/category
And puzzles are stored in:
/var/lib/ctf/tokens/puzzle_name
Using this scheme, the token client has only to iterate over
/opt/*/tokencli/* instead of implementing some sort of parser.

View File

@ -52,4 +52,4 @@ echo "$color" > $base/teams/colors/$hash
echo "Registered with hash: $hash" echo "Registered with hash: $hash"
# Write teams.html if it's an actual contest # Write teams.html if it's an actual contest
/opt/mcp/bin/teams.sh > $www/teams.html.new && mv $www/teams.html.new $www/teams.html $(dirname $0)/teams.sh > $www/teams.html.new && mv $www/teams.html.new $www/teams.html

View File

@ -93,7 +93,7 @@ main(int argc, char *argv[])
int fd; int fd;
int ret; int ret;
fd = open(state_path("token.keys/%.*s", (int)servicelen, service), O_RDONLY); fd = open(package_path("mcp/tokend.keys/%.*s", (int)servicelen, service), O_RDONLY);
if (-1 == fd) { if (-1 == fd) {
perror("Open key"); perror("Open key");
return 0; return 0;

View File

@ -30,7 +30,7 @@ done
mkdir -p $CTF_BASE/teams/names mkdir -p $CTF_BASE/teams/names
mkdir -p $CTF_BASE/teams/colors mkdir -p $CTF_BASE/teams/colors
for team in team1 team2 team3; do for team in team1 team2 team3; do
hash=$(bin/register $team | awk '{print $NF;}') hash=$(bin/addteam $team | awk '{print $NF;}')
done done
@ -86,11 +86,11 @@ fi
## Token tests ## Token tests
## ##
mkdir -p $CTF_BASE/token.keys mkdir -p $CTF_BASE/mcp/tokend.keys
echo -n '0123456789abcdef' > $CTF_BASE/token.keys/tokencat echo -n '0123456789abcdef' > $CTF_BASE/mcp/tokend.keys/tokencat
mkfifo $CTF_BASE/nancy 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 src/tokencli tokencat $CTF_BASE/mcp/tokend.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 if ! grep -q 'tokencat:x....-....x' $CTF_BASE/tokens.db; then
die "in.tokend didn't write to database" die "in.tokend didn't write to database"

2
mcp/tokend.keys/octopus Normal file
View File

@ -0,0 +1,2 @@
Àñõ®¶'çå6Œ™²¤Y=

1
mcp/tokend.keys/pwnables Normal file
View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD>t322<EFBFBD>/<2F>0<EFBFBD>g<EFBFBD><67>ji

View File

@ -1,6 +1,8 @@
# Octopus / Some kind of octopus / Tearing my shell apart / Letting the # Octopus / Some kind of octopus / Tearing my shell apart / Letting the
# sea get in / You make my insides outside # sea get in / You make my insides outside
build: octopus
octopus: octopus.o token.o octopus: octopus.o token.o
clean: clean:

View File

@ -9,6 +9,8 @@ pwnables-install: pwnables-build
mkdir -p $(PWNABLES_PKGDIR)/bin/ mkdir -p $(PWNABLES_PKGDIR)/bin/
$(MAKE) -C pwnables/src install DESTDIR=$(CURDIR)/$(PWNABLES_PKGDIR) $(MAKE) -C pwnables/src install DESTDIR=$(CURDIR)/$(PWNABLES_PKGDIR)
$(call COPYTREE, pwnables/tokencli, $(PWNABLES_PKGDIR)/tokencli)
$(call COPYTREE, pwnables/service, $(PWNABLES_PKGDIR)/service) $(call COPYTREE, pwnables/service, $(PWNABLES_PKGDIR)/service)
pwnables-clean: pwnables-clean:

View File

@ -15,21 +15,24 @@ if [ ! -x /mnt/pwnables-root/bin/busybox ]; then
# Make some skeleton junk # Make some skeleton junk
install -o root -m 0755 -d /mnt/pwnables-root/var/lib install -o root -m 0755 -d /mnt/pwnables-root/var/lib
install -o root -m 0755 -d /mnt/pwnables-root/var/lib/ctf
install -o root -m 0755 -d /mnt/pwnables-root/var/lib/ctf/tokens
install -o root -m 0755 -d /mnt/pwnables-root/var/log install -o root -m 0755 -d /mnt/pwnables-root/var/log
install -o root -m 0755 -d /mnt/pwnables-root/var/spool install -o root -m 0755 -d /mnt/pwnables-root/var/spool
install -o root -m 0755 -d /mnt/pwnables-root/var/cache install -o root -m 0755 -d /mnt/pwnables-root/var/cache
install -o root -m 0777 -d /mnt/pwnables-root/var/run install -o root -m 0777 -d /mnt/pwnables-root/var/run
install -o root -m 0777 -d /mnt/pwnables-root/var/cache install -o root -m 0777 -d /mnt/pwnables-root/var/cache
# Install the pwnables
install -o root -d /mnt/pwnables-root/home/alice/ install -o root -d /mnt/pwnables-root/home/alice/
install -o root -m 0111 bin/* /mnt/pwnables-root/home/alice/ install -o bob -m 0111 bin/gimmie /mnt/pwnables-root/home/alice/
# ltrace needs to read the binary # ltrace needs to read the binary
chmod +r /mnt/pwnables-root/home/alice/ltraceme install -o bob -m 0555 bin/ltraceme /mnt/pwnables-root/home/alice/
# strace needs to be suid # straceme and killme need to be suid, to prevent LD_PRELOAD
chown bob /mnt/pwnables-root/home/alice/straceme install -o bob -m 04111 bin/straceme /mnt/pwnables-root/home/alice/
chmod 04511 /mnt/pwnables-root/home/alice/straceme install -o bob -m 04111 bin/killme /mnt/pwnables-root/home/alice/
fi fi
cp -r service/* /var/service/ cp -r service/* /var/service/

View File

@ -16,6 +16,7 @@ main(int argc, char *argv[])
key, sizeof(key), key, sizeof(key),
token, sizeof(token) - 1); token, sizeof(token) - 1);
if (-1 == tokenlen) { if (-1 == tokenlen) {
write(1, "Something's broken: I can't read my token.\n", 43);
return 69; return 69;
} }

View File

@ -54,7 +54,7 @@ main(int argc, char *argv[])
* if (fmt[0] == 'T') write(1, buf, len); * if (fmt[0] == 'T') write(1, buf, len);
* } * }
*/ */
printf("Token length %u at %p.\n", tokenlen, token); printf("Token length %u at %p.\n", (unsigned int)tokenlen, token);
return 0; return 0;
} }

View File

@ -0,0 +1 @@
pwnables

View File

@ -0,0 +1 @@
<EFBFBD><EFBFBD>t322<EFBFBD>/<2F>0<EFBFBD>g<EFBFBD><67>ji

View File

@ -0,0 +1 @@
_d).Fvヘe<EFBE8D><65>、ゥOル

View File

@ -1,11 +0,0 @@
#! /bin/sh
exec 2>&1
while true; do
for fn in /opt/*/*.tokenkey; do
cat=$(basename $fn .tokenkey)
echo "XXX: not implemented yet"
done
sleep 60
done

4
tokencli/service/tokengetd/run Executable file
View File

@ -0,0 +1,4 @@
#! /bin/sh
exec 2>&1
exec ./tokengetd

View File

@ -0,0 +1,18 @@
#! /bin/sh
chat=/tmp/tokencli.chatter
token=/tmp/tokencli.token
trap "rm -f $chat $token" 0
mkfifo -m 0500 $chat $token
while true; do
for dn in /opt/*/tokencli/*; do
[ -d $dn ] || continue
puzzle=$(basename $dn)
category=$(cat $dn/category)
nc 10.0.0.1 1 < $fifo | tokencli $category $dn/category.key > $fifo 3> $token
arc4 $dn/enc.key < $token > /var/lib/ctf/tokens/$category
done
sleep 60
done

3
tokencli/setup Executable file
View File

@ -0,0 +1,3 @@
#! /bin/sh
cp -r service/* /var/service

View File

@ -1,3 +1,7 @@
build: tokencli arc4
arc4: arc4.o arc4-main.o
tokencli: tokencli.o arc4.o tokencli: tokencli.o arc4.o
clean: clean:

49
tokencli/src/arc4-main.c Normal file
View File

@ -0,0 +1,49 @@
#include <stdint.h>
#include <stdio.h>
#include <sysexits.h>
#include "arc4.h"
int
main(int argc, char *argv[])
{
struct arc4_ctx ctx;
/* Read key and initialize context */
{
uint8_t key[256];
size_t keylen = 0;
FILE *f;
if (argc == 2) {
if (! (f = fopen(argv[1], "r"))) {
perror(argv[0]);
}
} else {
f = fdopen(3, "r");
}
if (f) {
keylen = fread(key, 1, sizeof(key), f);
fclose(f);
}
if (0 == keylen) {
fprintf(stderr, "Usage: %s [KEYFILE] <PLAINTEXT\n", argv[0]);
fprintf(stderr, "\n");
fprintf(stderr, "You can also pass in the key on fd 3; omit\n");
fprintf(stderr, "KEYFILE in this case.\n");
return EX_IOERR;
}
arc4_init(&ctx, key, (size_t)keylen);
}
/* Encrypt */
while (1) {
int c = getchar();
if (EOF == c) break;
putchar(c ^ arc4_pad(&ctx));
}
return 0;
}

View File

@ -6,7 +6,10 @@ tokencli-install: tokencli-build
$(call COPYTREE, tokencli/service, $(TOKENCLI_PKGDIR)/service) $(call COPYTREE, tokencli/service, $(TOKENCLI_PKGDIR)/service)
cp tokencli/setup $(TOKENCLI_PKGDIR)/
cp tokencli/src/tokencli $(TOKENCLI_PKGDIR)/bin/ cp tokencli/src/tokencli $(TOKENCLI_PKGDIR)/bin/
cp tokencli/src/arc4 $(TOKENCLI_PKGDIR)/bin/
tokencli-clean: tokencli-clean:
rm -rf $(TOKENCLI_PKGDIR) $(TOKENCLI_PACKAGE) rm -rf $(TOKENCLI_PKGDIR) $(TOKENCLI_PACKAGE)