zyg0th/anglerfi.sh
GitHub: zyg0th/anglerfi.sh
面向 Debian/Ubuntu 上进攻安全工具链的统一包管理器,将 apt/go/pipx/git/手动安装封装在一个 CLI 和可编辑目录之后,实现一致的安装、移除和列表操作。
Stars: 1 | Forks: 0
# 𩽾𩾌鱼
**用于进攻安全设备的统一包管理器。**
用于进攻安全工作的 Debian/Ubuntu 设备最终会将工具散落在 `apt`、`go install`、`pipx`、`/opt` 中手动构建的 tarball 以及各种临时 shell 脚本中——每个管理器互不感知,偶尔还会互相覆盖同名的二进制文件。Anglerfish 将所有这些包装在一个 CLI 和一个可编辑的目录之后,因此无论工具实际来自哪里,安装、列出和移除你的工具集只需使用一条统一的命令。
专为运行 Debian 或 Ubuntu 的进攻安全从业者构建,他们希望有一种干净、可重现的方式,将一台全新的设备变成一个可用的工具包。
## 它是什么
- **`anglerfi.sh`** —— CLI。解析命令,分发给 `apt`、`go install`、`pipx` 或手动 tarball/jar/deb 安装程序,并可以锁定防火墙。
- **`package.json`** —— 工具目录。可编辑的列表,记录了可安装的内容及安装方式,并分组为 `meta` 捆绑包(`web`、`mobile`、`infra`、`references`),你可以一次性安装它们。
## 安装
### 选项 A —— `.deb`(推荐)
从 [GitHub Actions artifacts](../../actions/workflows/build-deb.yml) 或 [ tagged release](../../releases) 获取最新的构建版本,然后:
```
sudo apt install ./anglerfish__all.deb
```
`apt`(不是 `dpkg -i`)会自动解析依赖(`jq`、`wget`、`curl`、`tar`、`unzip`、`python3`、`git`、`iptables`、`iptables-persistent`)。这会安装:
- `/usr/bin/anglerfi.sh` —— CLI,root:root 755
- `/usr/bin/af` —— 指向 `anglerfi.sh` 的符号链接,这样你就不必输入全名
- `/etc/anglerfish/package.json` —— 目录,root:root 644,标记为 conffile(你的修改在升级后依然保留)
- `man anglerfi.sh` / `man af` —— 包含每个 flag、目录类型以及 `-pkg`/`+pkg` 元组合语法的完整参考
### 选项 B —— 从源码运行
```
git clone git@github.com:zyg0th/anglerfi.sh.git
cd anglerfi.sh
chmod +x anglerfi.sh
./anglerfi.sh -l # unprivileged actions work as-is
```
以这种方式运行时,脚本会回退到位于其旁边的 `package.json`。
**特权操作(`apt`/`manual` 安装和移除、`--firewall`、`--setup`)要求脚本和目录同时归 root 所有,且不可被 group/other 写入** —— 脚本会故意拒绝在其他情况下运行(参见[安全说明](#security-notes))。一个全新的 git checkout 副本属于你,而不是 root,因此在修复所有权之前,这些命令会失败:
```
sudo chown root:root anglerfi.sh package.json
sudo chmod 755 anglerfi.sh
sudo chmod 644 package.json
sudo ./anglerfi.sh --setup
```
如果你不想对你当前的工作副本进行 chown,请改用选项 A —— `.deb` 会为你设置好这一切。
## 用法
```
anglerfi.sh -i, --install [-v|--version ] [-pkg ...] [+pkg ...]
install a package or a full meta group
(-pkg excludes a member from a meta group; +pkg adds an extra package to the run)
anglerfi.sh -r, --remove remove a package or a full meta group
anglerfi.sh -l, --list [-a|-all|--all] list installed packages (--all: include missing ones too)
anglerfi.sh --firewall configure iptables, persisted via iptables-persistent
anglerfi.sh -s, --setup install go/pipx/git/cargo toolchains
anglerfi.sh -h, --help show this help
```
### 示例
```
anglerfi.sh -i nmap # single package (apt-backed) - prompts for sudo itself
anglerfi.sh -i nmap -v 7.94 # pin a specific apt version instead of whatever's current
anglerfi.sh -i nuclei -v v3.2.0 # same, for a go-backed package (rewrites the @version suffix)
anglerfi.sh -i reflutter -v 0.8.5 # same, for a pipx-backed package (forces reinstall at that pin)
anglerfi.sh -i web # everything in the "web" meta group
anglerfi.sh -i web -zaproxy +burpsuite-pro # "web", but skip zaproxy and add burpsuite-pro for this run
anglerfi.sh -i web +infra +osint # merge three meta groups into one run (deduplicated)
anglerfi.sh -l # what's actually installed
anglerfi.sh -l --all # installed + missing, full catalog
anglerfi.sh -r caido # remove a manually-installed tool
anglerfi.sh --firewall desktop # deny all inbound except 8000/8080
anglerfi.sh --firewall server # deny all inbound except 22
```
`-v`/`--version` 仅在最终刚好安装一个包时适用(在应用了所有的 `-pkg`/`+pkg` 之后)—— 如果解析出的数量多于或少于一个,或者对于 `manual` 安装,它都会被拒绝(因为这些安装已经通过 hash 固定到了特定的 artifact 上;如果你需要不同的版本,请修改 `package.json`)。
`-pkg`/`+pkg` 可以在不改动 `package.json` 的情况下,为单次运行自定义 meta 组:`-pkg` 会剔除某个成员,`+pkg` 则会在安装时附带一个额外的包。两者都可以自由地重复和组合使用;如果指定的名称本身就是一个 meta,`+pkg` 会扩展出整个 meta 组的所有成员(因此 `-i web +infra +osint` 会在单次运行中合并三个组)—— 最终的列表总是会进行去重。这两个 flag 在针对单个(非 meta)包时会被拒绝 —— 因为此时既没有可以剔除的成员,也没有可以伴随运行的对象。
你不需要自己加 `sudo` 前缀 —— 脚本只会在遇到需要 root 权限的具体命令时(如 `apt-get`、在 `/opt`/`/etc` 下的写入操作、`iptables` 等)提升权限,并在执行到该命令时提示你输入密码。`go install` 及相关命令会始终以你自己的用户身份运行,因此二进制文件会存放在你自己的 `$GOPATH` 中,而不是 root 的目录下。
## 目录 (`package.json`)
六个部分:
- **`meta`** —— 命名的捆绑包(`web`、`mobile`、`infra`、`references`、`osint`、`dev`、`wireless`),映射到一个包名列表。`-i web` 会展开并安装每个成员。字典/指南被放在了它们专属的 `references` 捆绑包中,而不是强加给每一个安装 `web`/`mobile`/`infra` 的用户 —— 没有人应该仅仅为了获取 `ffuf` 就不得不忍受一个 3.4GB 大小的 SecLists 克隆。
- **`apt`** —— `apt-get install` 的轻量级封装。`check` 决定了它是否已经存在。可选的 `pre_install` 会在安装前运行一次(例如添加供应商的 apt repo 和 GPG key),适用于那些不在 Debian/Ubuntu 默认 repo 中,但提供了它们自己 repo 的包 —— 这样就无需在上游每次发布时固定或重新验证 hash,因为从那时起,供应商的 repo 就是信任机制(参见 `code`,即 VS Code 真实的 apt 包名)。
- **`go`** —— 封装了 `go install @version`。
- **`pipx`** —— 封装了 `pipx install `,适用于不应污染系统 `pip` 的 Python CLI 工具。
- **`git`** —— 浅克隆(`--depth 1`)一个 `repo` 到 `/opt/` 中,可选择在特定的 `ref`(tag/branch)处克隆,然后运行 `post_clone`(符号链接、包装脚本)。不进行 hash 固定 —— 这是为了那些需要追踪上游的工具(例如 `searchsploit` 自身的 `-u` 更新路径就期望它能对一个真实的 git checkout 执行 `git pull`)而做出的权衡。当上游项目本身就是 git repo(一个你原本会手动 `git clone` 的脚本/源码树),而不是真实 artifact 是单独构建的发布版二进制文件时,请使用此选项代替 `manual`。
- **`manual`** —— 适用于没有包管理器的任何情况:下载 tarball/jar/deb,通过与固定的 `hash`(sha256)进行比对来验证它,然后运行 `post_install`(解压、在 `/usr/local/bin` 创建符号链接、创建 `.desktop` 文件,或执行 `apt-get install ./file.deb`),并提供相应的 `remove` 命令以便进行彻底的卸载。
目前所有 `manual` 类型的下载都固定为 `linux-x86_64`/`amd64` 构建版本 —— 暂不支持 arm/aarch64。
目前已包含:`nmap`, `nuclei`, `httpx`, `ffuf`, `sqlmap`, `gobuster`, `wpscan`, `caido`, `subfinder`, `masscan`, `amass`, `netexec`, `smbmap`, `python3-impacket`, `hashcat`, `john`, `hydra`, `jadx`, `adb`, `apktool`, `scrcpy`, `android-studio`, `uber-apk-signer`, `apkeditor`, `reflutter`, `frida-tools`, `hermes-dec`, `palera1n`, `pidcat`, `searchsploit`, `feroxbuster`, `seclists`, `payloadsallthethings`, `internalallthethings`, `hardwareallthethings`, `mastg`, `wstg`, `gtfobins`, `lolbas`, `sherlock`, `maigret`, `holehe`, `theharvester`, `libimage-exiftool-perl`, `gau`, `waybackurls`, `clang`, `gcc`, `neovim`, `code` (VS Code), `responder`, `netcat-openbsd`, `socat`, `sliver-client`, `sliver-server`, `metasploit-framework`, `wireshark`, `tcpdump`, `bettercap`, `aircrack-ng`, `wifite`, `reaver`, `bluez-tools`, `libnfc-bin`, `mfoc`, `podman`, `vagrant`, `docker-ce`, `virtualbox-7.2`, `burpsuite-pro`, `zaproxy`。
`docker-ce` 和 `virtualbox-7.2` 使用 `pre_install` 来注册它们各自供应商的 apt repo(分别是 Docker 和 Oracle 的)—— 与 `code` 采用相同的模式,出于同样的原因:无需维护 hash,并且 `apt upgrade` 会永久保持它们的最新状态。
`burpsuite-pro` 会安装 Professional 版本的二进制文件本身(通过 hash 固定,通过 `-q -dir` 进行静默 Install4j 安装)—— 目录中任何地方都不存储或需要 license key;你需要在自己首次启动时使用自己的 PortSwigger license 进行激活。安装程序已经生成了一个正确的(带有真实图标的) `.desktop` 条目并指向安装目录,因此 `post_install` 只需复制它,而无需手动编写。
`metasploit-framework` 运行的是 Rapid7 官方的 `msfinstall` 脚本(通过 hash 固定),而不是由我们自己重新实现它的 apt repo/GPG key 验证流程 —— 它内部已经完全实现了这些功能,手动重新推导只会增加一项需要与上游保持同步的工作。
`theharvester` 的 PyPI 包是一个陈旧且无人维护的 `0.0.1` stub —— 真实的工程(目前版本为 `4.11.1`)从未在那里发布过正式的 release。直接安装它将成为一个典型的 dependency-confusion 陷阱,因此它的 `pipx` 条目将 `package` 指向了 `git+https://github.com/laramies/theHarvester.git`,而不是 PyPI 上的名称,它直接从真实的源码进行构建(已确认生成的 wheel 的 entry points 匹配)。
`gtfobins`/`lolbas` 是 `.desktop` 快捷方式,而不是克隆 —— 它们只是通过 `xdg-open` 在你的默认浏览器中打开在线网站(`gtfobins.org`、`lolbas-project.github.io`)。不需要 git clone,也不需要 Ruby/Jekyll 工具链:因为本目录中的几乎所有其他操作都已经默认你需要有互联网访问权限,所以在本地构建除了占用磁盘和带来维护成本之外,没有任何额外价值。
修改 `package.json` 以添加你自己的工具或更改某个 meta 组的安装内容。
## 安全说明
- **选择性提权,而非仅限 root 进程。** 脚本以你自己的用户身份运行,并且仅重新执行那些需要 root 权限(通过 `sudo`)的特定命令 —— 如 `apt-get`、在 `/opt`/`/etc` 下的写入操作、`iptables`。`go install` 和目录查找绝不会进行提权,因此即使你碰巧使用了 `sudo` 来启动整个脚本,工具也会安装到你自己的 `$GOPATH` 中,而不是 root 的目录下(它会检测 `$SUDO_USER` 并在这些调用时降权回原始用户)。
- **目录是受信任的配置,而非用户输入。** 当特权操作需要时,每一个 `install`/`post_install`/`remove`/`check` 字段都会以 root 身份运行。请像对待 `/etc/sudoers` 一样对待 `/etc/anglerfish/package.json` —— 必须归 root 所有,且不可被 group/world 写入。
- **脚本会在运行时自行强制执行此规则。** 在执行任何特权操作之前,它会验证 `anglerfi.sh` 和 `package.json` 是否都归 root 所有,并且没有 group/other 写入权限 —— 否则将拒绝执行。这堵住了明显的 privesc 漏洞:低权限用户将 `$ANGLERFISH_PKG` 指向自己的文件,或者编辑可写的脚本/目录,都无法借此让 root 运行任何内容。`.deb` 会自动设置正确的所有权;而源码检出副本则需要先对这两个文件执行 `chown root:root`,特权命令才能运行(参见[选项 B](#option-b-run-from-source))。
- **如果被设置了 setuid/setgid 则拒绝运行。** Linux 的 `execve()` 本来就已经会在解析 `#!` 脚本时丢弃这些位,但这是内核行为,并非本脚本可以控制的保证。`anglerfi.sh` 并不打算通过这种方式获取特权(它按命令显式使用 `sudo`)—— 因此它会在启动时检查自身的模式,如果发现设置了其中任何一个位,就会在任何操作之前退出。
- **手动安装经过了 hash 验证。** 下载的 artifact 在进行任何解压或符号链接之前,都会与固定的 sha256 进行检查比对;如果不匹配,则会中止操作并该文件。
- **PATH 在启动时已被固定**(`/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin`),并且脚本调用的每个外部二进制文件(`jq`、`apt-get`、`go`、`tar`、`sha256sum` 等)都会根据该固定路径解析一次 —— 恶意添加到 `$PATH` 前面的目录无法覆盖它们。
## License
参见 [LICENSE](LICENSE)。
标签:Blue Team, Cutter, Debian/Ubuntu, Shell脚本, 域名收集, 攻防工具链管理, 日志审计, 统一包管理器, 网络安全研究