我们将构造一个架空的公司 ACME Infinity Servers,配备有虚构的工作人员,顾客,数据
使用 Kali Linux 系统尝试对目标进行一系列攻击,在这个过程中学习网络安全的基本事项

# Kali 的安装与配置

Kali Linux 是一个 Linux 发行版,专门为网络安全和渗透测试而设计。
官网:https://www.kali.org/

本文基于使用虚拟机,构建 x86_64 架构的 Kali Linux 为前提,不同的架构会导致后续指令中有报错

下载并安装 VMware Workstation Pro:https://www.vmware.com/products/workstation-player/workstation-player-evaluation.html
下载 Kali Linux 镜像(VMWare 版本):https://www.kali.org/get-kali/#kali-virtual-machines
解压 Kali 镜像压缩包,找到其中的 .vmx 文件,用 VMware Workstation Pro 打开即可
Hint:如果在里面不显示鼠标,先结束虚拟机进程,升级虚拟机配置到符合当前 VMware 的版本,再重启
Hint:在虚拟机中,从主机粘贴文本进去是 Ctrl + Shift + V ,而不是 Ctrl + V
Hint:默认情况下用户名和密码都是 kali

在开始之前,请先确保设备连接上了网络,并且检查当前时间是否同步

基础配置:更新软件源(这会花费一些时间)

sudo apt update -y
sudo apt upgrade -y
sudo apt dist-upgrade -y

如果希望将默认的 Zsh 切换回 Bash,可以执行以下命令

sudo usermod -s /bin/bash $USER

# 测试环境的搭建

# 自动配置(建议)

我们默认在用户目录创建工具文件夹,并构建测试环境,这也会自动为系统配置将要使用的诸多工具

cd ~
git clone https://github.com/oreilly-japan/black-hat-bash-ja.git
cd ./black-hat-bash-ja/lab

如果你的用户名不是 kali ,那么需要修改一下自动化代码:

sed -i 's/grep kali/grep "${SUDO_USER}"/' init.sh
sed -i 's/usermod --shell \/bin\/bash kali/usermod --shell \/bin\/bash "${SUDO_USER}"/' init.sh

执行自动化脚本,这会花费一些时间
在执行前,修改一下 pwncat-cs 的安装命令,因为 Kali 的 Python 包管理器发生了变化

sed -i 's/pip3 install pwncat-cs/pip3 install pwncat-cs --break-system-packages/' init.sh
sudo make init

# 手动配置

Kali 中经常使用 Docker 来构建测试环境

在实际安装 Docker 之前,通常建议执行以下配置:
设置 Docker 官方 APT 源,以便使用 apt 包管理器安装和更新 Docker。

printf "%s\n" "deb https://download.docker.com/linux/debian bullseye stable" | \
sudo tee /etc/apt/sources.list.d/docker-ce.list

下载并添加 Docker 官方 GPG 密钥,以确保从 Docker 仓库安装的软件包的安全性。

curl -fsSL https://download.docker.com/linux/debian/gpg | \
sudo gpg --dearmor -o /etc/apt/trusted.gpg.d/docker-ce-archive-keyring.gpg

完成上述配置后,更新软件源,并安装 Docker 引擎和相关组件。

sudo apt update -y
sudo apt install docker-ce docker-ce-cli containerd.io -y

安装完成后,可以通过以下命令验证 Docker 是否正确安装并正在运行。

sudo docker compose --help

建议配置:启动开机自启,并且通过将当前用户添加到 Docker 组来允许非 root 用户运行 Docker 命令。需要重启生效

sudo systemctl enable docker --now
sudo usermod -aG docker $USER

WhatWeb 是由 Andrew Horton 与 Brendan Coles 开发的,基于 Ruby 语言的 Web 扫描器
能够识别目标网站使用的服务器软件、编程语言、CMS、框架等技术细节。

安装并确认

sudo apt install whatweb -y
whatweb -h

RustScan 是由 Autumn Skerritt 开发的,基于 Rust 语言的端口扫描器
特点是超高速,可以在几秒内完全扫描一个主机的所有 65535 个端口

为了更省事、更隔离、更少污染系统,建议通过 Docker 来安装和使用 RustScan

sudo docker pull rustscan/rustscan:2.1.1
sudo docker run --rm rustscan/rustscan:2.1.1 --help

Nuclei 是由 ProjectDiscovery 开发的,基于 Go 语言的漏洞扫描工具
能够快速扫描目标系统的漏洞和安全配置问题,支持多种协议和模板。

安装并确认

sudo apt install nuclei -y
nuclei -h

首次运行 Nuclei 后,会自动创建目录 ~/.local/nuclei-templates ,可以用于下载目前公开的 Nuclei 模板库


dirsearch 用于检索 Web 服务器上的隐藏目录和文件

安装并验证

sudo apt install dirsearch -y
dirsearch -h

# 检查环境

完成搭建后,检查测试环境是否已经就绪

sudo make test
# output: 
# Lab is up.

使用 docker 可以查看当前运行的容器列表

sudo docker ps --format "{{.Names}}"

在我们的测试环境中,已经预设了八个靶机
靶机列表

Machine Public IP Private IP Hostname
p-web-01 172.16.10.10 p-web-01.acme-infinity-servers.com
p-ftp-01 172.16.10.11 p-ftp-01.acme-infinity-servers.com
p-web-02 172.16.10.12 10.1.0.11 p-web-02.acme-infinity-servers.com
p-jumpbox-01 172.16.10.13 10.1.0.12 p-jumpbox-01.acme-infinity-servers.com
c-backup-01 10.1.0.13 c-backup-01.acme-infinity-servers.com
c-redis-01 10.1.0.14 c-redis-01.acme-infinity-servers.com
c-db-01 10.1.0.15 c-db-01.acme-infinity-servers.com
c-db-02 10.1.0.16 c-db-02.acme-infinity-servers.com

通过以下指令可以实现对目标机器的访问

sudo docker exec -it MACHINE_NAME bash

为了轻松访问两侧的测试环境,这里有两个不同的网络接口,分别是用于访问公网的 br_public 和用于访问内网的 br_corporate ,可以通过以下命令查看

ip addr | grep "br_"

# 主机扫描

信息收集是任何网络攻防战的第一步,攻击者需要尽可能多地了解目标系统的细节,以便找到潜在的漏洞和攻击路径。

这里先给出利用 Bash 实现的自动化名单生成方法
第一个是生成连续的 IP 地址列表,示例中使用目标公司的公网网段

#!/bin/bash
# generate_ip_list.sh
for ip in $(seq 1 254); do
    echo "172.16.10.${ip}" >> 172.16.10-hosts.txt
done

使用

sudo chmod u+x generate_ip_list.sh
./generate_ip_list.sh

第二个是生成子域名列表,假设我们想要侦察域名 example.com ,如果不指定子域名,会使得扫描范围过大,因此一般来说需要限定在 mail.example.comftp.example.comdev.example.com 等常见子域名上
Kali 系统中默认装配有子域名列表 /usr/share/wordlists/amass/subdomains-top1mil-110000.txt
编写生成子域名的脚本

#!/bin/bash
# generate_subdomains.sh
DOMAIN="${1}"
FILE="${2}"
while read -r subdomain; do
    echo "${subdomain}.${DOMAIN}"
done < "${FILE}"

使用该脚本,但是由于 Kali 自带的子域名列表对于我们的学习来说过大,这里使用测试环境中准备的文件 subdomains-1000.txt

sudo chmod u+x generate_subdomains.sh
./generate_subdomains.sh example.com ~/black-hat-bash-ja/ch04/subdomains-1000.txt

完成后,我们开始使用具体的工具执行主机扫描

# Ping

最基本的工具是 ping ,它通过发送 ICMP 回显请求来检测主机是否在线。
该命令将持续执行,直到手动使用 Ctrl + C 来停止

ping 172.16.10.10

可以通过 Bash 脚本实现对多个目标的批量 ping ,例如对示例网段 172.16.10.0/24 进行扫描

#!/bin/bash
# multi_host_ping.sh
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}"
  • -c :指定发送的 ICMP 包数量,这里设置为 1,表示只发送一个包
  • -W :指定等待每个回复的超时时间(秒),这里设置为 1 秒
  • -w :指定整个 ping 命令的超时时间(秒),这里设置为 1 秒,确保命令不会因为某个主机无响应而长时间挂起

使用:

sudo chmod u+x multi_host_ping.sh
./multi_host_ping.sh 172.16.10-hosts.txt
# output:
# 172.16.10.1 is up
# 172.16.10.10 is up
# 172.16.10.11 is up
# 172.16.10.12 is up
# 172.16.10.13 is up

# Nmap

此外,还可以使用 Nmap 执行网段扫描

nmap -sn 172.16.10.0/24
  • -sn (skip port scan):表示仅进行主机发现扫描,不进行端口扫描

可以精简 Nmap 的输出结果,只显示在线主机的 IP 地址

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

# arp-scan

如果是扫描本地局域网内的主机,可以使用 arp-scan
arp-scan 向局域网内的每个 IP 地址发送 ARP 请求(用于解析 IP 地址到 MAC 地址),并根据响应来确定哪些主机在线
该命令需要 root 权限来执行

sudo arp-scan 172.16.10.0/24 -I br_public
  • -I (Interface):指定要使用的网络接口,这里设置为 br_public ,需要根据实际情况替换为正确的接口名称

# 端口扫描

主机发现之后,攻击者通常会进行端口扫描,以确定目标主机上有哪些服务在运行,以及这些服务可能存在的漏洞。

# Nmap

指定目标即可用 Nmap 进行端口扫描,这里使用 Nmap 官方的练习靶机 scanme.nmap.org 作为示例

nmap scanme.nmap.org

如果不进行任何参数指定,默认情况下 Nmap 会以以下配置执行

  • SYN 扫描(半开放扫描):通过发送 SYN 包来探测端口状态,而不完成 TCP 三次握手,减少被检测到的风险
  • 前 1000 个常见端口:只扫描最常见的 1000 个端口
  • TCP 协议:默认扫描 TCP 端口,不扫描 UDP 端口

也可以指定 IP 地址,或者多重目标扫描

nmap 172.16.10.1
nmap localhost scanme.nmap.org

也可以从文件中读取,并利用 grep 筛选

nmap -sV -iL 172.16.10-hosts.txt | grep open
# output:
# 8081/tcp open  http    Werkzeug httpd 3.0.1 (Python 3.12.3)
# 21/tcp open  ftp     vsftpd 3.0.5
# 80/tcp open  http    Apache httpd 2.4.58 ((Ubuntu))
# 80/tcp open  http    Apache httpd 2.4.57 ((Debian))
# 22/tcp open  ssh     OpenSSH 9.6p1 Ubuntu 3ubuntu13.15 (Ubuntu Linux; protocol 2.0)
  • -sV (service/version detection):启用服务版本检测,尝试识别每个开放端口上运行的服务及其版本信息
  • -iL (input from List):从指定文件中读取目标列表,这里是 172.16.10-hosts.txt

# RustScan

rustscan 扫描端口的速度更快,但是扫描网段很慢,所以一般先检测到网段中的存活主机,再使用 rustscan 进行端口扫描

sudo nmap -sn 172.16.10.0/24 -oG - | awk '/Up$/{print $2}' > alive.txt
rustscan -g -a $(paste -sd, alive.txt) -r 1-1024
# output:
# 72.16.10.11 -> [21,80]
# 172.16.10.13 -> [22]
# 172.16.10.12 -> [80]
  • -oG (output in Grepable format):以 grepable 格式输出扫描结果,并将输出发送到标准输出(即终端)
  • -g (grepable):启用 grepable 输出格式
  • -a (address):指定要扫描的目标地址,这里使用 $(paste -sd, alive.txt)alive.txt 中的 IP 地址列表转换为逗号分隔的字符串
  • -r (range):指定要扫描的端口范围,这里设置为 1-1024,表示扫描前 1024 个端口