How can I properly mimic this encryption method to produce the proper value for the encryptedPwd field?
Asked Answered
C

1

13

Background

I'm needing to pull reports from Amazon's Seller Central portal for multiple clients of ours on a weekly basis via a python script. I try to avoid webdrivers due to their inconsistent, error-prone nature across different OSes (from experience). Therefore, I figured it would be a fun little project (and maybe, ultimately, exercise in futility) to try reverse-engineering the login process for sellercentral.amazon.com. The process isn't difficult, save for two fields in the initial login form: password and metadata1. The password field is discussed in detail below. The metadata1 field seems to employ a similar technique, while introducing the additional hurdle of changing every few seconds. When i monitored the metadata1 value it appeared to be generated using a large json object of the various browser metrics. But, one thing at a time, so I'll focus on the password encryption in this post and worry about metadata1 in a future post.

Getting to the point 

Upon form submission the value in the password field is encrypted using techniques discussed further down in this post. The resulting encrypted value then replaces the value in the the password field and renames the field encryptedPwd

My Findings

So far, I've been reviewing the javascript files and stepping through the code sequences and have learned the following:

  • They're utilizing a proprietary SiegeCrypto.js script as the main cryptographic library (Siege being Amazon's Secure Ingress and Egress Team) & SubtleCrypto as a part of the process for generating the encryptedPwd   - SiegeCrypto is first found in AuthenticationPortalSigninNA.js, declaring the basic initial encryption definition:
SiegeCrypto.addProfile("AuthenticationPortalSigninNA", {
  "password": {dataType: "AuthPortalSigninPasswordNA", requiresTail: false},
});
...
SiegeCrypto.addDataType({
    "dataTypeId": "AuthPortalSigninPasswordNA",
    "jwkPublicKey": {"kty":"RSA","e":"AQAB","n":"gXXZV1VqZ6k_uQtyJNJy5q-qvKdqrXJNgKUO1aYc1UPBVqlhCP0GPxf-0GSo-LEtArgcbF8-j6_vSLSqztYxxF8og--rB8zAyZ8DXZaugX-UiJDQnoJL_HtXKuwIm9U7oEPoeD6H4ZDcfbsPj77xVn7UA2-a90N4aZqMC8EIfXIy1tqSbSPnxPOaiEmy8xGtG-L3RdCyc7TL0Swd_f0_DjRT6ip91IBlCmquoa-xJgZ9e44PVH4AwdyssiV4ZLEZ5yFcE0zcRb_62kx_TQptidbJ4nHocFVjmUW9YsrAWeKrBmOGZEjO4vbATYs1Yf4vgcH7Ix61EPR5sbDP4SlBWQ"},
    "providerId": "si:md5",
    "keyId": "56d14edce8e2cb6c6842c59ddaee426e"
});

Stepping through the code I was able to find more specifics of the algorithm

*profile* (used by SiegeCrypto)
- password: {dataType: "AuthPortalSigninPasswordNA", requiresTail: false}
*publicKeyProvider* (added as a DataType to SiegeCrypto)
- keyId: 56d14edce8e2cb6c6842c59ddaee426e
- providerId: si:md5
*wrapKey*
- wrappingAlgorithm
  - name: RSA-OAEP
  - hash: SHA-256
  - modulusLength: 2048
  - publicExponent: [1, 0, 1]
*Additional Fields*
name: aes_128_gcm_iv12_tag16
encryption: AES-GCM
ivLength: 12
keyLength: 128
tagLength: 128

Later in the process I was able to find the following, which I'm assuming is the parameters amidst being processed according to the encryptions specifications above, but i have no idea how to get to that point

cipherMessage: Uint8Array(413) [1, 128, 0, 20, 124, 132, 165, 153, 149, 96, 94, 4, 210, ...]
messageHeader:
- algorithmId: 20
- contentType: 2
- encryptedDataKeys: [{"keyInfo": "56d14edce8e2cb6c6842c59ddaee426e"}]
- encryptionContext: {}
- frameLength: 12
- headerIvLength: 12
- messageId: Uint8Array(16) [124, 132, 165, 153, 149, 96, ...]
- type: 128
- version: 1

Looking over Amazon's AWS Encryption SDK (Python Repo) I've found the following three pieces that seem to be what I need. However, I'm not sure where to go from here.

# algorithm, mode, data_key_length, iv_length, auth_length, auth_key_length=0
EncryptionSuite.AES_128_GCM_IV12_TAG16 = (algorithms.AES, modes.GCM, 16, 12, 16)

# algorithm_id,  encryption, message_format_version
AlgorithmSuite.AES_128_GCM_IV12_TAG16 = (0x0014, EncryptionSuite.AES_128_GCM_IV12_TAG16, 0x01)

# encryption_type, algorithm, padding_type, padding_algorithm, padding_mgf
WrappingAlgorithm.RSA_OAEP_SHA256_MGF1 = (EncryptionType.ASYMMETRIC, rsa, padding.OAEP, hashes.SHA256, padding.MGF1)

The Question

Can someone provide a short python snippet utilizing the above encryption techniques along with an explanation, so I can see how the encryptedPwd field value is generated? Here's a dummy password to demonstrate with: Blamazon123

Two example values of the above dummy password as encryptedPwd (I've added spaces where I saw consistences):

AYAAF  P/a2u8yLSNjLWzPRIi0Bac  AAAABAAZzaTptZDUAIDU2ZDE0ZWRjZThlMmNiNmM2ODQyYzU5ZGRhZWU0MjZlAQ  Brthm+db6k/Oo832X/5U+JtXcBrVnCetjOnvcypG5ZZ6xZr0rXDDMctQevThwGjGYqOOQTy6tFALgMHnjWC2bcBBtyKMhUflpCjGTRodjE7btdqrgExEr07k1ErejaQ1vAW8hQSedfsQR3gyWxJcKKlQ91B4CYO5UMMJzevQyln0SASh5MLW6xOHMnjwdHI8aKFw2ErcvIFg5OpqCDSIyPjifvxkSTue7gJ3fB0ACda04EA5wxmkRteCF753kVGYNBD0h9eOHCPcCm/Y7bWoJAelvqu/U/LxAPkl216deDko4oxjVqLeRy/IExbx6cdEDT7zu0U7HROhvstu8TZE1f  AgAAAAAMAAAADAAAAAAAAAAAAAAAA  O0Gt/txLoiiXlGQcb5dyFn/////  AAAAAQAAAAAAAAAAAAAAAQAAAAv  LEJ4zlnbivrzliBrcFGIsPBU3srfmTu91dw4=
AYAAF  L1E3ydr57mIKpAQtOrAPsE  AAAABAAZzaTptZDUAIDU2ZDE0ZWRjZThlMmNiNmM2ODQyYzU5ZGRhZWU0MjZlAQ  AUJX+8tRKZESh1o09BLe6Qj13iuyP5Kb2IC/ipA1mRlWIQtIYApU8792+f5U2x8wv7rTVHcKM8wnFXP2I78PCbo4kXwV5Q6JE99bV4BP+5YnzB1YI6XUgrZ2ubm1wcSV3W1K3OhMogcXIbWjeEjKj2WmpVgSgCXKS6+Z6GxMnE+hArZlNIATYojL7IlLPR5kiGzN4pq86gLzGbfcG2at1MNQ5DdrJtktixLJPU1oFwCtT4AFfy6kiGfoepN+VE0AK0ysMyX3FY7QaI9qLtuA20zQX52NbLzG/qSENYohHzgvOOVzCIr4uwyJ3uXSA0kKXEJ4IbWmQ+k30cotoWRSJW  AgAAAAAMAAAADAAAAAAAAAAAAAAAA  NUNRLibdfG4P1ac0dL8Ka//////  AAAAAQAAAAAAAAAAAAAAAQAAAAv  4vyjW2MLIuuBm8D1c41v5ZwEQFk8k/p4GOss=

Adding Additional Source Code with Analysis

The javascript file largely responsible for generating the metadata1 field can be found here. I've decrypted the functions that I saw were part of the metadata1 generation process. They start on the following lines:

  • 1827 (relates to encryptedPwd) adds the encryption eventlistener to the form submit action
  • 332 the core generating function that dispatches the encrypting steps
  • 789 & 810 create a crcTable that's used in generating
  • 1839 calculates a checksum (used in the metadata1 process)
  • 2540 is where the metadata1 values are returned (from line 332)
  • 2672 and 2704 are where I noticed the email being converted a hex value, that is prefixed to the metadata1 contents before it's encrypted
Claribel answered 17/4, 2021 at 15:13 Comment(8)
Here some kind of logging to get info for kindle, so it might help.Cullum
Those look a lot like JWT tokens, see jwt.io. The string jwkPublicKey strongly hints at JWT as well.Disparate
I suspect the metadata1 object is going to be crucial; it is almost certainly used to prevent automated logins. It is probably used in the same way captchas work: increasing confidence that there is a human being interacting with the browser.Disparate
Did you ever figure this out? I'm looking to do something similar. Decrypting the metadata1 doesn't seem to have yielded anything about how the encryptedPwd field is generated.Freitag
@Freitag See mkb79's answer. It provides insight into how to properly generate it.Claribel
@Claribel Thanks, I get that part but I'm struggling with actually authenticating at the moment. Even using the generated version on the web page, I can't seem to sign in using nodejs. I can manage in postman thoughFreitag
@Claribel Can you explain a little more how decrypting the metadata1 field helps in generating the encryptedPwd field?Freitag
@Claribel I have a potentially similar but (I think) easier use case. I want to be able to trap the encryptedPwd value right before the signin form is actually submitted. I have been pulling out my hair trying to figure out how to do this, since no matter where I add a "submit" event listener (at the <form>, <body> or document level), that field doesn't seem to exist as an element of the form, and yet, when the POST is actually made, there it is, and the password field is gone. Any guidance on how to intervene after this SiegeCrypto stuff is run?Vaughnvaught
N
4

The metadata1 is encrypted in XXTEA. I‘ve wrote a Python script to decode and encode the metadata1. This can be found here.

Neddra answered 21/9, 2021 at 20:50 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.