OWASP / OWASP/pysap

RSECTAB decryption (ABAP Secure Storage)

Open
#80 4 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

question
Dominant language
Python
Stars
257
Forks
72
Avg merge
33m
Merged PRs (30d)
6

Description

Hello everyone,

When changing default encryption key of ABAP Secure Storage entries (transaction SECSTORE), data is stored encrypted in hex format in table RSECTAB, field DATA.

The encryption key is stored in encrypted format in SSFS and can be decrypted with .KEY and .DAT files and the SSFS implementation in pysap.

However, to decrypt RSECTAB blob from DATA field usage of the decrypted key does not work properly.

I verified I had the right decrypted key as I stored a backup of it when generating it from the SECSTORE Wizard.

The issue is that the plaintext key is 29 bytes however pysap implementation with function rsectab below only accepts 24 bytes key length. I tried using the last 24 bytes or the first 24 bytes and some other random bytes permutation to only take a 24 bytes key as input without success.

Below is the pysap function I used for decryption which implements the RSECCipher class for the custom 3DES-EDE3 custom algorithm implementation of SAP.

I have also tried implementing a custom decryption algorithm following the algorithm details specified in this article SAP ABAP Secure Storage algorithm but without success. I see that decryption depends also on SID and Installation Number, so maybe I'm missing something ?

Any help would be appreciated, and many thanks in advance !

`def rsec_decrypt(blob, key):
    """Decrypts a blob of data using SAP's RSEC decryption algorithm. The algorithm is based on
    the TripleDES.

    The decryption method is used in SSFS but also as part of other encryption schemes (e.g. RSECTAB),
    hence implemented in the crypto library instead of the particular layer.

    :param blob: encrypted blob to decrypt
    :type blob: bytes

    :param key: key to use to decrypt
    :type key: bytes

    :return: decrypted blob
    :rtype: bytes

    :raise Exception: if decryption failed
    """
    if len(key) != 24:
        raise Exception("Wrong key length")

    blob = [ord(i) for i in blob]
    key = [ord(i) for i in key]
    key1 = key[0:8]
    key2 = key[8:16]
    key3 = key[16:24]

    cipher = RSECCipher()
    round_1 = cipher.crypt(RSECCipher.MODE_DECODE, blob, key3, len(blob))
    round_2 = cipher.crypt(RSECCipher.MODE_ENCODE, round_1, key2, len(round_1))
    round_3 = cipher.crypt(RSECCipher.MODE_DECODE, round_2, key1, len(round_2))

    return ''.join([chr(i) for i in round_3])`

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the rsec_decrypt function and RSECCipher implementation, then compare the SSFS and RSECTAB decryption paths described in the issue. Reproduce the failure with the 29-byte plaintext key and investigate the role of the SID and Installation Number; done means successfully decrypting the RSECTAB DATA blob with the correct key handling.

Written by the indexing model from the issue text.

Assessment

Tech stack
python
Domain
cryptography, reverse-engineering, security
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Quiet
Clarity
Needs clarification
Newbie friendliness
28/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.