FTP漏洞扫描器构建:用Bash脚本整合Nuclei与Nmap NSE

2 阅读3分钟

练习概述

本次练习来自 Dolev Farhi 与 Nick Aleks 合著的《Black Hat Bash》一书的第五章:漏洞扫描与模糊测试。我们将解决其中的一个挑战性练习。

本章介绍了一些渗透测试过程中的关键工具:

  1. Nuclei
  2. Nmap NSE 脚本
  3. GitJacker(用于发现网站端点上配置错误的 Git 仓库)
  4. Wfuzz 与 ffuf(用于向网站发送半随机负载以发现隐藏信息,常用于寻找隐藏的 Web 路径、目录和文件)
  5. nikto(用于 Web 漏洞扫描)

在章节末尾,按照惯例,我们将面临一个具有挑战性的练习。

让我们运用所学知识和技能尝试解决这个练习,即使最终结果可能存在瑕疵,但至少我们做出了尝试,并且可以不断改进!

练习:组合工具发现 FTP 问题

“本练习的目标是编写一个脚本,该脚本能够调用多个安全工具,解析它们的输出,并将这些输出传递给其他工具以执行后续操作。以这种方式编排多个工具是渗透测试中的常见任务,因此我们鼓励你熟练掌握此类工作流的构建。

你的脚本应实现以下功能:

  1. 在命令行中接受一个或多个 IP 地址。
  2. 对 IP 地址运行端口扫描器(使用何种端口扫描器完全由你决定)。
  3. 识别开放端口。如果其中存在 FTP 端口(21/TCP),脚本应将该地址传递给第 4 步中的漏洞扫描器。
  4. 使用 Nuclei 扫描 IP 地址和端口。尝试应用专门用于查找 FTP 服务器问题的模板。在 Nuclei 模板文件夹 ~/.local/nuclei-templates/ 中搜索与 FTP 相关的模板,或使用 Nuclei 的 -tags ftp 标志。
  5. 使用 Nmap 扫描 IP 地址。利用能够发现 FTP 服务器漏洞的 NSE 脚本,你可以在 /usr/share/nmap/scripts/ 目录中搜索这些脚本,例如 ftp-anon.nse
  6. 将结果解析并写入一个文件,格式自定。该文件应包含漏洞描述、相关的 IP 地址和端口、发现漏洞的时间戳以及检测到该问题的工具名称。对数据呈现方式没有硬性要求;一种选择是使用 HTML 表格,也可以将结果写入 CSV 文件。”

我的脚本解决方案

#!/usr/bin/env bash

if [[ "$#" == 0 ]]; then
    echo "你必须提供一个 IP 作为参数。"
    exit 1
fi

for TARGET in $@; do
    if ! nc -w 1 ${TARGET} 21; then
        echo "[!] 目标 ${TARGET} 上未检测到 FTP"
        continue
    fi

    while read -r line; do
        ftp_port=$(echo "${line}" | grep "tcp" | awk -F '/' '{print $1}' | grep 21)
        if [[ $ftp_port -eq 21 ]]; then
            echo "[!] 在目标 ${TARGET} 上发现 FTP"
            echo "[!] 正在运行 nuclei…"
            nuclei_result=$(nuclei -tags ftp -target "${TARGET}")
            echo "[!] 正在运行 NSE…"
            nse_result=$(nmap --script=ftp-anon.nse "${TARGET}")
            echo "[!] 正在写入日志文件: opfile.txt…"
            echo -e "# 如果某个目标的结果未在此处显示,则表示该目标未使用 FTP,但脚本会保存端口扫描输出。\n\n目标: ${TARGET}\n工具: Nuclei\n发现结果:\n$nuclei_result\n\n工具: Nmap NSE\n\n发现结果:\n\n$nse_result\n" >> opfile.txt
        fi
    done < <(nmap -sS $TARGET)
done

脚本运行演示

脚本显示了未检测到 FTP 的目标。通过手动对端口 21(FTP)进行 Nmap 端口扫描验证。

脚本显示了检测到 FTP 的目标。

opfile.txt 的输出内容。

解释说明

如您所见,脚本首先检查是否有任何参数传递给了命令行。$# 是一个特殊的 Bash 变量,它以整数形式返回传递给脚本的参数总数。

我们使用一个 for 循环来遍历所有参数。$@ 是一个特殊的 Bash 变量,它包含了传递给脚本的所有参数(类似于数组形式)。

对于传递给脚本的每个参数(即目标的 IP 地址),我们运行一个标准的 Nmap SYN 端口扫描。

我们通过使用 Netcat 连接到目标端口 21 来专门检查该端口是开放还是关闭。这里使用了 if command; then <expr> fi 格式的命令成功评估。

如果 FTP 端口关闭,它会打印“FTP 未检测到”,并使用 continue 命令跳过当前迭代。

如果端口开放,它会运行循环的后续代码块:

只有当目标上的 FTP 端口开放时,才会运行 while 循环的剩余部分。否则我们只打印“FTP 未检测到”。

我们使用带有进程替换(下文解释)的 while 循环来格式化工作流程。

我们通过命令替换过滤出所需的特定端口(21/ftp),并将值赋给 ftp_port 变量。

然后我们使用整数运算符 -eq(代表 equals to,即“等于”)检查 ftp_port 的值是否等于 21。

如果存在值,它会打印“发现 FTP 端口”。

它使用 -tags ftp-target 标志运行 Nuclei,并将输出追加到 nuclei_result 变量。

接着它运行 NSE 脚本,并将输出追加到 nse_result 变量。

然后使用带有 -e 标志的 echo 命令,该标志允许我们将反斜杠解释为转义序列,从而以专业、易于解析的格式将输出打印到 opfile.txt 文件中。

done < <(nmap -sS ${TARGET}) 是一个 Bash 进程替换指令,它允许我们将一个命令当作文件来使用。它在一个流上运行命令,该流由一个整数的文件描述符表示。例如,假设我们的 nmap -sS 扫描在 /dev/fd/3/ 流上运行,它看起来像一个目录。命令的输出保留在 /dev/fd/3/ 目录中,循环从该流中读取数据,就像从文件中读取一样。

结语

亲自尝试一下吧!目标不是构建一个零错误的完美专业级脚本,而是理解工作流程,并使其足够语义化,以便你能够在无需外部帮助的情况下自行编排。 CSD0tFqvECLokhw9aBeRqhu8+HKTh/2RSSRVwf75o4HAONYzpbYkCeYXW65N31x9X/8tC5F8MBuHE8UkKjB5Yaie+qjXi0Gd/cZQcCXpNepOPts5oD3jjtnd1g2sU9gj