目录一、渗透准备1、下载安装cursor2、明确需求3、修改skills文档二、AI生成web靶场1、index.php2、upload_vuln.php3、upload_secure.php三、渗透实战1、不安全版本2、安全版本本文以upload文件上传靶场为例讲解如何使用大模型自动化生成靶场渗透源码聚焦两大核心场景——存在大小写绕过黑名单风险的脆弱场景与完成安全加固的防御场景系统讲解大模型自动化渗透环境的构建方法、核心skills设计逻辑深入剖析两个场景下的代码审计要点、渗透测试方法与安全加固方案全程贯穿孙子兵法“知己知彼百战不殆”的核心思想让渗透测试与安全防御的过程成为对这一古老谋略的现代践行最终完成的靶场效果如下所示。一、渗透准备首先了解本文的核心搭建什么样的靶场用于渗透测试。我这篇文章的核心是搭建一个“攻防一体的upload靶场”upload文件上传的渗透与防御本质上就是“知彼”与“知己”的博弈渗透者通过“知彼”找到靶场的安全风险点如大小写绕过黑名单通过“知己”运用合适的渗透技巧突破防御防御者通过“知彼”了解渗透者的攻击手段如大小写绕过方法通过“知己”弥补自身代码与配置的短板实现安全加固。这种博弈逻辑与《孙子兵法》中“先察后战”的谋略高度契合也是本文实践的核心指导思想。传统的渗透环境构建依赖人工配置需手动搭建PHP运行环境、编写upload上传代码、配置服务器参数过程繁琐、耗时较长且容易出现配置错误故而目前基本上都是下载现成的靶场进行渗透。随着大模型技术的发展利用大模型自动化构建渗透环境成为提升渗透测试效率、快速“知彼”的关键手段——大模型可根据用户需求自动生成靶场代码、配置运行环境、模拟靶场场景甚至预判潜在风险可快速掌握靶场的核心特征为后续的渗透测试奠定基础。1、下载安装cursor这里我以cursor为例大家用各自的擅长的大模型即可。下载并安装cursor如下图所示。安装cursor后按ctrlshiftL打开大模型我们的目标是输入skills让其自动化构建靶场。2、明确需求针对upload文件上传PHP靶场大模型自动化构建的核心目标很简单快速生成两个可以自由切换的场景脆弱场景有大小写绕过黑名单风险加固场景做好安全加固能抵御大小写绕过等攻击确保靶场的PHP运行环境、上传功能、不安全场景包含大小写绕过风险和真实的网站应用差不多同时提供清晰的代码结构和运行说明让我们不用手动配置环境就能直接开展代码审计和渗透测试。这里呢我们需要将需求更加细化比如我这里会细化如下几点要求使其给予我细化版需求生成第一版skills1 自动生成PHP上传代码包含黑名单验证逻辑能切换脆弱场景和加固场景2确定PHP运行环境比如集成Apache或者Nginx、PHP版本为7.4开启文件上传权限3自动生成场景切换脚本方便我们对比两个场景的差异4要求大模型可以自动生成靶场说明文档讲清楚靶场的核心风险、运行方法、测试重点帮我们快速了解靶场情况。需求生成skills 创建一个PHP文件上传网站用于网络安全教育学习。 包含两个版本 1. 漏洞版本 - 展示大小写绕过漏洞 2. 安全版本 - 修复后的加固代码 技术要求 - 使用PHP 7.4 - 简单的HTML上传界面 - 仅允许jpg/png/gif图片上传 - 漏洞版本仅检查文件扩展名小写形式可被.PHP、.Php等绕过 - 安全版本使用strtolower() 严格MIME类型检查 重命名文件 - 包含详细注释说明漏洞原理和修复方法 输出结构 - index.php主页面可切换漏洞/安全模式 - upload_vuln.php漏洞版处理程序 - upload_secure.php安全版处理程序 - README.md使用说明和漏洞解释Skills就是大模型的“工具箱”每个skill对应一项具体任务比如生成代码、配置环境、切换场景。针对upload文件上传PHP靶场。将如上需求发给cursor等待cursor返回出版skills文件如下图所示。3、修改skills文档大模型首先会解析我们输入的需求提取关键信息upload文件上传、PHP靶场、大小写绕过黑名单、安全加固、两个场景对比。结合网络安全的相关知识大模型会明确我们的核心需求——不只是要一个能运行的上传靶场更重要的是要有两个场景可以对比方便我们学习代码审计、渗透方法和加固修复而且靶场的不安全场景要和真实网站差不多。这时候大模型返回给我们的skills我们不能看都不看就直接用我们需要基于此进行修改以让大模型后续可以基于skills生成符合我们需求的php靶场。我们先来看看大模型生成的第一个版本的skills。--- name: php-upload-vuln-lab description: - Builds a minimal PHP 7.4 educational file-upload lab with vulnerable and hardened variants, HTML UI, mode switching, upload directory hardening via .htaccess, and README documentation. Use when the user asks for a file upload vulnerability lab, upload bypass education, case-sensitive extension bypass demos, or secure vs insecure PHP upload handling for cybersecurity training in an isolated authorized environment only. --- # PHP File Upload Vulnerability Lab (Education) ## Scope and ethics - Intended **only** for authorized cybersecurity education (private lab, VM, classroom). Do not deploy vulnerable code to the public internet or production. - Clearly label the vulnerable path as **intentionally unsafe** in UI and README. ## When the user requests this lab Deliver this **exact file set** (unless they specify otherwise): | File | Role | |------|------| | index.php | Simple HTML upload UI; **toggle** between vuln and secure mode (e.g. query param ?modevuln / ?modesecure or radio same page). Forms POST to the correct handler. | | upload_vuln.php | Vulnerable upload handler (see below). | | upload_secure.php | Hardened upload handler (see below). | | README.md | Setup (PHP 7.4, local server), safe usage, **vulnerability explanation**, **fix summary**, and how to verify each mode. | Target runtime: **PHP 7.4**. ## Vulnerable version (upload_vuln.php) - Allow only images by **extension list** intent: jpg, jpeg, png, gif. - **Intentional flaw**: validate extension using only a **lowercase comparison** of the *original* filename extension (e.g. compare pathinfo($name, PATHINFO_EXTENSION) after strtolower() **only on the comparison side** while still accepting the raw upload name—or equivalently, reject only when lowercase extension is not in the list but **fail to normalize the stored filename**, so .PHP / .Php slip through). Goal: demonstrate **case-based blacklist/bypass** when validation does not normalize before decision storage. - Use **detailed comments** in code explaining: why case matters on case-preserving filesystems / how ApachePHP may still execute .Php depending on config; difference between **display extension** and **stored name**. ## Secure version (upload_secure.php) - Normalize extension decision with **strtolower()** on the extension used for validation. - Add **strict content check**: prefer finfo_open(FILEINFO_MIME_TYPE) / finfo_file() on the temp upload path; allow only image MIME types aligned with jpg/png/gif (e.g. image/jpeg, image/png, image/gif). Reject unknown/broad types. - **Rename** stored files: random name forced safe extension (e.g. .jpg), never trust original basename for the final path. - Comment briefly: MIME can be spoofed; this is **defense in depth** alongside extension checks, size limits, and non-executable upload directory. ## Upload directory and .htaccess - Use a dedicated directory (e.g. uploads/). Ensure PHP writes it (document chmod in README for lab use). - .htaccess in **that directory** should disable script execution, e.g. php_flag engine off where supported, and/or RemoveHandler / RemoveType / FilesMatch patterns appropriate for Apache. Note in README: effectiveness depends on **Apache AllowOverride**; other stacks (nginx) need different config—keep README honest. ## index.php UI - Minimal HTML: file input, submit, visible **mode indicator** (vuln vs secure). - CSRF not required for a local lab unless user asks; mention in README that real apps need sessions/CSRF. ## README.md contents - How to run (php -S localhost:8080 or Apache vhost). - **Attack narrative** for vuln mode (e.g. upload shell.PHP). - **Mitigations** list for secure mode. - **Legal/ethical** disclaimer: lab only, authorized use. ## Implementation notes for the agent - Keep code short and readable; prioritize teaching comments over features. - Do not add unrelated vulnerabilities unless requested. - If the user wants nginx/IIS, add a short appendix instead of bloating SKILL.md (use reference.md).最初我就直接拿这个skills直接生成靶场但是发现大小写绕过使用的白名单检查虽然代码仍有大小写绕过风险但是这个问题会导致严重偏离我的期望因为白名单大小写绕过没有意义我们是无法渗透成功的。于是我们需要对skills进行修改告知大模型靶场需要使用黑名单大小写绕过而且在Windows环境中搭建其中web服务是使用Nginx服务启动的最终我修改后的skills如下所示。--- name: php-upload-vuln-lab description: - Builds a PHP 7.4 file upload training lab with vulnerable and secure modes. The vulnerable mode demonstrates case-sensitive PHP blacklist bypass (.php blocked but .PHP/.Php/.pHP bypass). The secure mode uses strtolower() extension normalization, strict finfo MIME validation, random file renaming, and nginx-compatible guidance without .htaccess. Use when the user requests a file upload vulnerability lab, secure-vs-vulnerable comparison, or upload bypass education in an authorized isolated environment. --- # PHP 文件上传漏洞学习靶场 Skill无 .htaccess 版本 ## 目标 生成一个用于网络安全教育学习的 PHP 文件上传靶场包含 1. 漏洞版本upload_vuln.php演示黑名单大小写绕过 2. 安全版本upload_secure.php修复后的加固实现 仅用于授权实验环境本地/课堂/靶场禁止用于公网或生产环境。 --- ## 交付文件结构必须 text index.php upload_vuln.php upload_secure.php README.md 注意本 Skill 明确不生成 .htaccess默认面向 nginx如 phpstudynginx环境。 技术约束必须满足 PHP 7.4 简单 HTML 上传界面 页面提示“仅允许 jpg/png/gif 图片上传” 漏洞版仅拦截小写 php不做大小写统一可被 .PHP/.Php/.pHP 绕过 安全版strtolower() finfo 严格 MIME 随机重命名 代码有清晰注释说明漏洞原理与修复方案 所有页面统一 UTF-8 编码避免中文乱码 兼容 phpstudynginx避免上传后直接访问受限目录导致 403 文件生成规范 1) index.php 必须实现 通过 ?modevuln 和 ?modesecure 切换模式 根据模式设置表单 action vuln - upload_vuln.php secure - upload_secure.php 页面包含 当前模式标识 “仅允许 jpg/png/gif 图片上传”提示 风险说明漏洞模式为故意不安全代码 meta charsetUTF-8 可选显示安全模式上传成功提示如 ?uploaded1 2) upload_vuln.php漏洞版 必须体现漏洞点 $extension pathinfo($originalName, PATHINFO_EXTENSION); if ($extension php) { exit(禁止上传 php 文件); } 要求 不使用 strtolower()故意保留漏洞 清晰注释说明绕过结果 test.php 被拦截 test.PHP / test.PhP / test.pHP 可绕过 故意不做 MIME 校验与重命名用于教学对照 包含基础异常处理请求方法、上传失败、目录不存在等 输出统一 UTF-8 3) upload_secure.php安全版 必须实现加固 扩展名统一小写 $extension strtolower(pathinfo($originalName, PATHINFO_EXTENSION)); 扩展名白名单 仅允许 jpg/png/gif MIME 严格校验 用 finfo_open(FILEINFO_MIME_TYPE) finfo_file() 仅允许 image/jpeg、image/png、image/gif 随机重命名保存 bin2hex(random_bytes(16)) . . . $extension 上传成功后建议 header(Location: index.php?modesecureuploaded1); 避免直接输出上传目录链接减少 nginx 403 误解 输出统一 UTF-8 README 要求必须 README.md 必须包含 项目简介漏洞版 vs 安全版 环境要求PHP 7.4推荐 phpstudynginx 目录结构无 .htaccess 启动方式 漏洞原理黑名单大小写绕过 修复说明strtolower MIME 重命名 nginx 说明 不使用 .htaccess 需在 nginx 配置中限制上传目录脚本执行 编码说明 文件保存为 UTF-8无 BOM 响应头 charsetUTF-8 法律与伦理声明仅授权学习 nginx 安全提示写入 README 必须提醒用户 代码质量要求 所有 PHP 文件 declare(strict_types1); 变量命名清晰 错误提示友好且不泄露系统路径 注释简洁明确 代码可直接运行 触发示例供用户调用 当用户说以下请求时应用本 Skill “创建 PHP 文件上传漏洞靶场不要 .htaccess” “做一个 nginx 场景的上传漏洞和修复对照” “演示 .PHP 大小写绕过并给安全版” 安全边界 只生成教学用途代码 不生成未授权攻击脚本 强调授权、隔离、合法使用二、AI生成web靶场源码给出大模型指令使其生成Web靶场具体指令为“请根据 php-upload-vuln-lab Skill在当前项目根目录生成完整靶场创建 index.php、upload_vuln.php、upload_secure.php、uploads/和 README.md严格按照 Skill 里描述的“php 黑名单大小写绕过”漏洞版和加固版实现。”1、index.php项目的主页面提供用户界面和功能切换。包含两个模式选项不安全模式和安全模式。用户可通过URL参数 ?modevuln 或 ?modesecure 切换不同的文件上传处理逻辑。页面显示上传表单引导用户选择文件并提交根据选择的模式调用对应的处理脚本是整个教学靶场的入口点和用户交互界面。?php declare(strict_types1); /** * PHP 文件上传教学靶场 * - ?modevuln 漏洞模式大小写绕过黑名单 * - ?modesecure 安全模式加固 */ $mode isset($_GET[mode]) ? (string)$_GET[mode] : vuln; if ($mode ! secure) { $mode vuln; } $formAction $mode secure ? upload_secure.php : upload_vuln.php; $pageTitle $mode secure ? 安全模式加固 : 漏洞模式故意不安全; ? !DOCTYPE html html langzh-CN head meta charsetUTF-8 meta nameviewport contentwidthdevice-width, initial-scale1.0 titlePHP 文件上传教学靶场/title style body { font-family: Arial, sans-serif; max-width: 820px; margin: 40px auto; padding: 0 16px; color: #222; } .box { border: 1px solid #ddd; border-radius: 8px; padding: 18px; margin-bottom: 18px; background: #fafafa; } .warning { background: #fff3cd; border-color: #ffe69c; color: #856404; } .mode-links a { margin-right: 14px; } .current { font-weight: bold; color: #c62828; } button { padding: 8px 16px; cursor: pointer; } code { background: #f4f4f4; padding: 2px 6px; border-radius: 4px; } .ok { color: #0f7b0f; font-weight: bold; } /style /head body h1PHP 文件上传教学靶场/h1 div classbox warning strong说明/strong仅用于授权的本地/靶场/课堂环境禁止部署到公网或生产环境。 /div div classbox h2模式切换/h2 div classmode-links a href?modevuln class?php echo $mode vuln ? current : ; ?漏洞模式/a a href?modesecure class?php echo $mode secure ? current : ; ?安全模式/a /div p当前模式strong?php echo htmlspecialchars($pageTitle, ENT_QUOTES, UTF-8); ?/strong/p ?php if (isset($_GET[uploaded]) $mode secure): ? p classok安全模式上传成功已保存并重命名。/p ?php endif; ? /div div classbox h2上传文件/h2 p系统提示strong仅允许 jpg / png / gif 图片上传/strong/p p strong漏洞模式教学点/strong仅做「php 黑名单」且只拦截小写 codephp/code 未统一大小写因此 code.PHP/code / code.Php/code / code.pHP/code 可绕过。 /p form action?php echo htmlspecialchars($formAction, ENT_QUOTES, UTF-8); ? methodpost enctypemultipart/form-data input typefile namefile required button typesubmit上传/button /form /div /body /html2、upload_vuln.php漏洞版本的文件上传处理脚本用于教学演示文件上传安全风险。支持文件上传功能但存在多个安全问题仅拦截小写php扩展名可被大小写绕过、未进行MIME类型检查、直接使用原始文件名保存、缺少文件内容验证。当用户上传文件时仅进行基本的错误检查然后直接保存到uploads目录允许上传恶意文件如WebShell演示了不安全的文件上传实现方式。?php declare(strict_types1); /** * 漏洞版上传处理脚本仅用于教学 * * 需求对齐 * - 漏洞版本仅检查文件扩展名的小写形式可被 .PHP/.Php 等绕过 * * 漏洞实现 * - 只拦截扩展名严格等于小写 php * - 不做 strtolower() 统一大小写 * - 因此 .PHP/.Php/.pHP 等不会命中黑名单 * * 注意 * - 页面提示“仅允许 jpg/png/gif 图片上传”只是提示 * - 漏洞版后端故意不做真正的图片白名单与 MIME 检测用于教学对照。 */ const UPLOAD_DIR __DIR__ . /uploads; header(Content-Type: text/html; charsetUTF-8); if ($_SERVER[REQUEST_METHOD] ! POST) { http_response_code(405); echo 仅允许 POST 请求。a hrefindex.php?modevuln返回/a; exit; } if (!isset($_FILES[file]) || !is_array($_FILES[file])) { http_response_code(400); echo 未收到上传文件。a hrefindex.php?modevuln返回/a; exit; } $file $_FILES[file]; $errorCode (int)($file[error] ?? UPLOAD_ERR_NO_FILE); if ($errorCode ! UPLOAD_ERR_OK) { http_response_code(400); echo 上传失败错误码 . $errorCode . 。a hrefindex.php?modevuln返回/a; exit; } $tmpPath (string)($file[tmp_name] ?? ); $originalName (string)($file[name] ?? ); if ($tmpPath || !is_uploaded_file($tmpPath)) { http_response_code(400); echo 无效的临时文件。a hrefindex.php?modevuln返回/a; exit; } if (!is_dir(UPLOAD_DIR)) { http_response_code(500); echo 上传目录不存在请先创建 uploads 目录并确保可写。a hrefindex.php?modevuln返回/a; exit; } $extension (string)pathinfo($originalName, PATHINFO_EXTENSION); /** * 漏洞点只拦截小写 php * - test.php - 拒绝 * - test.PHP - 绕过 * - test.PhP - 绕过 * - test.pHP - 绕过 */ if ($extension php) { http_response_code(400); echo 禁止上传 php 文件漏洞版仅拦截小写 php可被大小写绕过。a hrefindex.php?modevuln返回/a; exit; } // 漏洞版故意不做 MIME 检测、不重命名直接使用原始文件名保存 $saveName basename($originalName); $destination UPLOAD_DIR . / . $saveName; if (!move_uploaded_file($tmpPath, $destination)) { http_response_code(500); echo 文件保存失败。a hrefindex.php?modevuln返回/a; exit; } echo !DOCTYPE htmlhtml langzh-CNheadmeta charsetUTF-8title漏洞模式上传结果/title/headbody; echo h2漏洞模式上传成功/h2; echo p提示页面写着“仅允许 jpg/png/gif 图片上传”但漏洞版后端仅做了错误的 php 黑名单检查。/p; echo p文件名code . htmlspecialchars($saveName, ENT_QUOTES, UTF-8) . /code/p; echo p保存路径codeuploads/ . htmlspecialchars($saveName, ENT_QUOTES, UTF-8) . /code/p; echo pa hrefindex.php?modevuln返回漏洞模式/a/p; echo /body/html;3、upload_secure.php安全版本的文件上传处理脚本用于教学演示安全的文件上传实现。实现了完整的安全措施使用 strtolower() 统一扩展名大小写、严格的扩展名白名单仅允许jpg/png/gif、使用 finfo 检测真实MIME类型、随机重命名保存文件。当用户上传文件时会进行多重验证确保仅允许安全的图片文件上传展示了文件上传功能的最佳安全实践。?php declare(strict_types1); /** * 安全版上传处理脚本PHP 7.4 * * 加固方法 * 1) strtolower() 统一扩展名大小写 扩展名白名单jpg/png/gif * 2) finfo_open(FILEINFO_MIME_TYPE) finfo_file() 检测真实 MIME * 3) 随机重命名保存不信任用户原始文件名 * * 兼容 phpstudy nginx * - 上传成功后不直接输出 /uploads/xxx.jpg 的链接避免 nginx 对 uploads 的访问规则导致 403 * - 直接跳回 index.php?modesecureuploaded1 */ const UPLOAD_DIR __DIR__ . /uploads; const ALLOWED_EXTENSIONS [jpg, png, gif]; const ALLOWED_MIME_TYPES [image/jpeg, image/png, image/gif]; header(Content-Type: text/html; charsetUTF-8); if ($_SERVER[REQUEST_METHOD] ! POST) { http_response_code(405); echo 仅允许 POST 请求。a hrefindex.php?modesecure返回/a; exit; } if (!isset($_FILES[file]) || !is_array($_FILES[file])) { http_response_code(400); echo 未收到上传文件。a hrefindex.php?modesecure返回/a; exit; } $file $_FILES[file]; $errorCode (int)($file[error] ?? UPLOAD_ERR_NO_FILE); if ($errorCode ! UPLOAD_ERR_OK) { http_response_code(400); echo 上传失败错误码 . $errorCode . 。a hrefindex.php?modesecure返回/a; exit; } $tmpPath (string)($file[tmp_name] ?? ); $originalName (string)($file[name] ?? ); if ($tmpPath || !is_uploaded_file($tmpPath)) { http_response_code(400); echo 无效的临时文件。a hrefindex.php?modesecure返回/a; exit; } if (!is_dir(UPLOAD_DIR)) { http_response_code(500); echo 上传目录不存在请先创建 uploads 目录并确保可写。a hrefindex.php?modesecure返回/a; exit; } $extension strtolower((string)pathinfo($originalName, PATHINFO_EXTENSION)); if (!in_array($extension, ALLOWED_EXTENSIONS, true)) { http_response_code(400); echo 仅允许 jpg / png / gif 图片上传。a hrefindex.php?modesecure返回/a; exit; } // MIME 检测不要使用 $_FILES[type]不可信 $finfo finfo_open(FILEINFO_MIME_TYPE); if ($finfo false) { http_response_code(500); echo 无法初始化 MIME 检测。a hrefindex.php?modesecure返回/a; exit; } try { $mimeType finfo_file($finfo, $tmpPath); } finally { finfo_close($finfo); } if ($mimeType false || !in_array($mimeType, ALLOWED_MIME_TYPES, true)) { http_response_code(400); echo 文件类型不合法MIME . htmlspecialchars((string)$mimeType, ENT_QUOTES, UTF-8) . 。a hrefindex.php?modesecure返回/a; exit; } // 随机重命名保存 $randomName bin2hex(random_bytes(16)) . . . $extension; $destination UPLOAD_DIR . / . $randomName; if (!move_uploaded_file($tmpPath, $destination)) { http_response_code(500); echo 文件保存失败。a hrefindex.php?modesecure返回/a; exit; } // 不输出 uploads 链接避免 nginx 对 uploads 的访问控制导致 403 header(Location: index.php?modesecureuploaded1); exit;三、渗透实战1、不安全版本将靶场源码放到phpstudy的源码根目录中并启动小皮的Web服务Nginx打开网站如下所示默认就是不安全版本模式选择后缀为phP的脚本文件上传。如下所示上传成功构造脚本的URL地址。http://127.0.0.1/php-upload-vuln-lab/uploads/ljn_pass6.phP访问恶意脚本如下所示渗透成功。2、安全版本打开网站进入安全模式如下所示选择后缀为phP的脚本文件上传如下所示。点击上传后提示失败具体如下所示防御成功。