The vulnerability of this component has been exposed a long time ago, but I encountered it again at work recently. I happened to be reading about Java deserialization recently, so I decided to take it out. After further analysis, we also encountered some strange problems during the period.
Most of the analysis articles on the Internet manually add the dependency of commons-collections4-4.0 in order to use the CommonsCollections2 payload generated by ysoserial. However, the situation I encountered was that CommonsBeanutils1 was used. You can directly succeed, so we will not repeat the analysis of CommonsCollections2 online here.
Debug environment:
JDK 1.8.0_72
Tomcat 8.0.30
First, we clone Shiro's source code back and cut to the branch in question.
git clone https://github.com/apache/shiro.git shiro-rootcd shiro-root git checkout 1.2.0
In order to make the samples that come with Shiro run, we need to make some modifications to the samples/web/pom.xml file. We need to change the jstl version to 1.2 and delete the scope field of servlet-api. . Put jstl-1.2.jar in the WEB-INF/lib directory. Then you should be able to run and debug.
We will hit the breakpoint to the resolvePrincipals method in org.apache.shiro.mgt.DefaultSecurityManager, and send a request with rememberMe Cookie, and it should be able to break.
We continue to follow the getRememberedIdentity method:
Continue to follow the getRememberedSerializedIdentity method:
In this In the method, the Cookie we passed in is read and base64 decoded:
Next, shiro will call convertBytesToPrincipals and pass in the base64 decoded byte array as a parameter:
You can also guess it by the function name. Two operations are performed, namely decryption and deserialization. Let’s look at the decryption part first. After simple debugging, we found that An AES decryption, and there is a preset key Base64.decode("kPH bIxk5D2deZiIxcaaaA==");. In the sample that comes with Shiro, this key is not set in other ways, so this preset key is used here. Set value.
The IV encountered in AES decryption is also obtained from the first few bytes of the Cookie we passed in, so we can easily construct a Cookie value containing any content and decrypt the plaintext It is the serialized content, and deserialize is called for deserialization.
The org.apache.shiro.io.DefaultSerializer#deserialize method will eventually be called for deserialization:
The whole process is very simple. A brief summary is: Read Get cookie -> base64 decoding -> AES decryption -> Deserialization
So our payload is very simple to construct. I will put the complete PoC on my GitHub.
During the debugging process, I encountered some problems and the calculator did not pop up successfully. Let’s record it here.
I was debugging this problem for a long time. I thought it was a problem with the payload or that Shiro's code had changed over time. Because the case I encountered at that time was that the payload entered my soul, and I was very confused. Later, we discovered a key problem. In the sample we cloned from github, the dependent version of commons-beanutils is 1.8.3, and the version of the payload generated by ysoserial is 1.9.2, so it cannot be successfully executed in the default sample. of. So I changed the version number to 1.9.2, and it became a hit.
So in the case we encountered, the actual dependent environment version may be like this, so we can directly succeed.
After cloning this project, you can see that there is a commons-collections package:
It will be thrown when trying to use CommonsCollections1 provided by ysoserial Exception, unable to succeed
When debugging, I found the exception thrown here. It is very confusing why the byte array cannot be deserialized
I checked the difference between Class.forName() and ClassLoader.loadClass() in Java and found that forName() always uses the caller's ClassLoader(), while loadClass() You can specify a different ClassLoader yourself. So where did ClasssLoader in shiro come from? It is obtained through Thread.currentThread().getContextClassLoader();, which is WebappClassLoader. But why does it prompt that the byte array cannot be loaded? After searching for a while, I saw the discussion below on the orange blog and learned the truth of the whole thing:
Shiro resovleClass uses ClassLoader.loadClass() instead of Class.forName(), and ClassLoader.loadClass does not support loading array type classes.
The above is the detailed content of Apache Shiro 1.2.4 Deserialization Vulnerability Example Analysis. For more information, please follow other related articles on the PHP Chinese website!