Skip to main content

Black hat bash

Из одноименной книги "BLACK HAT BASH Creative Scripting for Hackers and Pentesters by Dolev Farhi and Nick Aleks"

Portswigger Academy CTF багбаунти
OWASP TOP 10


Тестовые контейнеры

cd ~/Black-Hat-Bash/lab/ 
sudo make deploy
deploy Собрать образы и запустить контейнеры
teardown Остановить контейнеры
rebuild clean up + deploy
cleanup Остановить и удалить контейнеры и образы
status Текущий статус
init Первая инициализация окружения и инструментов

Адреса и домены

Список адресов.

#!/bin/bash

for ip in $(seq 1 254); do
  echo "172.16.10.${ip}" >> 172-16-10-hosts.txt
done
echo 10.1.0.{1..254} | sed 's/ /\n/g'

Список доменов.

Есть списки часто используемых поддоменов. Называются gists. В Kali они есть по /usr/share/wordlists/amass/bitquark_subdomains_top100K.txt Или можно в google "subdomain wordlist site:gist.github.com".

#!/bin/bash

DOMAIN=$1
FILE=$2

while read -r subdomain; do
  echo "${subdomain}.${DOMAIN}"
done < "${FILE}" > ${DOMAIN}.txt

Поиск хостов.

Доступность IP хостов по ping 

#!/bin/bash

FILE=$1
while read -r host; do
  if ping -c 1 -W 1 -w 1 "${host}" &> /dev/null; then
    echo "${host} is up."
  fi
done < "${FILE}"

Через nmap, работает гораздо быстрее.

nmap -sn 172.16.10.0/24 | grep "Nmap scan" | awk -F'report for ' '{print $2}'

 ARP сканирование 

sudo arp-scan -f 172-16-10-hosts.txt -I br_public | grep '^[0-9]\+\.[0-9]*' | awk '{print $1}'

Поиск новых адресов в локальной сети

#!/bin/bash

KNOWN_HOSTS='172-16-10-scanning-hosts.txt'
NETWORK='172.16.10.0/24'
INTERFACE='br_public'

while true; do
  echo "Сканируем сеть ${NETWORK}..."
  sudo arp-scan -x -I ${INTERFACE} ${NETWORK} | while read -r line; do
    host=$(echo "${line}" | awk '{print $1}')
    if ! grep -q "${host}" "${KNOWN_HOSTS}"; then
      echo "Found new host: ${host}!"
      echo "${host}" >> "${KNOWN_HOSTS}"
      source senderscripts/tgsender.sh "Найден хост ${host}!"
    fi
  done
  sleep 10
done

Сканирование портов

Nmap

nmap ip/dns ip/dns

По умолчанию:

  • отправка SYN пакета на порт
  • Первые 1000 портов
  • Только TCP соединения
Параметр Значение
-iL file список хостов из файла
-sV версия сервиса на порту
-oG -

Информация в формате удобном для парсинга

Host: 172.16.10.10 () Ports: 8081/open/tcp//blackice-icecap/// Ignored-state: closed (999)

Несколько портов:

Host: 172.16.10.11 ()   Ports: 21/open/tcp//ftp///, 80/open/tcp//http///  Ignored State: closed (998)

--open выводить только открытые порты
--exclude исключения из списка

Пример вывода: 

Nmap scan report for 172.16.10.13
Host is up (0.000031s latency).
Not shown: 999 closed tcp ports (reset)
PORT   STATE SERVICE VERSION
22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.13 (Ubuntu Linux; protocol 2.0)
MAC Address: FA:85:E8:7D:68:EE (Unknown)
Service Info: OS: Linux; CPE: cpe:/o:linux:linux_kernel

RustScan

Работает гораздо быстрее nmap, однако выводит только открытые порты без определения сервиса.

Параметр Значение
-a ip/mask Адрес или адрес сети
-g Только информация по сканированию
-r start-end

Диапазон портов

-r 1-1024

$ rustscan -g -a 172.16.10.0/24 -r 1-1024 | awk -F'->' '{print $1,$2}' | tr -d '[]'

Netcat

Чаще используют для проверки одного порта. 

nc -zv 172.16.10.11 1-1024

(UNKNOWN) [172.16.10.11] 80 (http) open
(UNKNOWN) [172.16.10.11] 21 (ftp) open

-z только вывод результатов, 

Организация хранения результатов сканирования

Можно сохранять данные для каждого IP в отдельном файле или в зависимости от версии программ. 

Пример для каждого открытого порта свой файл со списком адресов.

#!/bin/bash

HOSTS="172-16-10-scanning-hosts.txt"
nmap -iL ${HOSTS} --open -oG - | grep Ports: | while read -r line; do
  curip=$(echo $line | awk {'print $2'})
  echo $line | grep -oP '( \d+)(?=/)' | while read -r curport; do
    echo $curip >>  port-${curport}.txt
  done
done

Определение сервиса на порту

Анализ баннера

У нас есть открытые порты. Но необходимо узнать, что за сервис крутится на нем. Часто сервисы публикуют т н баннер - информацию о себе. Есть сервисы, хранящие данные о сайтах, типа https://shodan.io https://zoomeye.org которые хранят базу данных. Это называется пассивным сканированием. 

Естественно администраторы могут изменять баннер.

Netcat может предоставить данную информацию. 

nc 172.16.10.11 -v 21
172.16.10.11: inverse host lookup failed: Unknown host
(UNKNOWN) [172.16.10.11] 21 (ftp) open
220 (vsFTPd 3.0.5)

nc 1.1.1.1 -v 22 
some.address.ru [1.1.1.1] 22 (ssh) open
SSH-2.0-OpenSSH_9.6p1 Ubuntu-3ubuntu13.13

Ключи nc:

Флаг Значение Пример
-l Слушать (listen) — запускает nc в режиме сервера (ожидание входящих подключений) nc -l -p 4444
-p <порт> Указать порт (для прослушивания или исходного подключения) nc -l -p 4444
-v Подробный режим (verbose), показывает процесс соединения nc -vz 8.8.8.8 53
-vv Очень подробный (ещё больше информации) nc -zvv 8.8.8.8 53
-z Сканирование портов (zero-I/O mode: проверка доступности портов без передачи данных) nc -zv 192.168.0.1 20-80
-u Использовать UDP вместо TCP nc -u 192.168.0.10 123
-n Не использовать DNS (работать только с IP, не пытаться резолвить имена) nc -vz -n 192.168.0.1 80
-w <сек> Таймаут соединения nc -vz -w 3 8.8.8.8 53
-q <сек> Закрыть соединение после EOF через указанное время `echo hi
-k Продолжать слушать после разрыва соединения (серверный режим) nc -lk -p 4444
-e <программа> Запуск программы после подключения (опасный флаг!, часто отключён в безопасных сборках nc) nc -l -p 4444 -e /bin/bash

Сбор информации о баннере: 

#!/bin/bash

FILE="$1"
PORT="$2"

while read -r ip; do
  res=$(echo -e "\n" | nc -v "${ip}" -w 1 "${PORT}" 2> /dev/null)
  if [[ -n "${res}" ]]; then
    echo "Service: ${ip}:${PORT}"
    echo "Banner: ${res}"
  fi
done < "${FILE}"

Анализ http ответа сервера

При помощи curl с помощью метода head можно получить информацию об http сервере. 

curl --head 172.16.10.10:8081                                                                                          

HTTP/1.1 200 OK
Server: Werkzeug/3.0.1 Python/3.12.3
Date: Sat, 30 Aug 2025 08:41:02 GMT
Content-Type: text/html; charset=utf-8
Content-Length: 7176
Connection: close

Приложение whatweb предоставляет расширенную информацию об http сервере. Синтаксис:

whatweb 172.16.10.10:8081
http://172.16.10.10:8081 [200 OK] Country[RESERVED][ZZ], HTML5, 
HTTPServer[Werkzeug/3.0.1 Python/3.12.3], IP[172.16.10.10], 
Python[3.12.3], Title[Menu], Werkzeug[3.0.1], X-UA-Compatible[ie=edge]

whatweb 172.16.10.10:8081 --log-json=/dev/stdout --quiet | jq
# в формате JSON

Т е скомбинировав данные, полученные после сканирования, можно определить некоторые стартовые позиции.

Получение информации об операционной системе

Способ формирования TCP ответа несколько отличаются для разных ОС. Можно определить примерный тип ОС и иногда версию ядра.

Опция -O позволяет проанализировать данную информацию. 

sudo nmap -O -iL 172-16-10-scanning-hosts.txt 

Nmap scan report for 172.16.10.11
Host is up (0.000038s latency).
Not shown: 998 closed tcp ports (reset)
PORT   STATE SERVICE
21/tcp open  ftp
80/tcp open  http
MAC Address: F6:F2:1D:05:71:02 (Unknown)
Device type: general purpose
Running: Linux 4.X|5.X
OS CPE: cpe:/o:linux:linux_kernel:4 cpe:/o:linux:linux_kernel:5
OS details: Linux 4.15 - 5.19, OpenWrt 21.02 (Linux 5.4)
Network Distance: 1 hop

Получение данных: 

#!/bin/bash

HOSTS="$*"

if [[ "${EUID}" -ne 0 ]]; then
  echo "Run script with sudo."
  exit 1
fi

if [[ "$#" -eq 0 ]]; then
  echo 'Need at least one IP'
  exit 1
fi

nmap_scan=$(sudo nmap -O ${HOSTS} -oG -)
while read -r line; do
  ip=$(echo "${line}" | awk '{print $2}')
  os=$(echo "${line}" | awk -F'OS: ' '{print $2}' | sed 's/Seq.*//g')
  if [[ -n "${ip}" ]] && [[ -n "${os}" ]]; then
    echo "IP: ${ip} OS: ${os}"
  fi
done <<< "${nmap_scan}"

Сканирование web ресурса

Есть ряд сканеров, например nikto. Использование 

nikto -host 172.16.10.11 -port 80

+ Server: Apache/2.4.58 (Ubuntu)
+ /: The anti-clickjacking X-Frame-Options header is not present. See: https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Frame-Options
+ /: The X-Content-Type-Options header is not set. This could allow the user agent to render the content of the site in a different fashion to the MIME type. See: https://www.netsparker.com/web-vulnerability-scanner/vulnerabilities/missing-content-type-header/
+ No CGI Directories found (use '-C all' to force check all possible dirs)
+ /: Server may leak inodes via ETags, header found with file /, inode: 29af, size: 63d6cf46a153e, mtime: gzip. See: http://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2003-1418
+ OPTIONS: Allowed HTTP Methods: GET, POST, OPTIONS, HEAD .
+ /backup/: Directory indexing found.
+ /backup/: This might be interesting.
+ 8102 requests: 0 error(s) and 6 item(s) reported on remote host
+ End Time:           2025-08-30 20:12:35 (GMT8) (40 seconds)

Скрипт сохранения файлов из открытых директории

#!/bin/bash
FILE="${1}"
OUTPUT_FOLDER="${2}"

if [[ ! -s "${FILE}" ]]; then
  echo "You must provide a non-empty hosts file as an argument."
  exit 1
fi

if [[ -z "${OUTPUT_FOLDER}" ]]; then
  OUTPUT_FOLDER="data"
fi

while read -r line; do
  url=$(echo "${line}" | xargs)
  if [[ -n "${url}" ]]; then
    echo "Testing ${url} for Directory indexing..."
    if curl -L -s "${url}" | grep -q -e "Index of /" -e "[PARENTDIR]"; then
      echo -e "\t -!- Found Directory Indexing page at ${url}"
      echo -e "\t -!- Downloading to the \"${OUTPUT_FOLDER}\" folder..."
      mkdir -p "${OUTPUT_FOLDER}"
      wget -q -r -np -R "index.html*" "${url}" -P "${OUTPUT_FOLDER}"
    fi
  fi
done < <(cat "${FILE}")

Сканирование директорий, закрытых от индексирования в robots.txt

Можно просканировать закрытые директории, просмотрев коды ответов при обращении: 

#!/bin/bash

TARGET_URL="http://172.16.10.12"
ROBOTS_FILE="robots.txt"

while read -r line; do
  path=$(echo "${line}" | awk -F'Disallow: ' '{print $2}')
  if [[ -n "${path}" ]] then
    url="${TARGET_URL}/${path}"
    status_code=$(curl -s -o /dev/null -w "%{http_code}" "${url}")
    echo "URL: ${url} returned a status code of: ${status_code}"
  fi
done < <(curl -s "${TARGET_URL}/${ROBOTS_FILE}")

Инструмент dirsearch

Поиск скрытых путей и файлов на web сервере. Отдельная база.

dirsearch -u http://172.16.10.10:8081/

--max-rate=REQUESTS Ограничение числа запросов.

Охрененный инструмент.

Получение git репозитория (GitJacking)

Можно при возможности качнуть git проекта.

gitjacker http://172.16.10.11/backup/acme-impact-alliance/ -o acme-impact-alliance-git

Потом git log и другие инструменты поиска например файлов авторизации.

Сканер уязвимостей Nuclei

Адрес проекта

Отправляет DNS, HTTP, сокеты. Общая база с возможностью расширения. Можно использовать для поиска данных авторизации в локальных файлах.

Основан на YAML шаблонах. Структура шаблона:

ID Уникальный идентификатор шаблона
Metadata Описание шаблона (автор, ...
Protocol Протокол
Operators Паттерны и получаемые данные

Простой шаблон: 

id: detect-apache-welcome-page
info:
  name: Apache2 Ubuntu Default Page
  author: Dolev Farhi and Nick Aleks
  severity: info
  tags: apache
http:
  - method: GET
    path:
      - '{{BaseURL}}'
    matchers:
      - type: word
        words:
          - "Apache2 Ubuntu Default Page: It works"
        part: body