From e79f056cff5a3d923162fa826ece6ac5c7937d0c Mon Sep 17 00:00:00 2001 From: iceboy Date: Thu, 29 Aug 2019 19:36:34 -0700 Subject: [PATCH] backdoor --- sandbox/nodejs/sandbox-wrap.cc | 4 +- sandbox/sandbox.cc | 76 +++++++++++++++++++++++++++++++--- sandbox/sandbox.h | 6 ++- sandbox/util.cc | 46 ++++++++++++++++++++ sandbox/util.h | 2 + 5 files changed, 126 insertions(+), 8 deletions(-) diff --git a/sandbox/nodejs/sandbox-wrap.cc b/sandbox/nodejs/sandbox-wrap.cc index 96d5f9c..4b1c494 100644 --- a/sandbox/nodejs/sandbox-wrap.cc +++ b/sandbox/nodejs/sandbox-wrap.cc @@ -51,7 +51,9 @@ SandboxWrap::SandboxWrap(const Napi::CallbackInfo &info) } void SandboxWrap::execute(const Napi::CallbackInfo &info) { - printf("SandboxWrap::execute()\n"); + // TODO(iceboy): async + ExecuteOptions options; + Sandbox::execute(options); } } // namespace nodejs diff --git a/sandbox/sandbox.cc b/sandbox/sandbox.cc index 0ab95f9..83a9ec7 100644 --- a/sandbox/sandbox.cc +++ b/sandbox/sandbox.cc @@ -2,6 +2,7 @@ #include #include +#include #include #include #include @@ -11,6 +12,8 @@ #include #include "sandbox/util.h" +extern "C" int pivot_root(const char *new_root, const char *put_old); + namespace sandbox { Sandbox::Sandbox(const Options &options) @@ -37,6 +40,12 @@ bool Sandbox::init() { return init_dirs() && init_sockets() && init_guest(); } +void Sandbox::execute(const ExecuteOptions &options) { + // TODO + waitpid(guest_pid_, nullptr, 0); + guest_pid_ = 0; +} + bool Sandbox::init_dirs() { std::string root_dir = options_.temp_dir + "/sandbox.XXXXXX"; if (!mkdtemp(&root_dir[0])) { @@ -68,7 +77,7 @@ bool Sandbox::init_guest() { // on the close semantics, as there can be open sockets from other sandbox // instances. if (pid == 0) { - do_guest(); + guest_entry(); exit(1); return false; } @@ -76,7 +85,7 @@ bool Sandbox::init_guest() { return true; } -void Sandbox::do_guest() { +void Sandbox::guest_entry() { uid_t host_euid = geteuid(); gid_t host_egid = getegid(); if (unshare(CLONE_NEWNS | CLONE_NEWUTS | CLONE_NEWIPC | @@ -117,7 +126,7 @@ void Sandbox::do_guest() { return; } if (pid == 0) { - do_guest_init(); + guest_init(); return; } if (waitpid(pid, nullptr, 0) == -1) { @@ -127,8 +136,65 @@ void Sandbox::do_guest() { exit(0); } -void Sandbox::do_guest_init() { - // TODO +void Sandbox::guest_init() { + // TODO(iceboy): Error handling. + mount("root", root_dir_.c_str(), "tmpfs", MS_NOSUID, nullptr); + chdir(root_dir_.c_str()); + mkdir("proc", 0755); + mount("proc", "proc", "proc", MS_NOSUID, nullptr); + mkdir("dev", 0755); + bind_node("/dev/null", "dev/null"); + bind_node("/dev/urandom", "dev/urandom"); + mkdir("tmp", 0755); + mount("tmp", "tmp", "tmpfs", MS_NOSUID, "size=16m,nr_inodes=4k"); + bind_or_link("/bin", "bin"); + mkdir("etc", 0755); + bind_or_link("/etc/alternatives", "etc/alternatives"); + bind_or_link("/lib", "lib"); + bind_or_link("/lib64", "lib64"); + mkdir("usr", 0755); + bind_or_link("/usr/bin", "usr/bin"); + bind_or_link("/usr/include", "usr/include"); + bind_or_link("/usr/lib", "usr/lib"); + bind_or_link("/usr/lib64", "usr/lib64"); + bind_or_link("/usr/libexec", "usr/libexec"); + bind_or_link("/usr/share", "usr/share"); + mkdir("var", 0755); + mkdir("var/lib", 0755); + bind_or_link("/var/lib/ghc", "var/lib/ghc"); + // TODO(iceboy): bind user directories. + std::ostringstream passwd; + passwd << options_.guest_username << ":x:" << options_.guest_uid << ":" + << options_.guest_gid << ":" << options_.guest_username + << ":/:/bin/bash\n"; + write_file("etc/passwd", passwd.str()); + mkdir("old_root", 0755); + pivot_root(".", "old_root"); + umount2("old_root", MNT_DETACH); + rmdir("old_root"); + mount("/", "/", "", MS_BIND | MS_REMOUNT | MS_RDONLY | MS_NOSUID, nullptr); + // TODO(iceboy): read socket. + guest_backdoor(); +} + +void Sandbox::guest_backdoor() { + pid_t pid = fork(); + if (pid == -1) { + perror("fork"); + return; + } + if (pid == 0) { + fcntl(0, F_SETFD, fcntl(0, F_GETFD) & ~FD_CLOEXEC); + fcntl(1, F_SETFD, fcntl(1, F_GETFD) & ~FD_CLOEXEC); + fcntl(2, F_SETFD, fcntl(2, F_GETFD) & ~FD_CLOEXEC); + execl("/bin/bash", "backdoor", nullptr); + return; + } + if (waitpid(pid, nullptr, 0) == -1) { + perror("waitpid"); + return; + } + // TODO(iceboy): return value. } } // namespace sandbox diff --git a/sandbox/sandbox.h b/sandbox/sandbox.h index f020cbc..415faef 100644 --- a/sandbox/sandbox.h +++ b/sandbox/sandbox.h @@ -14,6 +14,7 @@ class Sandbox { uid_t guest_uid = 1000; gid_t guest_gid = 1000; std::string guest_hostname = "sandbox"; + std::string guest_username = "user"; }; explicit Sandbox(const Options &options); @@ -34,8 +35,9 @@ class Sandbox { bool init_dirs(); bool init_sockets(); bool init_guest(); - void do_guest(); - void do_guest_init(); + void guest_entry(); + void guest_init(); + void guest_backdoor(); Options options_; std::string root_dir_; diff --git a/sandbox/util.cc b/sandbox/util.cc index 016935f..31ef265 100644 --- a/sandbox/util.cc +++ b/sandbox/util.cc @@ -1,6 +1,12 @@ #include "sandbox/util.h" +#include #include +#include +#include +#include +#include +#include namespace sandbox { @@ -11,4 +17,44 @@ bool write_file(const std::string &filename, const std::string &content) { return stream.good(); } +bool bind_node(const std::string &from, const std::string &to) { + if (mknod(to.c_str(), 0600, 0)) { + return false; + } + if (mount(from.c_str(), to.c_str(), "", MS_BIND | MS_NOSUID, nullptr)) { + return false; + } + return true; +} + +bool bind_or_link(const std::string &from, const std::string &to) { + struct stat stat; + if (lstat(from.c_str(), &stat)) { + return false; + } + std::array buffer; + if (S_ISLNK(stat.st_mode)) { + ssize_t ret = readlink(from.c_str(), buffer.data(), buffer.size() - 1); + if (ret < 0) { + return false; + } + buffer[ret] = '\0'; + if (symlink(buffer.data(), to.c_str())) { + return false; + } + } else { + if (mkdir(to.c_str(), 0755)) { + return false; + } + if (mount(from.c_str(), to.c_str(), "", MS_BIND | MS_NOSUID, nullptr)) { + return false; + } + if (mount(from.c_str(), to.c_str(), "", + MS_BIND | MS_REMOUNT | MS_RDONLY | MS_NOSUID, nullptr)) { + return false; + } + } + return true; +} + } // namespace sandbox diff --git a/sandbox/util.h b/sandbox/util.h index d73d9bc..8349afc 100644 --- a/sandbox/util.h +++ b/sandbox/util.h @@ -6,6 +6,8 @@ namespace sandbox { bool write_file(const std::string &filename, const std::string &content); +bool bind_node(const std::string &from, const std::string &to); +bool bind_or_link(const std::string &from, const std::string &to); } // namespace sandbox