mirror of
https://github.com/carlospolop/hacktricks
synced 2024-11-15 01:17:36 +00:00
GitBook: [master] one page modified
This commit is contained in:
parent
5aa6b23de5
commit
2b6688a92d
1 changed files with 23 additions and 142 deletions
|
@ -4,109 +4,34 @@ description: 'https://pentesterlab.com/'
|
|||
|
||||
# Electronic Code Book \(ECB\)
|
||||
|
||||
**Post from:** [**https://pentesterlab.com/**](https://pentesterlab.com/)\*\*\*\*
|
||||
|
||||
## ECB
|
||||
|
||||
ECB is an encryption mode in which the message is splitted into blocks of X bytes length and each block is encrypted separetely using a key.
|
||||
\(ECB\) Electronic Code Book - symmetric encryption scheme which **replaces each block of the clear text** by the **block of ciphertext**. It is the **simplest** encryption scheme. The main idea is to **split** the clear text into **blocks of N bits** \(depends on the size of the block of input data, encryption algorithm\) and then to encrypt \(decrypt\) each block of clear text using the only key.
|
||||
|
||||
The following schema \(source: [Wikipedia](http://en.wikipedia.org/wiki/Block_cipher_mode_of_operation)\) explains this method:
|
||||
![](https://assets.pentesterlab.com/ecb/ECB_encryption.png)
|
||||
|
||||
![License](https://assets.pentesterlab.com/ecb/ECB_encryption.png)
|
||||
Using ECB has multiple security implications:
|
||||
|
||||
You can check the [recent XKCD on the Adobe's password leak](http://xkcd.com/1286/) to get an humoristic idea of the problems tied to ECB.
|
||||
|
||||
During the decryption, the reverse operation is used. Using ECB has multiple security implications:
|
||||
|
||||
* Blocks from encrypted message can be removed without disturbing the decryption process.
|
||||
* Blocks from encrypted message can be moved around without disturbing the decryption process.
|
||||
|
||||
In this exercise, we will see how we can exploit these two weaknesses.
|
||||
* **Blocks from encrypted message can be removed**
|
||||
* **Blocks from encrypted message can be moved around**
|
||||
|
||||
## Detection of the vulnerability
|
||||
|
||||
In this exercise, you can register an account and log in with this account \(to make things easier, you get automatically logged in when you register\).
|
||||
Imagine you login into an application several times and you **always get the same cookie**. This is because the cookie of the application is **`<username>|<password>`**.
|
||||
Then, you generate to new users, both of them with the **same long password** and **almost** the **same** **username**.
|
||||
You find out that the **blocks of 8B** where the **info of both users** is the same are **equals**. Then, you imagine that this might be because **ECB is being used**.
|
||||
|
||||
If you create an account and log in two times with this account, you can see that the cookie sent by the application didn't change.If you log in many times and always get the same cookie, there is probably something wrong in the application. The cookie sent back should be unique each time you log in. If the cookie is always the same, it will probably always be valid and there won't be anyway to invalidate it.
|
||||
|
||||
If we look at the cookie, we can see that it seems uri-encoded and base64-encoded:
|
||||
|
||||
![License](https://assets.pentesterlab.com/ecb/cookie.png)
|
||||
|
||||
The 2 equals sign encoded as `%3d%3d` are a good indicator of base64-encoded string.
|
||||
|
||||
We can decode it using the following ruby code:
|
||||
Like in the following example. Observe how these **2 decoded cookies** has several times the block **`\x23U\xE45K\xCB\x21\xC8`**
|
||||
|
||||
```text
|
||||
% irb
|
||||
> require 'base64' ; require 'uri'
|
||||
=> true
|
||||
> Base64.decode64(URI.decode("OR9hcp18%2BC1bChK10NlRRg%3d%3d"))
|
||||
=> "9\x1Far\x9D|\xF8-[\n\x12\xB5\xD0\xD9QF"
|
||||
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
|
||||
|
||||
\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8\x04\xB6\xE1H\xD1\x1E \xB6\x23U\xE45K\xCB\x21\xC8\x23U\xE45K\xCB\x21\xC8+=\xD4F\xF7\x99\xD9\xA9
|
||||
```
|
||||
|
||||
Or by decoding the URI to a string manually and use the base64 command:
|
||||
This is because the **username and password of those cookies contained several times the letter "a"** \(for example\). The **blocks** that are **different** are blocks that contained **at least 1 different character** \(maybe the delimiter "\|" or some necessary difference in the username\).
|
||||
|
||||
```text
|
||||
% echo "OR9hcp18+C1bChK10NlRRg==" | base64 -D | hexdump -C
|
||||
0000000 39 1f 61 72 9d 7c f8 2d 5b 0a 12 b5 d0 d9 51 46 |9.ar.|.-[.....QF|
|
||||
0000010
|
||||
```
|
||||
|
||||
On osX, the command `base64 -D` replaces `base64 -d`
|
||||
|
||||
In both cases, we can see that the information seems to be encrypted.
|
||||
|
||||
First, we can start by creating two accounts `test1` and `test2` with the same password: `password` and compare the cookies sent by the application. We get the following cookies \(after URI-decoding\):
|
||||
|
||||
| Account: | test1 | test2 |
|
||||
| :--- | :--- | :--- |
|
||||
| Cookie: | vHMQ+Nq9C3MHT8ZkGeMr4w== | Mh+JMH1OMhcHT8ZkGeMr4w== |
|
||||
|
||||
If we base64-decode both cookies, we get the following strings:
|
||||
|
||||
| Account: | test1 | test2 |
|
||||
| :--- | :--- | :--- |
|
||||
| Decoded cookie: | \xBCs\x10\xF8\xDA\xBD\vs**\aO\xC6d\x19\xE3+\xE3** | 2\x1F\x890}N2\x17**\aO\xC6d\x19\xE3+\xE3** |
|
||||
|
||||
We can see that part of the decrypted values look really similar.
|
||||
|
||||
Now we can try to create a user with an arbitrary long username and password. For example, a username composed of 20 `a` and a password composed of 20 `a`. By creating this user, we get the following cookie:
|
||||
|
||||
```text
|
||||
> document.cookie
|
||||
"auth=GkzSM2vKHdcaTNIza8od1wS28inRHiC2GkzSM2vKHdcaTNIza8od1ys96EXmirn5"
|
||||
```
|
||||
|
||||
If we decode this value, we get the following value:
|
||||
|
||||
```text
|
||||
\x1AL\xD23k\xCA\x1D\xD7\x1AL\xD23k\xCA\x1D\xD7\x04\xB6\xF2)\xD1\x1E \xB6\x1AL\xD23k\xCA\x1D\xD7\x1AL\xD23k\xCA\x1D\xD7+=\xE8E\xE6\x8A\xB9\xF9
|
||||
```
|
||||
|
||||
We can see that the following pattern \(composed of 8 bytes\): **`\x1AL\xD23k\xCA\x1D\xD7`** comes back multiple times:
|
||||
|
||||
```text
|
||||
\x1AL\xD23k\xCA\x1D\xD7\x1AL\xD23k\xCA\x1D\xD7\x04\xB6\xF2)\xD1\x1E \xB6\x1AL\xD23k\xCA\x1D\xD7\x1AL\xD23k\xCA\x1D\xD7+=\xE8E\xE6\x8A\xB9\xF9
|
||||
```
|
||||
|
||||
Based on the size of the pattern, we can infer that the ECB encryption uses a block size of 8 bytes.This example is using a weak encryption mechanism and it's likely that real life examples will use bigger block size.
|
||||
|
||||
The decoded information also shows us that the username and password are not directly concatenated and that a delimiter is added \(since one of the block in the middle is different from the previous one\).
|
||||
|
||||
We can think of the encrypted stream has one of the two following possibilities:
|
||||
|
||||
* The stream contains the username, a delimiter and the password:
|
||||
|
||||
![Schema username password](https://assets.pentesterlab.com/ecb/del_u_p.png)
|
||||
|
||||
* The stream contains the password, a delimiter and the username:
|
||||
|
||||
![Schema password username](https://assets.pentesterlab.com/ecb/del_p_u.png)
|
||||
|
||||
By creating another user with a long username and a short password, we can see that the following pattern is used: `username|delimiter|password`.
|
||||
|
||||
Now let's try to find the size of the delimiter, if we play with different size of username and password we get the following results:
|
||||
Now, the attacker just need to discover if the format is `<username><delimiter><password>` or `<password><delimiter><username>`. For doing that, he can just **generate several usernames** with s**imilar and long usernames and passwords until he find the format and the length of the delimiter:**
|
||||
|
||||
| Username length: | Password length: | Username+Password length: | Cookie's length \(after decoding\): |
|
||||
| :--- | :--- | :--- | :--- |
|
||||
|
@ -116,68 +41,24 @@ Now let's try to find the size of the delimiter, if we play with different size
|
|||
| 4 | 4 | 8 | 16 |
|
||||
| 4 | 5 | 9 | 16 |
|
||||
|
||||
We can see that the size of the decoded cookie goes from 8 to 16 bytes when the length of the Username+Password is greater than 7. We can infer from this value that the delimiter is a single byte since the encryption is done per block of 8 bytes.
|
||||
|
||||
Another important thing is to see what part of the encrypted stream is used by the application when we send the cookie back. If we remove everything after the block corresponding to the delimiter, we can see that we are still authenticated. The password does not seem to be used when the cookie gets used by the application.
|
||||
|
||||
We now know that we just need to get the correct `username|delimiter` to get authenticated within the application as `username`.If you can find what delimiter is used \(or brute force it\), you can try to create a user with a username that contains the delimiter \(for example the username "`admin:`"\). Using this method, you may be able to get logged in as `admin`. This web application prevents this type of attack.
|
||||
|
||||
## Exploitation of the vulnerability
|
||||
|
||||
### By removing information
|
||||
### Removing entire blocks
|
||||
|
||||
The easiest way to get `admin` access is to remove some of the encrypted data. We know that the application uses the following format:
|
||||
Knowing the format of the cookie \(`<username>|<password>`\), in order to impersonate the username `admin` create a new user called `aaaaaaaaadmin` and get the cookie and decode it:
|
||||
|
||||
```text
|
||||
\[username\]:\[separator\]
|
||||
\x23U\xE45K\xCB\x21\xC8\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
|
||||
```
|
||||
|
||||
and only uses the `username` when the cookie is sent back to the application. We also know that each block of 8 bytes is completely independant \(ECB\). To exploit this issue, we can create a username that contains 8 characters followed by the word `admin`:
|
||||
We can see the pattern `\x23U\xE45K\xCB\x21\xC8` created previously with the username that contained only `a`.
|
||||
Then, you can remove the first block of 8B and you will et a valid cookie for the username `admin`:
|
||||
|
||||
```text
|
||||
aaaaaaaaadmin
|
||||
\xE0Vd8oE\x123\aO\x43T\x32\xD5U\xD4
|
||||
```
|
||||
|
||||
And we will receive the cookie \(retrieved using the Javascript Console\):
|
||||
|
||||
```text
|
||||
> document.cookie
|
||||
"auth=GkzSM2vKHdfgVmQuKXLregdPxmQZ4yvj"
|
||||
```
|
||||
|
||||
This value will get decoded as:
|
||||
|
||||
```text
|
||||
\x1AL\xD23k\xCA\x1D\xD7\xE0Vd.)r\xEBz\aO\xC6d\x19\xE3+\xE3
|
||||
```
|
||||
|
||||
We can see the pattern `\x1AL\xD23k\xCA\x1D\xD7` detected previously with the username that contained 20 `a`.
|
||||
|
||||
We can then remove the first 8 bytes of information and reencode our payload to get a new cookie:
|
||||
|
||||
```text
|
||||
\xE0Vd.)r\xEBz\aO\xC6d\x19\xE3+\xE3
|
||||
```
|
||||
|
||||
That will get encoded by the following ruby code:
|
||||
|
||||
```text
|
||||
% irb
|
||||
> require 'cgi'; require 'base64'
|
||||
=> true
|
||||
> CGI.escape(Base64.strict_encode64("\xE0Vd.)r\xEBz\aO\xC6d\x19\xE3+\xE3"))
|
||||
=> "4FZkLily63oHT8ZkGeMr4w%3D%3D"
|
||||
```
|
||||
|
||||
Once you modify the cookie:
|
||||
|
||||
![Cookie tampering with JS console](https://assets.pentesterlab.com/ecb/cookiemod.png)
|
||||
|
||||
And send this value back to the application \(by reloading the page\), you get logged in as `admin`:
|
||||
|
||||
![License](https://assets.pentesterlab.com/ecb/admin.png)
|
||||
|
||||
### By swapping blocks around
|
||||
### Moving blocks around
|
||||
|
||||
A more complicated way to bypass this is to swap data around. We can make the assumption that the application will use an SQL query to retrieve information from the user based on his `username`. For some databases, when using the type of data `VARCHAR` \(as opposed to `BINARY` for example\), the following will give the same result:
|
||||
|
||||
|
@ -220,7 +101,7 @@ Once you modify your cookie, and you reload the page, you should be logged in as
|
|||
|
||||
![License](https://assets.pentesterlab.com/ecb/admin.png)
|
||||
|
||||
## Conclusion
|
||||
## References
|
||||
|
||||
This exercise showed you how you can tamper encrypted information without decrypting them and use this behaviour to gain access to other accounts. It showed you that encryption can not be used as a replacement to signature and how it's possible to use ECB encryption to get control on the decrypted information. I hope you enjoyed learning with PentesterLab.
|
||||
* [http://cryptowiki.net/index.php?title=Electronic\_Code\_Book\_\(ECB\)](http://cryptowiki.net/index.php?title=Electronic_Code_Book_%28ECB%29)
|
||||
|
||||
|
|
Loading…
Reference in a new issue