Java 安全研究初探(下)
发布日期:2023-04-03      作者:       来源:      分享:

Java 安全研究初探(下)


Class.forName 显式导入驱动的方式在新版本已经不需要了,不过这个方式有利于让开发者理解 JDBC 使用的具体数据库驱动,一些例子如下:

  • PostgreSQL : org.postgresql.Driver

  • Oracle : oracle.jdbc.driver.OracleDriver

  • Microsoft SQL Server : com.microsoft.sqlserver.jdbc.SQLServerDriver

  • SQLite : org.sqlite.JDBC

  • H2 : org.h2.Driver

  • Apache Derby : org.apache.derby.jdbc.ClientDriver

  • MariaDB : org.mariadb.jdbc.Driver

  • IBM DB2 : com.ibm.db2.jcc.DB2Driver

  • Informix : com.informix.jdbc.IfxDriver

如果想实现自己的驱动,需要实现 java.sql.Driver 接口,其中一些关键方法有 connect、acceptsURL 等。connect 方法中会接受到传入的 URL 以及相关属性(如账号、密码)。实际上 DriverManager 查询驱动的方式也很简单,即通过循环遍历已注册的驱动 registeredDrivers,然后逐个调用其 driver.connect 方法,如果发现不为空就返回。registeredDrivers 是个列表结构,因此先添加的驱动会优先执行。

另外如果驱动中实现的有问题,且攻击者可以污染传入的 URL 或者 Property,也有可能间接造成代码执行,关于这类攻击可以参考 New Exploit Technique In Java Deserialization Attack

JMX

JMX 全称为 Java Management Extensions,即 Java 管理拓展,主要用于管理和监控 Java 程序。常见的监控资源有 CPU 占用率、线程数、JVM 内存等。下面是一些相关标准的定义:

我们常用的 JConsole、VisualVM,以及现在流行的 Spring Boot 框架中的 Spring Boot Actuator 内部都使用了 JMX 拓展,因此对其进行了解有助于我们更好地认识这些应用和框架。

组件

JMX 主要包括几个关键组件,下面分别进行介绍。

MBean,全称是 Managed Bean,类似于 Java Bean,主要用来进行消息传递。与 Java Bean 的区别是 JMX 中对这些 Bean 进行了额外的定义,兼容 JMX 标准的 MBean 才可以被加载。在 java.lang.management 中定义了许多 JDK 提供的 MBean,包括 Memory、Thread 相关的 MBean,用于传递 JVM 应用的内存和线程相关信息。我们平时使用 jconsole 去分析 Java 应用时所展现的数据大多来源于这些 MBean。

MBeanServer,主要用于 MBean 的管理,同名接口定义在 javax.management 中,包含 MBean 创建、注册以及删除等操作相关的接口。一般用户不会直接实现该接口,而是通过 MBeanServerFactory 工厂类去获取 MBeanServer 实例。通常一个 Java 虚拟机中只会有一个 MBeanServer,只有注册到 MBeanServer 中的 MBean 才能被进行管理,即能够被连接到 MBeanServer 的客户端远程访问其属性和相关方法。

Connector/Adaptor,这是直接面对客户端的组件,负责具体协议的连接或者转换。在 JMX 标准中提到,RMI Connector 是在 JMX 标准实现中唯一强制实现的协议。RMI (Remove Method Invocation) 是 Java 中的远程调用接口,其具体的传输协议可以不同,常见有以下两种:

  1. JRMP(Java Remote Method Protocol),这是 RMI 的默认传输协议,专为 Java 而开发,因此性能较好;

  2. IIOP(Internet Inter-ORB Protocol),CORBA 标准的一部分,依赖于 CORBA 类库,因此可以实现多语言传输 RMI 远程对象,更适用于跨平台开发;

除了 RMI Connector,JMX 中还定义了 Generic Connector 即通用连接器的标准。基于上文 JSR 160 提到的 JMX Remote API 来实现可配置和可插拔的连接器,包括传输协议和对象封装等接口。JMXMP,即 JMX Remote API over Message Service Protocol,就是一种通用连接器实现。客户端和服务器之间通过消息进行通信,消息可以是纯文本或二进制格式。JMXMP 支持基于 SSL/TLS 对连接进行加密,同时还有连接池、心跳等功能。

Adaptor 称为适配器,和连接器类似,主要将客户端对服务器中 MBean 的操作适配为其他协议,比如 SNMP 或者 HTTP 等。例如,Jolokia 就是一个常用的开源 JMX-HTTP 适配器,可以使远程的 JMX 客户端通过 HTTP/HTTPS 协议访问 JMX MBean。

示例

假设我们是某个服务端应用,需要对外暴露一些监控信息,这种情况下就可以自定义一个 MBean 实现。JMX 要求 MBean 首先需要是一个接口,且接口名字以 MBean 结尾,例如:

public interface DemoMBean {


String getName();

String getPassword();

void say(String what);}

一个具体的 MBean 需要实现上述接口:

class Demo implements DemoMBean {


@Override

public String getName() { return "evilpan"; }

@Override

public String getPassword() { return "jmxdemo"; }

@Override

public void say(String what) {

System.out.println(getName() + " say: " + what);

}}

为了能够被客户端访问,需要将该 MBean 的实例注册到 MBeanServer:

MBeanServer server = ManagementFactory.getPlatformMBeanServer();ObjectName userName = new ObjectName("com.evilpan:type=Foo,name=bar");server.registerMBean(new Demo(), userName);

其中 userName 是在 JMX MBean 中显示的名称,上述示例在 jconsole 的 MBeans 中查看有以下结构:

com.evilpan


└─ Foo

└─ bar

├─ Attributes

│ ├─ Password

│ └─ Name

└─ Operations

└─ say

点击 Attributes 中的 Name 和 Password 会调用对应的 getName 和 getPassword 方法来获取信息,而点击 say 可以调用对应 MBean 实例的方法,并指定相关参数。

这里是使用 jconsole attach 本地应用的方式连接 MBeanServer 的,实际应用中可以通过 RMI 协议去让客户端进行远程管理,关键代码如下:

MBeanServer server = ManagementFactory.getPlatformMBeanServer();// Register MBean ...LocateRegistry.createRegistry(7890);JMXServiceURL url = new JMXServiceurl(http://img403.hackdig.com/imgpxy.php?url=imrxmj%2F0987%3Atsohlacol%2F%2F%3Aimr%2Fidnj%2F%2F%2F%3Aimr%3Axmj%3Aecivres);JMXConnectorServer jcs = JMXConnectorServerFactory.newJMXConnectorServer(url, null, server);jcs.start();

当然,实际上 Java 本身也提供了内置的 JMX 连接器功能,可以通过命令行启动指定属性去开启,比如:

java -Dcom.sun.management.jmxremote.port=7890 \ -Dcom.sun.management.jmxremote.authenticate=false \ -Dcom.sun.management.jmxremote.ssl=false \ -cp target/classes com.example.demo.BeanTest

和上面自行添加 RMI 监听效果是一样的。 其中 RMI registry 的端口为 7890,JMXServiceURL 路径的结尾可以随意指定,但如果需要用 jconsole来进行连接,则必须使用 /jmxrmi。

实际应用中更多使用 -Dcom.sun.management.config.file 指定 JMX 相关的配置

应用启动后也可以通过 nmap 来查看对应端口信息:

$ nmap localhost -p 7890,56097 -sVC


PORT STATE SERVICE VERSION

7890/tcp open java-rmi Java RMI| rmi-dumpregistry:| jmxrmi| javax.management.remote.rmi.RMIServerImpl_Stub| @127.0.0.1:56097| extends| java.rmi.server.RemoteStub| extends|_ java.rmi.server.RemoteObject

56097/tcp open java-rmi Java RMI

上面监听的 56097 端口是实际的 JMX-RMI Connector 监听端口,被注册为 RMI Nameing Registry 中的 jmxrmi 名称。

从上面的介绍中可以看出,JMX 在 Java 应用管理和监控中的作用很大,但同时也暴露了很大的风险,如果服务端的 JMX 管理端口能被攻击者访问,就可能泄露敏感数据,或者被调用任意的 MBean 方法从而导致代码执行等危害。另外由于 RMI 是 JMX 默认的连接器,因此历史上也出现过许多针对 RMI 的攻击和反序列化漏洞,这里就先不展开了,其中相关的利用技巧和深入介绍可以参考下面的文章:

后记

写到这里,可以说对 Java 安全有了一个比较基本的了解。Java 生态历经了几十年的发展,直到今天依旧在企业级服务端应用中占有半壁江山。从文中可以看到 Java 一直致力于提供高可用、可拓展的标准,有一些标准由于设计复杂接受度不高(如 EJB),但也有很多标准从初稿到现在依然是主流(如 JNDI、JMX)。文中所介绍的几个功能应该算是 Java 初学者最先接触的技术,虽然只是冰山一角,但通过对这些技术的学习可以让我们管窥 Java EE 的全貌,也为后续针对性的研究打好基础。

来源:www.ctfiot.com/107075.html


友情链接:

返回软协官网首页

通讯地址:北京市海淀区海淀南路甲21号中关村知识产权大厦A座2层206、207室     邮政编码:100080

电话:010-62565314 刘莉    京ICP证16064523号-2    版权所有:北京软件和信息服务业协会

技术支持:中科服    内容支持:鑫网安

你知道你的Internet Explorer是过时了吗?

为了得到我们网站最好的体验效果,我们建议您升级到最新版本的Internet Explorer或选择另一个web浏览器.一个列表最流行的web浏览器在下面可以找到.