OWASP / pysap

pysap is an open source Python library that provides modules for crafting and sending packets using SAP's NI, Diag, Enqueue, Router, MS, SNC, IGS, RFC and HDB protocols.
https://owasp.org/www-project-core-business-application-security/
GNU General Public License v2.0
219 stars 61 forks source link

SAPCredv2 decrypt_with_header fails for TripleDES (LPS off) #36

Closed rstenet closed 3 years ago

rstenet commented 3 years ago

If CCL parameter ccl/enable_credential_uid_from_os is set to 1 ccl/enable_credential_uid_from_os = 1 the credentials are encrypted with 3des with header.

Decryption fails with ValueError: Invalid key size (256) for 3DES.

Following dirty fix solves the problem:

        key = derive_key(cred_key_fmt, blob[0:4], header.salt, username)
        if algorithm == algorithms.TripleDES:
           key = key[:24]
           header.cipher_text = header.iv[8:] + header.cipher_text
           header.iv = header.iv[:8]
joegoerlich commented 3 years ago

Hello Robert,

the parameter is supposed to affect the method how the user working with cred_v2 is determined. "On Unix/Linux operating systems the user was determined from system variable $USER which made it reasonably easy for attackers with system access to misuse the PSEs. CommonCryptoLib 8.5.15 allows to retrieve the user via system functions provided by the operating system. " (SAP note 2338952). Could you please elaborate if this indeed affects the algorithm used to encrypt the credentials defined by parameter ccl/credential_encryption_algorithm?

Thank you, Joe

rstenet commented 3 years ago

Hi Joe,

looks like it affects the algorithm. Now it is with header. ccl/credential_encryption_algorithm is 3DES by default. Have a look at the following tests. CommonCryptoLib version is 8.5.36. Credentials are for user xxxadm. Here the generated cred_v2 file cred_v2_lps_off_3_algs.zip

According sapgenpse seclogin -h there is an option -U which should be the same as configuring ccl/enable_credential_uid_from_os = 1, but in my tests it had no effect.

First generated 4 PSEs

sapgenpse gen_pse -x "Ab_1234567890" -p test1.pse "CN=PSEowner1, C=BG"
sapgenpse gen_pse -x "Ab_1234567890" -p test2.pse "CN=PSEowner2, C=BG"
sapgenpse gen_pse -x "Ab_1234567890" -p test3.pse "CN=PSEowner3, C=BG"
sapgenpse gen_pse -x "Ab_1234567890" -p test4.pse "CN=PSEowner4, C=BG"

And then the credentials

sapgenpse seclogin -x "Ab_1234567890" -p test1.pse
sapgenpse seclogin -U -x "Ab_1234567890" -p test2.pse     # no effect
sapgenpse seclogin -r -U -x "Ab_1234567890" -p test2.pse  # no effect
sapgenpse seclogin -x "Ab_1234567890" -p test3.pse        # created with just ccl/enable_credential_uid_from_os = 1
sapgenpse seclogin -x "Ab_1234567890" -p test4.pse        # added ccl/credential_encryption_algorithm = AES256

ASN1 view image

List credentials as root with USER variable set to xxxadm image

Cheers, Robert

martingalloar commented 3 years ago

Thanks folks, I might need to take a look. In my early testing I don't remember seeing something like that, but it might be that I was using the -U flag instead of changing the profile parameter. I still don't get if enabling it makes it switch to another Cipher version and what are those extra bytes.

rstenet commented 3 years ago

Hi Martin, here another 3 test

if both parameters are set with their default values there is no effect.

ccl/enable_credential_uid_from_os = 0
ccl/credential_encryption_algorithm = 3DES
sapgenpse seclogin -x "Ab_1234567890" -p test1.pse
[xxxadm@localhost sec]$ openssl asn1parse -inform DER -dump -in cred_v2
    0:d=0  hl=2 l=  85 cons: SEQUENCE
    2:d=1  hl=2 l=  83 cons: SEQUENCE
    4:d=2  hl=2 l=  18 prim: IA5STRING         :CN=PSEowner1, C=BG
   24:d=2  hl=2 l=   0 prim: IA5STRING         :
   26:d=2  hl=2 l=  30 prim: IA5STRING         :/usr/sap/XXX/D00/sec/test1.pse
   58:d=2  hl=2 l=   0 prim: IA5STRING         :
   60:d=2  hl=2 l=  25 prim: BIT STRING
      0000 - 00 12 18 93 50 51 d0 ee-94 d3 ef 1b 64 97 93 d1   ....PQ......d...
      0010 - 2c e5 84 24 f0 19 20 86-02 

Setting only ccl/credential_encryption_algorithm to AES256 leads to encryption with header

ccl/enable_credential_uid_from_os = 0
ccl/credential_encryption_algorithm = AES256
sapgenpse seclogin -x "Ab_1234567890" -p test1.pse
[xxxadm@localhost sec]$ openssl asn1parse -inform DER -dump -in cred_v2
    0:d=0  hl=3 l= 129 cons: SEQUENCE
    3:d=1  hl=2 l= 127 cons: SEQUENCE
    5:d=2  hl=2 l=  18 prim: IA5STRING         :CN=PSEowner1, C=BG
   25:d=2  hl=2 l=   0 prim: IA5STRING         :
   27:d=2  hl=2 l=  30 prim: IA5STRING         :/usr/sap/XXX/D00/sec/test1.pse
   59:d=2  hl=2 l=   0 prim: IA5STRING         :
   61:d=2  hl=2 l=  69 prim: BIT STRING
      0000 - 00 01 01 00 00 33 e0 1e-f7 5a b8 20 e6 26 60 24   .....3...Z. .&`$
      0010 - 57 47 3b f3 ba 27 c9 7b-e1 f6 31 35 73 21 89 47   WG;..'.{..15s!.G
      0020 - db 29 b1 c3 1d 3e 72 c1-f3 5c a4 49 c9 94 c0 87   .)...>r..\.I....
      0030 - a9 d4 c8 72 9f b5 cf 84-0d 4a 95 cc 00 b4 c2 4b   ...r.....J.....K
      0040 - 5d c5 94 0f 44              

Setting only ccl/enable_credential_uid_from_os = 1 leads again to encryption with header. This time 3DES is used.

ccl/enable_credential_uid_from_os = 1
ccl/credential_encryption_algorithm = 3DES # or unset which defaults to 3DES
[xxxadm@localhost sec]$ openssl asn1parse -inform DER -dump -in cred_v2
    0:d=0  hl=2 l= 113 cons: SEQUENCE
    2:d=1  hl=2 l= 111 cons: SEQUENCE
    4:d=2  hl=2 l=  18 prim: IA5STRING         :CN=PSEowner1, C=BG
   24:d=2  hl=2 l=   0 prim: IA5STRING         :
   26:d=2  hl=2 l=  30 prim: IA5STRING         :/usr/sap/XXX/D00/sec/test1.pse
   58:d=2  hl=2 l=   0 prim: IA5STRING         :
   60:d=2  hl=2 l=  53 prim: BIT STRING
      0000 - 00 01 00 01 00 40 88 06-03 89 43 b4 41 35 35 91   .....@....C.A55.
      0010 - f3 56 06 fb 33 02 58 c3-01 1d 92 92 f1 e8 e4 2f   .V..3.X......../
      0020 - c8 5b f8 f8 39 19 ff 93-c8 63 e1 33 bf 4b 29 dd   .[..9....c.3.K).
      0030 - 26 fc cc 61 e2          

I opened the issue for the last case. Your decryption function works actually. The algorithm is recognized correctly as TripleDES. Key deviation is the same. What I did is to cut the derived key to 24 bytes and to shift the last 8 bytes from IV to the payload.

martingalloar commented 3 years ago

Let me know of it looks for you in #37!

$ pysapgenpse -c seclogin -vf cred_v2_lps_off_3_algs -d -u xxxadm
pysapgenpse version: 0.1.20.dev0
pysapgenpse: Reading credentials file 'cred_v2_lps_off_3_algs'

 0 (LPS:OFF): CN=PSEowner1, C=BG
     (LPS:N/A): /usr/sap/XXX/D00/sec/test1.pse
         Credential cipher format version 0, algorithm 3DES
         PIN:       Ab_1234567890

 1 (LPS:OFF): CN=PSEowner2, C=BG
     (LPS:N/A): /usr/sap/XXX/D00/sec/test2.pse
         Credential cipher format version 0, algorithm 3DES
         PIN:       Ab_1234567890

 2 (LPS:OFF): CN=PSEowner3, C=BG
     (LPS:N/A): /usr/sap/XXX/D00/sec/test3.pse
         Credential cipher format version 1, algorithm 3DES
         PIN:       Ab_1234567890

 3 (LPS:OFF): CN=PSEowner4, C=BG
     (LPS:N/A): /usr/sap/XXX/D00/sec/test4.pse
         Credential cipher format version 1, algorithm AES256
         PIN:       Ab_1234567890

 4 readable SSO-Credentials available
rstenet commented 3 years ago

Looks good and works, too.