# Admin CLI
* remote
## Description
> A (very) early version of the administration tool used for FE-CTF was found. Looks like they only just started making> it, but maybe it's already vulnerable?
```shellnc admin-cli.hack.fe-ctf.dk 1337```
---
## Challenge
We are given a Java class file, `Main.class`, a Dockerfile that runs the class file, and a netcat command to connect tothe server where the Docker container is running.
Looking at the Dockerfile, the first intention is that it seems to be a Log4shell challenge, since it uses thevulnerable Log4j version 2.14.1.
```dockerfileRUN wget http://archive.apache.org/dist/logging/log4j/2.14.1/apache-log4j-2.14.1-bin.zipRUN unzip apache-log4j-2.14.1-bin.zip```
However, looking at the Java class file, it seems not necessary to exploit the Log4j vulnerability, since the class filesimply replaces ``API_KEY`` with the flag.
```javapublic class Main {
	/* flag{....} */	private static String API_KEY = Base64.getUrlEncoder().encodeToString(System.getenv("FLAG").getBytes()); 	/* Doesn't seem to be authorized, I don't know why... */	/* https://backend.fe-ctf.local/removePoints?teamId=0&amount=1000&key=api_key */	private static int HASH_CODE = -615519892;
	/* Should be safe, right? */	private static Logger logger = LogManager.getLogger(Main.class); 	public static void main(String[] args) {		Configurator.setLevel(Main.class.getName(), Level.INFO);		Scanner s = new Scanner(System.in);		System.out.print("Enter URL: ");		String input = s.nextLine();		s.close();		try {			URL url = new URL(input.replaceAll("API_KEY", API_KEY));			if (url.hashCode() == HASH_CODE && url.getHost().equals("backend.fe-ctf.local")) { logger.info("URLs Matched, sending request to {}", url);				/* TODO: Figure out how to send request				HttpURLConnection con = (HttpURLConnection) url.openConnection();				con.setRequestMethod("GET")				*/			} else {				logger.warn("URLs are not equal!");			}		} catch (MalformedURLException e) {			logger.error("Invalid URL");			System.exit(1);		}	}}```
At a second glance it looks more like a hash collision challenge. The class file takes a URL as input,replaces ``API_KEY`` with the flag, and then checks if the hash code of the URL is equal to ``-615519892`` and if thehost is ``backend.fe-ctf.local``. If both conditions are true, it will log the URL.
So the goal is to create a URL that has the same hash code as ``-615519892`` and has ``backend.fe-ctf.local`` as host.The URL also needs to contain the flag, so we can see it in the logging message.
The hash code is taken from the ``java.net.URL`` class, which uses the following hash function:
```javaprotected int hashCode() {    int h = 0;
    // Generate the protocol part.    String protocol = u.getProtocol();    if (protocol != null) h += protocol.hashCode();
    // Generate the host part.    String host = u.getHost();    if (host != null) h += host.toLowerCase().hashCode();
    // Generate the file part.    String file = u.getFile();    if (file != null) h += file.hashCode();
    // Generate the port part.    if (u.getPort() == -1) h += u.getDefaultPort();    else h += u.getPort();
    // Generate the ref part.    String ref = u.getRef();    if (ref != null) h += ref.hashCode();
    return h;}```
After some testing around with the hash function, we realized that the hash code function does not take the authoritypart of the URL into account.
By simply setting the authority part of the URL to ``API_KEY``, we can create a URL with a hash code independent of theflag.
Luckily in the comments of the class file, we can find a URL that has the hash code ``-615519892``:
```java/* https://backend.fe-ctf.local/removePoints?teamId=0&amount=1000&key=api_key */```
So by just taking that URL and adding the authority we can get the flag.
```https://[email protected]/removePoints?teamId=0&amount=1000&key=api_key```
## Useful links
* https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
## Alternative solutions
## Option 1
During the CTF we also realized that the port changes the hash code by its exact value.
```java// Generate the port part.if (u.getPort() == -1) h += u.getDefaultPort();else h += u.getPort();```
So it would be possible to just calculate the difference between the url hash code and the target hash code and then addthe difference as the port. This opens up the possibility to craft a URL that abuses the Log4j vulnerability.
## Option 2
After the CTF we came across a writeup that used the fact that apparently already when creating the URL object, a DNSlookup is performed. So it is possible to create a URL that contains ``API_KEY`` as a subdomain which will be replacedby the flag and then the DNS request will just leak the flag in the subdomain as the hostname ist first checked afterthe URL object is created.
```javaURL url = new URL(input.replaceAll("API_KEY", API_KEY));if (url.hashCode() == HASH_CODE && url.getHost().equals("backend.fe-ctf.local")) {```