Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

Vulnerability Analysis of Thinkphp5.0, 5.1,6.x deserialization

2025-03-26 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Network Security >

Share

Shulou(Shulou.com)05/31 Report--

This article introduces Thinkphp5.0, 5.1, 6.x deserialization vulnerability analysis, the content is very detailed, interested friends can refer to, hope to be helpful to you.

Namespace

The declaration of namespaces avoids problems caused by duplicate class or function names. Use namespace to declare and switch namespaces.

/ * run result * current namespace first * current namespace second * /

Classes of the same name can be defined in different namespaces, and when there are multiple namespaces, the default is the last declared space. If you want to use a class with another namespace, you need to add a namespace before the class, and classes that directly use other namespaces will make an error.

/ / Operation result / / O%3A27%3A%22think%5Cprocess%5Cpipes%5CWindows%22%3A1%3A%7Bs%3A34%3A%22think%5Cprocess%5Cpipes%5CWindowsfiles%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A11%3A%22D%3A%2F%2Fdel.txt%22%3B%7D%7D

Line 163 of the removeFiles function, using the file_exist function to handle the $filename,file_exist function will treat the argument as a string, and the _ _ toString method can be triggered if you make $filename an object with a _ _ toString method.

The _ _ toString method of the Pivot class comes from the parent class Model, while the _ _ toString method of Model comes from the trait class Conversion

The _ _ toString chain of the Conversion class is as follows

The toArray code is too long. Intercept the useful parts as follows

In the meantime, the $relation variable comes from $this- > data [$name], and the $name variable comes from $this- > append, both of which are controllable. If you make $relation an object that has available visible methods or no visible methods but has available _ _ call methods, you can move on to the next step.

_ _ call find the Request class here, as follows

Because $this- > hook is controllable, we can easily execute to call_user_func_array. However, due to the existence of 330lines of array_unshift, the Request object is placed in the first place of $args, so we cannot execute any code here (because the parameters are uncontrollable), so we need to look again for the first function whose parameters do not affect the result to construct the available chain.

Find Request::isAjax here and track it.

Tracking input

$name from config ['var_ajax'], controllable, $data from $this- > param, also controllable.

Trace filterValue, during which call_user_func is executed ($filter, $value)

$value comes from $data in input, so it finally comes from $this- > param,$filter and gets it after calling the getFilter function.

In the meantime, $this- > filter is controllable, so $filter is controllable. Since $filter,$value is controllable, you can execute arbitrary code and look back at the pop chain again.

Windows::__destruct-- > Pivot::__toString-- > Request::__call-- > Request::isAjax-- > Request::param-- > Request::input-- > Request::filterValue-- > call_user_func

Exp

If you want to perform system ('id'), you need to control the variable to the following values

Request- > filter = "system"; Request- > param = array ('id'); Request- > hook [' visible'] = [$this, "isAjax]; Request- > config ['var_ajax'] =''; Pivot- > data = [" azhe "= > new Request ()]; Pivot- > append = [" azhe "= > [" 4ut "," 15m "]]; Windows- > files = [new Pivot ()];-- exp

TPv6.x vulnerability

POP chain Model- > _ destruct ()-- > Model- > save ()-> Model- > updateData ()-> Model- > checkAllowFields ()-> Conversion- > _ toString ()-> Conversion- > toJson ()-> Conversion- > toArray ()-> Attribute- > getAttr ()-> Attribute- > getValue ()

First look at the starting point of deserialization Model- > _ _ destruct ()

Call save when $this- > lazySave = = true and trace as follows

To call updateData, you need to bypass the first if and $this- > exists = = true

Bypass of if requires isEmpty () to return false and trigger () to return true

Trace isEmpty () and return false when $this- > data is not empty

Trace trigger (), and trigger () returns true when $this- > withEvent = = false. (PS:trigger () belongs to ModelEvent)

After bypassing, trace updateData ().

To call checkAllowFields, you need to bypass the second if. Track getChangedData () to see the acquisition of $data

When $this- > force = = true, $data is controllable and is the value of $this- > data

Track checkAllowFields (). You can already see a _ _ toString trigger point here. In addition to this trigger point, another trigger point is db ()

Track db (). The trigger point is where the string is concatenated. Just make $this- > table, $this- > name, or $this- > suffix an object with the _ _ toString method.

To execute to the trigger point, you need to bypass the second and third if of updateData, that is, $this- > field (empty by default) and $this- > schema (empty by default)

The above is the _ _ destruct chain. To sum up, the properties you need to set are as follows

Model- > lazySave = true;Model- > exists = true;Model- > withEvent = falseModel- > force = true;Model- > data is not empty Model- > name (or table, suffix) is an object

Next look at the _ _ toString chain

Conversion- > _ _ toString

Trace toArray ()

To call getAttr (), you first need to bypass if.

$data comes from $this- > data and $this- > relation. When the value of $data is not an instance of Model or ModelCollection, the first if can be passed. If you set $this- > visible, getAttr will be called on line 173, and if not set, it will be called on line 175without influence.

Follow up getAttr ()

Call getData to get $value and follow up

Follow up getRealFieldName ()

When $this- > strict = = true (also true by default), $name is returned (name is the key of $this- > data). That is, the key with the final value of $fieldName of $this- > data.

The if in line 279 returns the value of the corresponding key when the $fieldname key exists in $this- > data. So the final value of $value is $this- > data [$fieldName]

Follow up getValue ()

Line 496 of the code, $closure is completely controllable, line 497 triggers rce.

Let's first look at the parameters passed in by calling getValue (), $name, $value, and $relation, which are $this- > data's key,$this- > data's value,false, respectively.

Because $this- > withAttr [$fieldName] is controllable and $relation = = false, the program executes to line 497.

The above is the _ _ toString chain, and the contents that need to be set are summarized as follows

$this- > data = array ('azhe'= >' whoami'); $this- > withAttr = array ('azhe'= > []) the conversion class is the trait class, and you need to find the class that uses it. You can summarize it with the Pivot class context as follows: $Model- > lasySave = true;$Model- > exists = true;$Model- > withEvent = false;$Model- > force = true;$Model- > name = new Pivot (); $Model- > data = array (' azhe'= > 'whoami'); $Model- > withAttr = array (' azhe'= > 'system');

TPv5.0 vulnerability

POP chain Windows- > _ destruct ()-- > Windows- > removeFiles ()-- > Model- > _ toString-- > Model- > toJson ()-> Model- > toArray ()-> Output- > _ call-- > Output- > block-- > Output- > writeln-- > Output- > write-> Memcache- > write-> File- > set

First look at the _ _ destruct chain, thinkphp/library/think/process/pipes/Windows.php:56

Follow up removeFiles (), here is the same as TPv5.1, there are also arbitrary file deletions, no longer demonstrate

Take a look at _ _ toString chain, thinkphp/library/think/Model.php:2265

Follow up toJson ()

Follow up toArray (), too much code, intercept key parts

If $value is controllable, you can trigger _ _ call here

Because $this- > append is controllable, $name is controllable when $name is not an array and does not contain. When the code enters line 899, follow up with Loader::parseName ()

That is, $relation can be any string that is lowercase of the first letter.

In lines 900-901 of the code, we can call any method of this class (Model) and assign the result to $modelRelation

Follow up getRelationData () first.

Follow up isSelfRelation ()

Follow up with getModel (), this getModel is the class method of Relation

Its getModel also calls the getModel of $this- > query. Because $this- > query is controllable, it searches getModel () globally and finds two easy-to-use getModel.

Both getModel are $this- > model that directly returns the object, so $modelRelation- > getModel () is controllable.

You can find that $this- > parent is controllable, and if $modelRelation is also controllable, then $value is controllable. Look back at $modelRelation, which is the return value of any Model method we call, look at the method of the Model class, and find a simple and controllable method getError ()

Look further down.

$modelRelation requires the existence of a getBindAttr method, and a global search finds that this method exists only in the abstract class OneToOne, which is also a subclass of Relation. From this point of view, we need to make $modelRelation a subclass of OneToOne. Looking further down, $bindAttr is controllable

At this point, you can easily control $bindAttr to make the code execute to 912 lines.

912 lines, you can look at it this way

$item [key of $bindAttr] = $this- > parent? $this- > parent- > getAttr ($bindAttra [key]): both null,$bindAttr and $this- > parent are controllable

The subclasses of OneToOne are as follows, and $modelRelation can choose one of them.

Since we are going to use the _ _ call method of the Output class, we need to make $this- > parent the Output object

The _ _ toString chain needs to construct the following

Model- > append = array ('4ut15mcm = >' getError'); Model- > error = new BelongsTo (); / / or HasOneModel- > parent = new Output (); OneToOne- > selfRelation = false;OneToOne- > query = new ModelNotFoundException (); OneToOne- > bindAttr = array ('4ut15m'); ModelNotFoundException- > model = new Output ()

Take a look at _ _ call chain, thinkphp/library/think/console/Output.php:208

Line 212, call the block method of the current object, follow up with block ()

Follow up writeln ()

$this- > handle is controllable. Search the write method globally and find Memcache::write.

Where $this- > handler and $this- > config are controllable

Global search for set method and discovery of File::set

Because $this- > options is controllable, $expire is controllable, $name is related to Memcache- > config, semi-controllable, follow up getCacheKey ()

At this point, the path of $filename is controllable, and $name is the value of MD5 that can be determined.

The content written to the file $data consists of $value and $expire, which is uncontrollable and has a value of true. The latter is uncontrollable due to formatting the output. Follow up setTagItem ()

The code calls the set method again on 200 lines, and the write $value is the passed parameter $name, that is, the previous $filename, and the path is partially controllable. Here, you can write to shell through php pseudo protocol php://write, as follows

Php://filter/write=string.rot13/resource=

The _ _ call chain needs to construct the following

Output- > styles = ['getAttr']; Output- > handle = new Memcache (); Memcache- > handler = new File () File- > options = ['expire' = > 0,' cache_subdir' = > false, / / files that can be controlled by false are written under the default path 'prefix' = >', 'path' = >' php://filter/write=string.rot13/resource=', 'data_compress' = > false]; exp

This is the end of the vulnerability analysis on Thinkphp5.0, 5.1,6.x deserialization. I hope the above can be helpful and learn more. If you think the article is good, you can share it for more people to see.

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Network Security

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report