TDCTF Academy Logo TDCTF ACADEMY

11.1.1 Bash untuk Security

Definisi

Bash (Bourne Again SHell) adalah shell default di hampir semua distribusi Linux dan menjadi senjata utama dalam keamanan siber. Sebagai penetration tester, kemampuan scripting Bash memungkinkan Anda mengotomatiskan hampir semua tugas: dari scanning port, parsing log, hingga backup konfigurasi sistem. Bash adalah jembatan antara command manual dan automation penuh.


1. Dasar Shell

Variables

# Assignment - tanpa spasi
TARGET="192.168.1.1"
PORT=8080
USERNAME="admin"

# Penggunaan
echo "Scanning $TARGET on port $PORT"

# Command substitution
CURRENT_IP=$(hostname -I | awk '{print $1}')
echo "IP saat ini: $CURRENT_IP"

# Variable default
OUTPUT_DIR=${OUTPUT_DIR:-"/tmp/scans"}
echo "Output ke: $OUTPUT_DIR"

Loops

# For loop - range
for port in {1..1024}; do
echo "Testing port $port"
done

# For loop - dari file
for ip in $(cat targets.txt); do
ping -c 1 "$ip" >/dev/null 2>&1 && echo "$ip UP" || echo "$ip DOWN"
done

# While loop - baca file baris per baris
while IFS= read -r line; do
echo "Memproses: $line"
done < targets.txt

# Until loop - tunggu service aktif
until nc -zv "$TARGET" 22; do
echo "Menunggu SSH..."
sleep 2
done

Conditionals

# If-elif-else
if [ "$PORT" -eq 80 ]; then
echo "HTTP service detected"
elif [ "$PORT" -eq 443 ]; then
echo "HTTPS service detected"
else
echo "Port lain: $PORT"
fi

# File test
if [ -f "$OUTPUT_DIR/report.txt" ]; then
echo "Report sudah ada"
fi

# String comparison
if [ "$USERNAME" = "root" ]; then
echo "Privileged user"
fi

# Logical OR/AND
[ -z "$TARGET" ] && echo "Target kosong!" && exit 1
[ ! -d "$OUTPUT_DIR" ] && mkdir -p "$OUTPUT_DIR"

2. Parsing dengan awk, sed, grep, cut

grep - Filter baris

# Cari string dalam log
grep "Failed password" /var/log/auth.log

# Recursive search
grep -r "password" /etc/

# Invert match
grep -v "INFO" app.log

# Only matching
grep -oP "\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}" access.log

# Context lines
grep -B 2 -A 2 "ERROR" syslog

awk - Pemrosesan kolom

# Cetak kolom tertentu
awk '{print \$1, \$7}' access.log

# Filter dengan kondisi
awk '\$9 >= 400 {print \$1, \$7, \$9}' access.log

# Delimiter kustom
awk -F: '{print \$1}' /etc/passwd

# Hitung frekuensi
awk '{count[\$1]++} END {for (ip in count) print ip, count[ip]}' access.log

# Format output
awk '{printf "%-15s %s\\n", \$1, \$7}' access.log

sed - Stream editor

# Replace teks
sed 's/old/new/g' file.txt

# In-place edit
sed -i 's/AllowUsers/AllowUsers pentest/' /etc/ssh/sshd_config

# Delete baris tertentu
sed '/^#/d' config.conf

# Print range baris
sed -n '10,20p' access.log

# Multiple commands
sed -e 's/http:/https:/g' -e 's/old/new/g' config.xml

cut - Kolom sederhana

# Berdasarkan delimiter
cut -d: -f1,3 /etc/passwd

# Berdasarkan karakter
cut -c1-10 access.log

# Range field
cut -d, -f1-3 data.csv

3. Networking Tools

curl - HTTP requests

# GET request
curl -s http://target.com

# Cek header response
curl -I https://target.com

# POST data
curl -X POST -d "user=admin&pass=test" http://target.com/login

# Cookie handling
curl -c cookies.txt -b cookies.txt http://target.com/dashboard

# Proxy
curl -x http://127.0.0.1:8080 http://target.com

# Custom headers
curl -H "Authorization: Bearer token123" http://target.com/api

# Download dengan resume
curl -C - -O http://target.com/file.zip

wget - Download tool

# Download file
wget http://target.com/payload.sh

# Mirror website
wget -r -l 2 http://target.com

# Dengan authentication
wget --user=admin --password=secret http://target.com/private.zip

nc (netcat) - Swiss army knife

# Port scan
nc -zv 192.168.1.1 22 80 443

# Range port
for port in {1..1000}; do nc -zv -w 1 "$TARGET" "$port" 2>&1 | grep succeeded; done

# Banner grabbing
echo "HEAD / HTTP/1.0\\r\\n\\r\\n" | nc -w 3 "$TARGET" 80

# Listen mode (reverse shell)
nc -lvnp 4444

# File transfer - receiver
nc -lvnp 9999 > received_file.zip

# File transfer - sender
nc -w 3 "$TARGET" 9999 < payload.zip

/dev/tcp - Bash built-in TCP

# Test port
echo >/dev/tcp/$TARGET/$PORT && echo "Port $PORT OPEN" || echo "Port $PORT CLOSED"

# HTTP request via /dev/tcp
exec 3<>/dev/tcp/target.com/80
echo -e "GET / HTTP/1.1\\r\\nHost: target.com\\r\\n\\r\\n" >&3
cat <&3
exec 3>&-

4. Argument Parsing

#!/bin/bash

usage() {
echo "Usage: \$0 -t <target> -p <ports> [-o <output>]"
exit 1
}

# Parse arguments
while getopts "t:p:o:h" opt; do
case \$opt in
t) TARGET="\$OPTARG" ;;
p) PORTS="\$OPTARG" ;;
o) OUTPUT="\$OPTARG" ;;
h) usage ;;
*) usage ;;
esac
done

echo "Target: \$TARGET"
echo "Ports: \$PORTS"
echo "Output: \${OUTPUT:-/tmp/scan.txt}"

5. Cron Scheduling

# Edit crontab
crontab -e

# Format: menit jam hari tanggal bulan hari_dalam_minggu command
# Setiap hari jam 2 pagi
0 2 * * * /home/pentest/scripts/backup.sh

# Setiap 30 menit
*/30 * * * * /home/pentest/scripts/healthcheck.sh

# Setiap Senin jam 8 pagi
0 8 * * 1 /home/pentest/scripts/weekly_scan.sh

# List cron
crontab -l

# System-wide cron
sudo crontab -e

6. Contoh Script Lengkap

Port Scanner Sederhana

#!/bin/bash
# simple-port-scanner.sh
# Script: Port scanner cepat dengan Bash

TARGET=\$1
START_PORT=\${2:-1}
END_PORT=\${3:-1024}
TIMEOUT=1

if [ -z "\$TARGET" ]; then
echo "Usage: \$0 <target> [start_port] [end_port]"
exit 1
fi

echo "Scanning \$TARGET from port \$START_PORT to \$END_PORT..."

for port in \$(seq \$START_PORT \$END_PORT); do
(echo >/dev/tcp/\$TARGET/\$port) 2>/dev/null && \
echo "[OPEN] Port \$port" &
done

wait
echo "Scan complete."

Log Parser - Ekstrak IP Attacker

#!/bin/bash
# log-parser.sh
# Ekstrak IP yang melakukan brute force dari auth.log

LOG_FILE="/var/log/auth.log"
THRESHOLD=\${1:-5}
MINUTES=\${2:-60}

echo "Mendeteksi brute force dari \$LOG_FILE..."
echo "Threshold: \$THRESHOLD failed attempts in \$MINUTES minutes"
echo "----------------------------------------"

# Ekstrak IP dengan failed login > threshold
grep "Failed password" "\$LOG_FILE" | \
awk '{print \$(NF-3)}' | \
sort | uniq -c | sort -rn | \
while read count ip; do
if [ "\$count" -gt "\$THRESHOLD" ]; then
echo "[ALERT] \$ip - \$count failed attempts"
# Block IP (uncomment untuk production)
# iptables -A INPUT -s \$ip -j DROP
fi
done

Backup Automation

#!/bin/bash
# auto-backup.sh
# Backup config penting dengan timestamp

BACKUP_DIR="/backups/\$(date +%Y%m%d_%H%M%S)"
CONFIG_FILES="/etc/nginx /etc/ssh /etc/apache2"

# Buat direktori backup
mkdir -p "\$BACKUP_DIR"

# Backup konfigurasi
for dir in \$CONFIG_FILES; do
if [ -d "\$dir" ]; then
tar -czf "\$BACKUP_DIR/\$(basename \$dir).tar.gz" "\$dir"
echo "[OK] Backup \$dir selesai"
else
echo "[WARN] \$dir tidak ditemukan, skipped"
fi
done

# Compress semua
tar -czf "\$BACKUP_DIR/full_backup.tar.gz" "\$BACKUP_DIR"
echo "[DONE] Backup selesai: \$BACKUP_DIR/full_backup.tar.gz"

7. Best Practices

Error Handling

set -e # Exit on error
set -u # Treat unset variables as error
set -o pipefail # Pipe fail = script fail

# Trap error
trap 'echo "Error on line \$LINENO"; exit 1' ERR

Quoting

# SELALU quote variables
# Wrong
[ \$var = "value" ] # Bisa error jika var kosong
# Right
[ "\$var" = "value" ]

# Array expansion
for file in "\$FILES[@]"; do
echo "Processing: \$file"
done

Debug Mode

# Debug mode
bash -x script.sh
# Atau di dalam script
set -x # Enable debug
# ... commands ...
set +x # Disable debug

# Verbose mode
bash -v script.sh

Checklist Best Practices

  1. Gunakan set -euo pipefail di awal setiap script
  2. Quote semua variable - "$VAR" bukan $VAR
  3. Gunakan trap untuk cleanup saat error/exit
  4. Jangan parsing ls - gunakan globbing atau find
  5. Gunakan [[ ]] daripada [ ] untuk lebih banyak fitur
  6. Validasi input sebelum diproses
  7. Beri error message yang jelas di setiap kondisi gagal
  8. Gunakan fungsi untuk kode yang reusable
  9. Jangan hardcode - gunakan variable atau file konfigurasi
  10. Test di VM dulu - jangan langsung di production
PADA HALAMAN INI