从零构建安全审计Skill:把资深审计经验封装成AI技能包
2026/9/23 7:57:21 网站建设 项目流程

从零构建一个 security-audit-skill:我把安全审计的看家本领,全部塞给了 AI

这两年大模型圈子里最热的关键词,除了 Agent(智能体),就是 Skill(技能)了。Claude 的 Agent Skills、Codex 的 skill 脚本、OpenCode 的 skill 插件、各种 GitHub 上的 skill 技能库……大家都在说“给 AI 装上一个专属技能包,它就能干专业活”。作为一个常年做安全审计和渗透测试的老兵,我几乎本能地意识到一件事:安全审计这个场景,简直天生就是 Skill 的完美素材。

为什么这么说?因为安全审计本身就是一个高度流程化、强依赖检查清单和标准规范的工作——资产盘点、端口与服务识别、配置基线核查、脆弱性分析、风险定级、报告输出,每一步都有成熟的方法论。这些东西恰恰是 LLM(大语言模型)最擅长固化的结构化知识。把“某个资深安全工程师脑子里的带人套路”变成一个可以反复调用、稳定输出的 security-audit-skill,我实测下来,效率提升不是一星半点。

这篇博文不聊空泛的趋势,直接围绕“security-audit-skill 是什么、怎么设计、怎么写、怎么调试、踩过哪些坑”展开。打算做 AI 技能开发的朋友、一线安全工程师、以及想把自己的专业经验沉淀成“可复制资产”的从业者,都可以参考。内容全部来自我的实际落地过程,代码和模板可以直接拿走改。

1. 为什么要做 security-audit-skill:AI 时代的审计方法论复用

1.1 Skill 到底是什么,它和 Agent 有什么区别

在进入正题之前,我先花点篇幅把 Skill 这层窗户纸捅破。现在社交平台上关于“Skill”的讨论非常热闹,但很多人其实没搞清楚 Skill 和 Agent 的关系。我的理解非常简单粗暴:Agent 是“干活的人”,Skill 是“干活的方法手册”。

打个比方。你招了一个新员工(Agent),他聪明、底子好(大模型的通用能力),但你让他做安全审计之前,必须给他一份“公司安全审计作业指导书”——里面写清楚第一步干什么、第二步看什么指标、什么情况定什么风险等级、报告用什么格式。这份“指导书”就是一个 Skill。Skill 本质上是把某个专业领域的知识、流程、判断标准、输出模板,封装成一个结构化的 Markdown 文件或文件套装,在需要的时候被 Agent 按需加载。

市面上 Skill 的形态大致有三种:

  • 纯提示词型:只有一个 SKILL.md,里面全是精心设计的指令和流程,适合纯对话式工具。
  • 脚本增强型:在 SKILL.md 之外附带可执行的 Python、Bash 或 JavaScript 脚本,AI 可以根据任务调用这些工具,适合和系统交互的场景。
  • 数据驱动型:包含大量知识库文件、漏洞库、检查基线数据,适合做检索增强式判断。

security-audit-skill 我采用的是第二种形态,也就是“流程提示词 + 可执行工具脚本 + 基线数据”。原因很简单:安全审计里很多信息(端口开放情况、服务版本、系统配置、日志片段)光靠大模型用“脑子”猜是猜不出来的,必须真实地去目标主机上采集。所以这个 Skill 不能只是嘴上功夫,得能“动手”。

1.2 安全审计场景为什么特别适合做成 Skill

我把安全审计的常规工作流拆开给大家看,你就明白为什么它适合做 Skill 了:

  1. 范围确认:确定审计目标,是 IP 段、域名还是单台主机,边界在哪里。
  2. 信息收集:开放端口、服务版本、操作系统指纹、域名解析记录。
  3. 配置核查:对照安全基线(如 CIS Benchmark、等保要求),检查密码策略、服务配置、补丁版本。
  4. 脆弱性分析:根据服务版本匹配已知漏洞库,对高风险点做进一步确认。
  5. 风险定级与报告输出:按严重程度对发现的问题排序,输出可执行的处理建议。

这套流程的最大特点就是“标准答案相当固定”——什么端口对应什么服务,什么服务版本可能存在什么问题,CIS 基线里某项配置应该是什么值,这些都是高度结构化的知识。传统做法是安全工程师脑子里装着几十个检查列表,辛辛苦苦手工核查。有了 LLM 之后,如果能把这些检查项和判断逻辑变成可检索、可推理的 Skill,审计就从“人肉翻配置文件”变成了“人和 AI 一起翻”,效率完全不是一个量级。

另外,安全审计还有一个特点:它是一个“成熟度依赖人”的工作。同样一份 nmap 扫描结果,新手可能只看开了哪些端口,老手会结合服务版本、TLS 配置、响应头等细节做综合判断。Skill 一个非常棒的价值在于:它能把老手这种“隐性经验”显性化、模块化。我把我在审计中积累的检查要点、风险判断逻辑、报告措辞习惯,原原本本地写进了 Skill 的 prompt 和数据文件里,这就是个人核心资产的“数字化沉淀”。

1.3 这个 Skill 到底能帮你解决什么问题

实际使用下来,security-audit-skill 在以下场景里价值最突出:

  • 中小企业安全自查:没有专职安全工程师,用 AI 配合这个 Skill 做初步基线检查,能发现大部分明显问题。
  • 团队新人陪跑:新入职的渗透测试/安全运营工程师,不知道从哪里下手时,让 AI 按 Skill 流程带着一步步做。
  • 甲方安全验收:拿到第三方检测报告后,想快速验证其中的关键项,用 Skill 辅助抽查。
  • 开发自测:开发同学想在上线前快速看看自己的服务有没有低级安全问题,这是一个足够友好的入口。

它不能替代真正的渗透测试和人工研判,但作为“第一道筛查”和“流程标准化工具”,非常实用。下面我就从头到尾演示一遍,我是如何设计并写出来这个 Skill 的。

2. 设计思路:把一个资深审计员的脑子,拆成一块块能被 AI 理解的功能模块

2.1 整体架构:SKILL.md 为核心的四层设计

写 Skill 不是随便写一段“你是安全专家”的提示词就完事,那样产出的内容极不稳定。我的经验是:按“目标—流程—知识—工具”四个层次来设计,缺一不可。

第一层是角色与目标定义。让 AI 明确知道它在这个 Skill 语境下扮演什么角色,承担什么任务。第二层是流程控制。把安全审计拆成阶段,规定 AI 必须按阶段推进,不能东一榔头西一棒子。第三层是知识与判断标准。把风险定级标准、常见漏洞库、配置基线检查项写成结构化数据。第四层是工具调用。让 AI 在需要真实数据的时候能跑脚本、读文件、扫描端口。

这四个层次最终会落到一个目录结构清晰的文件套装里。我最终采用的目录结构如下:

security-audit-skill/ ├── SKILL.md # 技能入口:定义角色、流程、调用规则 ├── prompts/ │ ├── scope.md # 审计范围与目标识别 │ ├── recon.md # 信息收集引导 │ ├── baseline.md # 配置基线核查 │ ├── vulnerability.md # 脆弱性分析 │ └── report.md # 审计报告生成 ├── scripts/ │ ├── port_scan.py # 轻量端口扫描 │ ├── config_collect.py # 系统配置采集 │ ├── log_check.py # 日志异常识别 │ └── tls_check.sh # TLS/SSL 配置检查 ├── data/ │ ├── risk_level.yaml # 风险定级模型 │ ├── services_map.yaml # 常见服务端口映射 │ ├── baseline_cis.yaml # CIS 基线检查项 │ └── cve_cache.json # 常见 CVE 缓存(离线) └── templates/ └── audit_report_template.md # 审计报告模板

2.2 关键决策:为什么用“多 prompt 文件 + 单入口 SKILL.md”而不是全塞进一个文件

在设计过程中,我第一个纠结的点是:把所有提示词一次性塞进 SKILL.md,还是拆分成多个文件,由 AI 按需读取?

答案是后者,而且要拆得足够细。原因很简单:大模型的上下文窗口是有限资源。如果在 SKILL.md 里把信息收集、配置核查、漏洞分析等全部内容都写满,那么一旦加载,就会占掉大量上下文额度,真正处理用户任务时的“脑容量”就少了。而且,安全审计的多个阶段本来就有先后顺序,没必要让 AI 在刚开始时就背下所有后期规则。

所以我的设计原则是:SKILL.md 只放“入口级别”的内容——角色定义、整体流程概览、各阶段之间的调用关系,以及“什么时候该去读哪个 prompt 文件”的索引。真正的具体指令放在 prompts/ 目录下的各个子文件里,由 AI 在执行到对应阶段时主动去加载。

我在 SKILL.md 里专门写了一段关于文件调用的说明,大意是:

在开始任何阶段前,先阅读 prompts/ 目录下对应该阶段的内容,严格遵循该文件中的步骤和输出格式。不要在未读取对应 prompt 文件的情况下自行猜测流程。

这样做还有一个额外好处:便于维护。比如我后续想优化“配置基线核查”的指令,只需要修改 baseline.md 一个文件,不会影响到其他模块。

2.3 安全边界与授权判断要先写进“基因”里

这一点我必须放在设计思路里单独强调:安全审计是双刃剑,Skill 的提示词设计必须把“合法合规”作为第一原则内置。凡是涉及主动扫描、连接目标系统、读取配置信息的操作,都必须以用户确认授权为前提。我在 SKILL.md 的角色设定里写了一条硬性规则:如果用户要求审计的目标,无法确认是其自有资产或已获得授权,AI 应拒绝继续执行,并提示用户先完成授权流程。

这既是职业操守,也是保护使用者自己的方式。在真实的业务中,我也遇到过一些客户拿着一份授权书副本就来让我们测第三方的系统,这类情况我向来是直接拒绝的。所以这个 Skill 里,这层判断逻辑绝对不可或缺。

3. 实操落地:手把手把 security-audit-skill 的每一个文件写出来

3.1 入口文件 SKILL.md 的完整写法

这个文件是整个 Skill 的大脑。我直接贴出我自己正在用的版本,关键段落我会解释为什么这么写。

--- name: security-audit-skill description: 执行一次结构化的安全审计任务,包括资产识别、端口与服务发现、配置基线核查、脆弱性分析和审计报告生成。适用于对自有系统或已获授权的目标进行安全自查。 when_to_use: 当用户要求进行安全审计、安全评估、基线检查、漏洞扫描或生成安全审计报告时。 --- # 安全审计技能(Security Audit Skill) ## 角色定义 你是一名拥有 10 年以上经验的安全审计专家,精通网络服务识别、系统配置基线核查、漏洞风险分析和安全报告撰写。你的工作风格严谨、细致、结论明确,每一项风险判断都必须有事实依据。 ## 核心原则 1. **授权优先**:在任何扫描、连接、信息采集动作之前,必须确认用户对目标拥有合法合规的操作授权。无法确认授权的,拒绝执行并说明原因。 2. **证据驱动**:所有审计结论必须基于采集到的真实数据,禁止凭经验猜测。没有证据支持的问题,可以列为“待确认项”,但不能写入已确认风险。 3. **最小影响**:信息采集动作应尽量采用非侵入性方式,避免对目标系统造成不必要的影响。 ## 执行流程 请严格按照以下阶段推进审计任务,每个阶段对应 prompts/ 目录下的一个或多个文件。每完成一个阶段,必须向用户汇报阶段结果并得到“继续”的确认后,再进入下一阶段。 ### 阶段一:审计范围确认 - 启动时:请阅读 prompts/scope.md。 - 目标:明确审计对象、审计网络范围、审计目标类型、资源限制。 - 输出:一次简洁的范围确认结果,包含目标列表与审计边界。 ### 阶段二:信息收集 - 在用户确认范围后:请阅读 prompts/recon.md 和 scripts/port_scan.py 的使用说明。 - 目标:发现目标开放端口、运行服务、系统类型、证书、响应头等。 - 输出:结构化的资产与服务清单。 ### 阶段三:配置基线核查 - 在资产清单输出后:请阅读 prompts/baseline.md、data/baseline_cis.yaml 和 scripts/config_collect.py。 - 目标:核查目标系统关键安全配置项是否满足基线要求。 - 输出:配置合规性清单,标注通过、不通过或未检测。 ### 阶段四:脆弱性分析 - 在配置核查完成后:请阅读 prompts/vulnerability.md 和 data/cve_cache.json。 - 目标:根据服务版本、配置缺陷,结合已知漏洞库,识别潜在脆弱性。 - 输出:按风险等级排序的脆弱性列表。 ### 阶段五:审计报告生成 - 在脆弱性分析完成并得到用户确认后:请阅读 prompts/report.md 和 templates/audit_report_template.md。 - 目标:汇总所有发现,输出符合模板要求的完整审计报告。 - 输出:一份包含执行摘要、风险清单、整改建议的 Markdown 报告。 ## 工具调用规则 - 需要真实环境数据时,优先使用 scripts/ 目录下的脚本。 - 调用脚本前,先向用户解释脚本功能与影响范围,确认后再执行。 - 禁止使用任何未在本技能中定义的、可能造成破坏行为的命令和工具。

这段内容的设计核心有两点值得大家借鉴。

第一,我刻意强调了“阶段性汇报与确认”。这是安全审计流程和普通问答式 AI 应用最大的区别——审计每一步都可能影响下一步的判断,所以在工程上强制设置了控制点,防止 AI 一股脑把所有事情做完,中间用户没有干预机会。这和我在实际带团队做审计项目时的节奏是一致的:每一阶段出阶段性结论,客户确认后再推进。

第二,我把“输出格式”的责任交给各个子 prompt,而不是在 SKILL.md 里统一规定。因为每个阶段的输出载体不同,信息收集阶段的输出可能是一张表格,报告阶段的输出是一份长文档,统一格式反而会限制灵活性。

3.2 阶段提示词的设计:以范围确认和脆弱性分析为例

在 prompts/scope.md 里,我的核心思路是“把模糊的需求变成可执行的任务清单”。安全审计里最怕的就是范围不清楚——你说测一个系统,是指只测 Web 应用,还是连底下的数据库、中间件、宿主机一起测?范围模糊不仅影响效率,还可能触及审计红线。所以这个文件里我列了一个范围确认清单:

# 审计范围确认 你需要向用户收集并确认以下信息,逐项确认后输出结构化的范围确认结果: 1. 审计目标:提供目标系统的 URL、域名、IP 或 IP 段。如果是 IP 段,请提供掩码范围。 2. 系统属性:目标是自有资产,还是由第三方运营的受测系统?是否有书面授权? 3. 审计边界:本次审计是否包含 Web 应用层、主机层、中间件层、数据库层、移动端 API? 4. 时间窗口:信息收集和扫描是否有时间限制?是否避开业务高峰期? 5. 禁止操作:是否有明确禁止的测试类型,例如拒绝服务测试、暴力破解、代码执行? 6. 已有信息:是否已有已知的账号权限、架构图、网络拓扑?如有,请一并提供。 ## 输出格式要求 请输出以下 Markdown 结构: ## 审计范围确认结果 - 目标资产列表: - 授权状态: - 审计边界: - 时间窗口: - 禁止操作: - 待确认问题:(如有信息缺失,在此列出并向用户提问)

注意,这里我刻意使用了“待确认问题”这个字段。设计意图在于:如果用户输入的信息不足以支撑审计启动,AI 不要自行假设,而是明确提问。这套思路来源于软件工程的“显式状态管理”——未知状态必须显式暴露,不能被系统悄悄吞掉。

在 prompts/vulnerability.md 里,我更关注“怎么让 AI 的判断有依据、不瞎说”。很多人在用 AI 做漏洞分析时会发现,模型特别喜欢把 CVE 编号、cvss 评分张口就来,结果很多是编的。针对这个问题,我在这份 prompt 里做了一个约束:

# 脆弱性分析 ## 分析前提 - 只有三种来源的信息可以作为判断依据:(1) 实际采集到的服务版本和配置信息;(2) data/cve_cache.json 中离线记录的漏洞条目;(3) 从目标服务器获取的官方公告或补丁信息。 - 对于无法通过上述来源确认的 CVE 编号或漏洞描述,一律标注为“未证实”,不得写入已确认风险。 ## 分析步骤 1. 列出资产清单中每个服务的名称、版本、开放端口与协议。 2. 在 data/cve_cache.json 中检索与版本信息匹配的漏洞条目,记录 CVE 编号、受影响版本、修复版本。 3. 结合配置核查结果,识别因配置不当导致的脆弱性,例如默认口令、弱加密套件、目录列举等。 4. 对每项脆弱性,评估可利用条件、可能影响范围,以及 CVSS 评分的参考范围。 ## 输出格式 | 资产 | 服务 | 版本 | 脆弱性描述 | 证据 | CVSS参考 | 风险等级 |

“证据”和“未证实”这两个词是这个模块的灵魂。我把它们写进 prompt 并解释给 AI:证据字段必须引用实际采集数据,比如“nginx/1.18.0 响应头,与 CVE-2022-xxxx 受影响版本匹配”;没有证据条目不写;无法证实的单独放。实际使用下来,这个约束把幻觉率压到了很低的水平。

3.3 可执行脚本:让 Skill 从“会聊”变成“会干”

Skill 里的脚本不需要很复杂,它们是用来给 AI 提供“真实世界数据”的。我写了几个轻量级脚本,这里挑最核心的两个讲。

第一个是端口扫描脚本scripts/port_scan.py。它本质上是一个基于 Python socket 的简易扫描器,不以全面性为目标,主要用于快速确认资产的开放端口和服务类型。代码如下:

#!/usr/bin/env python3 import socket import sys from concurrent.futures import ThreadPoolExecutor COMMON_PORTS = { 21: "ftp", 22: "ssh", 23: "telnet", 25: "smtp", 53: "dns", 80: "http", 110: "pop3", 143: "imap", 443: "https", 445: "smb", 1433: "mssql", 1521: "oracle", 3306: "mysql", 3389: "rdp", 5432: "postgresql", 6379: "redis", 8080: "http-proxy", 8443: "https-alt", 9200: "elasticsearch", 27017: "mongodb" } def scan_port(host, port, timeout=2.0): try: with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s: s.settimeout(timeout) if s.connect_ex((host, port)) == 0: try: service = socket.getservbyport(port) except OSError: service = COMMON_PORTS.get(port, "unknown") return port, "open", service except Exception: pass return port, "closed", None def main(host, ports=None): if ports is None: ports = list(COMMON_PORTS.keys()) print(f"正在扫描 {host} ...") with ThreadPoolExecutor(max_workers=20) as executor: results = list(executor.map(lambda p: scan_port(host, p), ports)) open_ports = [(p, s, svc) for p, s, svc in results if s == "open"] if not open_ports: print("未发现开放的常见端口。") else: print("开放的端口:") print(f"{'端口':<10}{'服务':<20}") for port, _, service in open_ports: print(f"{port:<10}{service:<20}") if __name__ == "__main__": if len(sys.argv) < 2: print("用法: python port_scan.py <host> [port1,port2,...]") sys.exit(1) host = sys.argv[1] ports = None if len(sys.argv) >= 3: ports = [int(p) for p in sys.argv[2].split(",")] main(host, ports)

这个脚本写得很朴素,但它解决了一个实际问题:AI 无法自己建立 socket 连接,它必须借助外部脚本来获取真实数据。扫描结果返回给 AI 后,AI 再结合 services_map.yaml 里的端口服务映射,去判断哪些服务是高价值审计目标。

第二个重要的脚本是scripts/config_collect.py,用于在本地主机上采集安全配置项。它做的不是攻击性的探测,而是防御性的自查,非常适合“自有资产审计”场景。

#!/usr/bin/env python3 import subprocess import platform import json def run_cmd(cmd): try: result = subprocess.run(cmd, shell=True, capture_output=True, text=True, timeout=10) return result.stdout.strip() except Exception as e: return f"执行失败: {e}" def collect_linux_config(): checks = { "操作系统版本": run_cmd("cat /etc/os-release"), "内核版本": run_cmd("uname -r"), "SSH端口": run_cmd("grep '^Port' /etc/ssh/sshd_config"), "SSH根登录": run_cmd("grep '^PermitRootLogin' /etc/ssh/sshd_config"), "SSH密码认证": run_cmd("grep '^PasswordAuthentication' /etc/ssh/sshd_config"), "空密码账户": run_cmd("awk -F: '($2 == \"\") {print $1}' /etc/shadow"), "近期登录日志": run_cmd("last -n 10"), "开放监听端口": run_cmd("ss -tlnp"), } return checks def main(): system = platform.system() print(f"[*] 目标系统: {system}") if system == "Linux": data = collect_linux_config() else: data = {"message": "当前版本仅支持 Linux 系统的配置采集。请手动检查其他系统。"} print(json.dumps(data, ensure_ascii=False, indent=2)) if __name__ == "__main__": main()

这里有一个细节值得展开说:这个脚本用的是ss -tlnp而非老旧的netstat,在较新的 Linux 发行版上,netstat默认不安装,AI 调用脚本时如果遇到命令不存在会中断流程。用ss可以避免这个坑。这是我在实际调试中踩过的一个非常具体的坑,后面“常见问题”部分我会再细说。

3.4 数据文件:把风险定级与基线检查项变成 AI 可检索的“词典”

Skill 里最值钱的部分其实是 data/ 目录下的结构化数据。我把多年审计中积累的检查项和判断标准,整理成了 YAML 和 JSON 文件。这里贴出 risk_level.yaml 的部分内容:

high: description: 可被远程直接利用,或攻击成本低、影响范围大,可能造成敏感数据泄露或系统完全受控的问题。 typical_examples: - 远程代码执行漏洞 - 存在已知公开利用的严重漏洞 - 敏感数据接口未授权访问 - 默认管理员口令 action: 必须立即修复,建议在 24 小时内完成处置并复查。 medium: description: 利用条件受限,或需要一定前提条件才能触发的安全问题。 typical_examples: - 使用已知弱加密套件 - 服务版本存在中风险 CVE 但暂无公开利用 - 配置信息泄露但未涉及账户密码 - 缺少安全响应头 action: 应在 1 至 2 周内完成加固。 low: description: 单一影响较小,或需要物理接触/高权限前提才能利用的问题。 typical_examples: - 信息泄露风险较低 - 未达到基线要求但不直接影响业务安全的配置项 - 日志留存周期不足 action: 建议在下一次常规维护周期内优化。 info: description: 不构成风险,但有助于完善资产台账和安全基线的观察项。 typical_examples: - 开放了非业务必需端口 - TLS 证书即将到期 - 使用了较老的软件版本但已无已知漏洞 action: 建议记录在案,纳入后续运维计划。

写这个文件时我特别注意了一点:不仅要给等级定义,还要给“典型例子”和“处置时限”。因为 AI 在判断风险等级时,如果只有抽象的定义,很容易出现同一个漏洞今天判 high 明天判 medium 的摇摆。给出一组具体例子之后,相当于给了 AI 锚点,输出稳定性会好很多。

services_map.yaml 则是把常见端口和服务名对应起来,方便 AI 在拿到信息收集结果后快速生成服务清单:

port_service_map: 22: openssh 21: ftp 25: smtp 53: dns 80: http 443: https 445: smb 873: rsync 3306: mysql 5432: postgresql 6379: redis 8080: http_proxy 8443: https_alt 9200: elasticsearch 11211: memcached 27017: mongodb

3.5 实操场景:带着 AI 走一遍小规模审计

写完了设计,我拿一个模拟环境实际跑了一遍流程,这里记录一下真实会话的大致过程。

第一步,我给 AI 设置了任务:“请帮我对内网测试环境 192.168.1.10 做一次安全审计,目标是自有测试服务器,已获得授权,审计边界为 Web 服务和中间件,时间不限,禁止做暴力破解。”

AI 按照 SKILL.md 的流程,先读了 prompts/scope.md,然后复述确认:目标 192.168.1.10,授权已确认,审计边界为 Web 服务和中间件,禁止暴力破解。它接着问我:“请确认该系统上运行的 Web 服务器和中间件是否为本次审计的主要对象?是否需要包含操作系统底层的配置核查?”这一步它严格遵守了“范围不清晰就提问”的原则。

我补充说明:“包含操作系统层配置核查。”然后它进入阶段二,调用了 port_scan.py 对目标进行扫描。扫描结果显示 22、80、443、3306、8080 端口开放。AI 结合 services_map.yaml 生成资产清单,并给出初步判断:80/443 提供 Web 服务,3306 是 MySQL,8080 疑似管理后台或其他 Web 服务。

再往下,它读取 baseline.md 和 config_collect.py,对操作系统进行了配置采集。这里有个环节值得注意,我在测试机的 sshd_config 里故意留了一个 PermitRootLogin yes 的隐患。AI 在拿到配置采集结果后,直接对照 baseline_cis.yaml 里的 SSHD 检查项,把“SSH 允许 root 直接登录”标记为基线不通过,风险等级定为 high,理由是攻击者一旦获得 SSH 凭据即可直接以最高权限登录。

最后进入脆弱性分析阶段,AI 从 fingerprint 中识别出 HTTP 服务版本是 nginx/1.18.0,并在 cve_cache.json 中检索到了对应版本的一个中危信息泄露问题。它很严谨地标注了“证据:HTTP 响应头 Server 字段显示 nginx/1.18.0,与缓存记录中的受影响版本匹配”,没有编造任何不存在的漏洞编号。

整个流程跑下来,报告输出的格式基本符合我预设的模板。虽然个别措辞还需要人工润色,但整体框架和风险判断的准确度已经相当能打。

4. 调试过程中的三大坑:这些问题你可能也会遇到

4.1 上下文污染导致流程“跑飞”

我第一次调试时踩的最大的坑,是 AI 在执行完阶段一之后,直接蹦到阶段四,跳过了服务版本识别和基线核查。原因在于我最初的 SKILL.md 把流程描述得太“宽松”,AI 觉得信息已经够多了,就自行跳步。

解决办法有两个。一是在 SKILL.md 里把阶段之间的依赖关系写死,明确要求“每完成一个阶段必须输出阶段结果并等待用户确认”;二是在每个子 prompt 的开头加上一段“前置检查”,规定只有满足前置条件才能开始本阶段。比如 recon.md 开头就写着:“在本阶段开始前,必须已经由用户确认了审计范围。若未确认,请先返回阶段一。”

这类问题在任何一个复杂的 Skill 里都会出现,因为大模型的“跳跃联想”能力太强了。给它一条清晰的“铁轨”,磨平跳步的倾向,是一个合格的 Skill 必须做到的基本功。

4.2 命令缺失或权限不足,脚本跑一半就挂了

我在调试 config_collect.py 时,第一次在精简版 CentOS 容器里执行,脚本直接报了sh: netstat: command not found。这就是我刚才提到的那个坑。后来我把脚本里的netstat替换成ss,又把ifconfig替换成ip addr,才算稳定下来。

另外一个高频问题是执行权限。AI 调用脚本时,如果当前用户没有 sudo 权限,很多配置读取会失败。我的处理方案是在脚本里对每个检查项做异常捕获,失败时返回“无法读取(可能需要 root 权限)”,而不是让整个脚本崩溃。这样 AI 至少能知道“这个项没查到,原因可能是权限”,不至于在报告里留下一条虚假的“合规”结论。

4.3 风险等级判定不稳定,同样的发现两次结论不同

一开始我在 risk_level.yaml 里只有抽象的等级定义,结果测试时 AI 把同一个“缺少 CSP 响应头”问题,一次判 high,一次判 medium。后来我加入了“典型例子”字段,并在 vulnerability.md 里规定:AI 在判定风险等级时,必须先在 risk_level.yaml 中查找是否存在匹配的典型例子,有则直接采用,无则需给出书面理由。

这个约束加上之后,判定稳定性好了很多。这也让我意识到一个问题:在做 AI 技能开发时,你写下的每一条规则,本质上都是在对抗模型的熵增倾向。规则越具体,输出越可控。

为了方便排查问题,我在调试过程中会习惯性保存每次完整会话的日志文件。如果你也在做类似的 Skill,这里强烈建议:每一次让 AI 跑完整个流程后,把对话记录存下来,命名成类似20250115_siteA_audit.md的格式。出了问题时,回看日志比重新跑一遍效率高得多,而且这些日志本身就是未来优化 prompt 的绝佳素材。

5. 从 security-audit-skill 延伸出去:Skill 开发通用的几个建议

5.1 Skill 的“最小可用版本”思维

很多人一上来就想把 Skill 写成一个功能齐全的企业级产品,结果往往陷入长期开发、迟迟不能上手的状态。我的建议是:先写一个 200 行的 SKILL.md 和两个最核心的脚本,跑通一个简单场景,然后再逐步迭代。Skill 开发的本质和做产品一样——MVP(最小可行产品)永远是第一步。

以 security-audit-skill 为例,你的 MVP 可以只包含:角色定义 + 阶段一范围确认 + 阶段二端口扫描 + 阶段五报告模板。跳过基线和漏洞分析,先让整个链路在端到端场景下跑通。跑通之后再加配置核查,再加漏洞数据,最后再打磨风险定级逻辑。我在第二轮迭代时才加了 config_collect.py 和 baseline_cis.yaml,效果比一开始想全部塞进去时顺畅得多。

5.2 让 AI “先说结论,再摆证据”

我在整个 Skill 的输出格式里反复使用了“先结论后证据”的模板。这种做法有几个好处:第一,用户阅读体验好,能快速抓住重点;第二,对 AI 本身也有引导作用——它必须先形成一个判断,然后再为这个判断找依据,而不是先罗列一堆数据最后给个模糊的结论。这个技巧不止适用于安全审计,几乎所有分析类的 Skill 都适用。

5.3 把个人经验变成“可复现资产”

最后我想多说一句。这一轮 AI Skill 的热潮,本质上是把过去只能存在人脑里的经验,变成可复制、可分发、可迭代的文件。security-audit-skill 对我来说不只是一个工具,它更是我这些年做安全审计的方法论沉淀。每次写完一个模块,都像把自己的某一个判断习惯“外置”到了电子文档里,这种成就感是纯接项目无法比拟的。

如果你也打算做自己的 Skill——不管是安全审计、会议纪要、PPT 生成、论文写作、代码审查还是前端开发——我的建议是:先整理你自己日常工作中最高频、最套路化的那个环节,然后像产品经理一样问自己:这件事的输入是什么?输出是什么?中间有哪些判断节点?判断标准是什么?把这些问题的答案写下来,你的 Skill 已经成功了一半。

我在安全审计这个 Skill 上踩过的坑、总结的办法,基本都浓缩在上面的内容里了。最后再分享一个小细节:写 Skill 的时候,尽量多用“能读文件就绝不口头告诉你”的原则。AI 一旦习惯从文件里读指令,而不是在对话里零零碎碎地接收指令,它的稳定性和一致性会有质的提升。这也是我和这个 Skill 磨合了很久之后,最深的一点体会。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询