我们将构造一个架空的公司 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.com , ftp.example.com , dev.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 个端口