Skip to content

Commit

Permalink
backdoor
Browse files Browse the repository at this point in the history
  • Loading branch information
iceboy233 committed Aug 30, 2019
1 parent dedf9a8 commit e79f056
Show file tree
Hide file tree
Showing 5 changed files with 126 additions and 8 deletions.
4 changes: 3 additions & 1 deletion sandbox/nodejs/sandbox-wrap.cc
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
76 changes: 71 additions & 5 deletions sandbox/sandbox.cc
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

#include <iostream>
#include <sstream>
#include <fcntl.h>
#include <sched.h>
#include <stdio.h>
#include <sys/mount.h>
Expand All @@ -11,6 +12,8 @@
#include <sys/wait.h>
#include "sandbox/util.h"

extern "C" int pivot_root(const char *new_root, const char *put_old);

namespace sandbox {

Sandbox::Sandbox(const Options &options)
Expand All @@ -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])) {
Expand Down Expand Up @@ -68,15 +77,15 @@ 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;
}
guest_pid_ = pid;
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 |
Expand Down Expand Up @@ -117,7 +126,7 @@ void Sandbox::do_guest() {
return;
}
if (pid == 0) {
do_guest_init();
guest_init();
return;
}
if (waitpid(pid, nullptr, 0) == -1) {
Expand All @@ -127,8 +136,65 @@ void Sandbox::do_guest() {
exit(0);
}

void Sandbox::do_guest_init() {
// TODO
void Sandbox::guest_init() {

This comment has been minimized.

Copy link
@undefined-moe

undefined-moe Aug 30, 2019

Member

Why not use "chroot"?

This comment has been minimized.

Copy link
@iceboy233

iceboy233 Aug 30, 2019

Author Member

chroot alone is not enough, because it leaves the old root mounted in our mount namespace, which makes it possible to escape the chroot eg. with another call to chroot or pivot_root.

source: sio2project/sio2jail#12 (comment)

note that this sandbox supports guest with root user, by setting guest_uid and guest_gid to 0.

This comment has been minimized.

Copy link
@undefined-moe

undefined-moe Aug 30, 2019

Member

I don't think it'll be good to run programs as root.
Maybe creating a limited user will be better.
By the way, will "proot" be able to use in sandbox?

This comment has been minimized.

Copy link
@iceboy233

iceboy233 Aug 30, 2019

Author Member

the default value of guest_uid and guest_gid is 1000. the guest is not running as root with this setting.

// 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
6 changes: 4 additions & 2 deletions sandbox/sandbox.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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_;
Expand Down
46 changes: 46 additions & 0 deletions sandbox/util.cc
Original file line number Diff line number Diff line change
@@ -1,6 +1,12 @@
#include "sandbox/util.h"

#include <array>
#include <fstream>
#include <fcntl.h>
#include <sys/mount.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>

namespace sandbox {

Expand All @@ -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<char, 4096> 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
2 changes: 2 additions & 0 deletions sandbox/util.h
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit e79f056

Please sign in to comment.