Java反序列化:滥用OJDBC进行SSRF

今年ZeroNights有了一个新的区域 - Web Village。对于那些对网络安全感兴趣的人来说,这是一个特别的“轨道”。Web Village的基本思想是告诉人们典型的漏洞和攻击技巧。我以各种语言讲解了反序列化的基础知识。我想展示一些常见的模式,使序列化库很容易受到攻击。有那个介绍

在演示中,我展示了一个新的Java小工具的例子,以证明它是愚蠢的“修复”小工具或“黑名单”,而不是保护/改变反序列化库。这里我想展示一下这个例子的一些细节。

小工具是库中的一个类,用于将Java应用程序连接到RDBMS Oracle - ojdbc。实际上,这个确切的类(OraclePooledConnection)负责建立一个连接。
这个例子非常简单,因为类有一个readObject方法,目标是在反序列化过程中重建与数据库的连接。
在帖子的底部,你可以阅读代码,但没有必要,因为我们要使用它应该使用它的方式。

当我们使用一个字符串来控制一个字段(connection_url)时,这个字符串在反序列化过程中尝试连接,这意味着我们在这里有一个SSRF漏洞。
乍一看,它看起来很无用,因为Oracle的协议是二进制的。但是几年前我和Oracle DB玩过,知道客户端(和TNS协议)非常灵活。
“URL”由几个字段组成:

jdbc:oracle:thin:login / password @ // any.domain.name.here.com:8888/service_name

我认为几乎所有这些都是自我描述。
对我们来说一个重要的特性是“服务名称”字段可以包含一个非常长的值和几乎所有的ASCII符号。所以,我们可能可以与基于文本的服务进行交互。是的,在服务名称之前和之后会有二进制垃圾,但许多服务器并不关心这样的事情(“errors friendly”)。

因此,我们一步一步地创建一个序列化的对象,并将特定的有效内容作为服务名称发送给应用程序。应用程序运行“OraclePooledConnection”类的readObject,并强制应用程序连接到我们想要的任何地方并发送我们的有效负载。

所以,我的观点很清楚,班上并没有什么隐患,但是我们仍然可以误用它的功能来进行攻击。

有一个简单的PoC

PS:如果您有权限访问Oracle数据库,您可以执行相同的“SSRF攻击”,使您可以创建数据库链接。

PPS:潜在的攻击可以有所改善......当我们控制连接的“url”时,可能是我们可以窃取NetNTLM证书(因为oracle auth支持它)还是执行TNS中毒攻击?OraclePooledConnection类的readObject方法的代码

private void readObject(ObjectInputStream paramObjectInputStream)
    throws IOException, ClassNotFoundException, SQLException
  {
    paramObjectInputStream.defaultReadObject();
    this.connectionProperty = ((Hashtable)paramObjectInputStream.readObject());
    try
    {
      Properties localProperties = (Properties)this.connectionProperty.get("connection_properties");
      String str1 = localProperties.getProperty("connection_url");
      this.oracleDriver = new OracleDriver();
      Connection localConnection = this.oracleDriver.connect(str1, localProperties);
      initialize(localConnection);
      this.eventListeners = ((Hashtable)this.connectionProperty.get("event_listener"));
      this.sqlException = ((SQLException)this.connectionProperty.get("sql_exception"));
      this.autoCommit = ((String)this.connectionProperty.get("pool_auto_commit")).equals("true");
      this.closeCallback = ((OracleCloseCallback)this.connectionProperty.get("close_callback"));
      this.privateData = this.connectionProperty.get("private_data");

      Map localMap = (Map)this.connectionProperty.get("obj_type_map");
      if (localMap != null) {
        ((OracleConnection)localConnection).setTypeMap(localMap);
      }
      String str2 = localProperties.getProperty("trans_isolation");
      localConnection.setTransactionIsolation(Integer.parseInt(str2));
      str2 = localProperties.getProperty("stmt_cache_size");

      int i = Integer.parseInt(str2);
      if (i != -1)
      {
        setStatementCacheSize(i);

        str2 = localProperties.getProperty("implicit_cache_enabled");
        if ((str2 != null) && (str2.equalsIgnoreCase("true"))) {
          setImplicitCachingEnabled(true);
        } else {
          setImplicitCachingEnabled(false);
        }
        str2 = localProperties.getProperty("explict_cache_enabled");
        if ((str2 != null) && (str2.equalsIgnoreCase("true"))) {
          setExplicitCachingEnabled(true);
        } else {
          setExplicitCachingEnabled(false);
        }
      }
      this.physicalConn.setAutoCommit(((String)localProperties.get("connect_auto_commit")).equals("true"));
    }
    catch (Exception localException) {}
  }

转载请注明出处:https://www.freearoot.com/index.php/java%e5%8f%8d%e5%ba%8f%e5%88%97%e5%8c%96%ef%bc%9a%e6%bb%a5%e7%94%a8ojdbc%e8%bf%9b%e8%a1%8cssrf.html

文章来源:http://agrrrdog.blogspot.jp/2018/01/java-deserialization-misusing-ojdbc-for.html?m=1