banner
lca

lca

真正的不自由,是在自己的心中设下牢笼。

Record of an autodecode AES decryption penetration test

Recently tested several sites, starting with a login box. After capturing the packets, the username and password were encrypted, formatted as follows:

Pasted image 20241129200536

AES is commonly used for front-end encryption. I have also encountered cases where the AES key is first encrypted using RSA, and then the data is encrypted for transmission using AES.

The above image is a case of direct AES encryption.

We can find the encrypted JS file through the browser, usually located in the source code/source under the JS directory. This site is relatively simple and directly uses the crypto-js.js file, which can be opened to see the AES key and encryption method.

Pasted image 20241129200734

From the above image, we can see that the key is provided, the mode is ECB, and the padding is Pkcs7. With these elements, we can proceed to decrypt the data.

Using the autodecoder plugin from Burp Suite, this decryption also utilizes this plugin.

Pasted image 20241129201305

AutoDecoder has four tabs.

Pasted image 20241129201504

The first options tab contains some settings:

  • Module Control: Specify which Burp modules to run autodecoder encryption/decryption on.
  • Encryption/Decryption Options: Control the method of encryption/decryption, whether to use built-in algorithms or interface-based encryption/decryption.

Pasted image 20241129201749

The subsequent options pertain to the first option. For example, if I choose interface-based encryption/decryption, I can set options for processing the data header or different encryption/decryption for request and response.

  • Encryption/Decryption Settings: It is important to fill in the encryption domain; otherwise, the autodecoder tab will not display. The others can be left as default.
  • After setting, be sure to save.

The second tab is for built-in algorithm encryption/decryption.

Pasted image 20241129202124

The third tab is for interface-based encryption/decryption.

You need to set the interface, and the interface can refer to what the author provided. If you need to customize some request parameters, most of the time, you will need to use interface-based encryption/decryption.

Pasted image 20241129202150

In this case, there are two parameters, and using the built-in algorithm for encryption/decryption does not quite meet the requirements.

Pasted image 20241129200536

The built-in algorithm for encryption/decryption has a regex pattern match that can only match one encrypted string (name), so it cannot extract the encrypted string for the pwd parameter.

The fourth tab is for request/response replacement.

This can be used to test some authorization vulnerabilities, similar to Burp's Autorize plugin, which I have not used.

Pasted image 20241129202217

A brief introduction to the autodecoder plugin.

I modified the author's script to adapt it to the current testing site.

from flask import Flask, request
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import base64
from urllib.parse import parse_qs, quote
import hashlib

def aes_encrypt(key, data):
    cipher = AES.new(key, AES.MODE_ECB)
    padded_data = pad(data.encode(), AES.block_size)
    cipher_text = cipher.encrypt(padded_data)
    return base64.b64encode(cipher_text).decode()

def aes_decrypt(key, data):
    cipher = AES.new(key, AES.MODE_ECB)
    decrypted_data = cipher.decrypt(base64.b64decode(data))
    unpadded_data = unpad(decrypted_data, AES.block_size)
    return unpadded_data.decode()

app = Flask(__name__)

@app.route('/encode', methods=["POST"])
def encrypt():
    key = b'write aes key here'  # 16 bytes key
    str1 = '123'
    param = request.form.get('dataBody')  # Get POST parameter
    md5value = param + str1
    param1 = quote(aes_encrypt(key, param))
    param2 = hashlib.md5(md5value.encode()).hexdigest()
    return f"Param={param1}&Autograph={param2}"
    '''
    data = json.loads(param)
    encrypted_id = aes_encrypt(key, data["id"])
    encry_param = param.replace(data["id"], encrypted_id)
    return base64.b64decode(encry_param.encode()).decode()
    '''

@app.route('/decode', methods=["POST"])
def decrypt():
    key = b'write aes key here'
    param = request.form.get('dataBody')
    print('param: ', param)
    parsed_params = parse_qs(param)
    print(parsed_params)
    
    # Decrypt two parameters, name and pwd
    decrypted_name = aes_decrypt(key, parsed_params["name"][0])
    decrypted_value = aes_decrypt(key, parsed_params["pwd"][0])
    
    # Return a JSON response containing both parameters
    return f"name={decrypted_name}&pwd={decrypted_value}"

if __name__ == '__main__':
    app.debug = True  # Set debug mode, remember to turn it off in production
    app.run(host="0.0.0.0", port=8888)

Once the script is ready, run it, and the program will listen on 127.0.0.1:8888.

python3 aed_decode.py

You can capture a packet for testing, and you will see that it successfully decrypted.

Pasted image 20241129203021

Current settings are as follows:

Pasted image 20241129203246

Pasted image 20241129203422

After completing the settings, you can see that each request will automatically decrypt, and the decrypted content can be viewed in the autoDecoder tab.

Pasted image 20241129203459

You can also start using Burp's intruder module for login brute-forcing.

Here, I also recommend a front-end encryption practice target, which includes test scenarios for asymmetric encryption, symmetric encryption, signing, and replay prevention, such as AES, DES, and RSA, for penetration testing practice.

Target address: https://github.com/SwagXz/encrypt-labs/tree/main

Loading...
Ownership of this post data is guaranteed by blockchain and smart contracts to the creator alone.