I have successfully executed su -c whoami -
using paramiko like such:
def amiroot(ssh: paramiko.client.SSHClient, root_pass: str) -> bool:
session = ssh.get_transport().open_session()
session.set_combine_stderr(True)
session.get_pty()
# print("Sending su -c whoami -")
session.exec_command("su -c whoami -")
stdin = session.makefile('wb', -1)
stdout = session.makefile('rb', -1)
while not re.search(b"[Pp]assword", session.recv(1024)):
time.sleep(1)
# print("Sending password")
stdin.write(root_pass + "\n")
stdin.flush()
start = time.monotonic()
while not stdout.channel.eof_received:
time.sleep(1)
if (time.monotonic() - start) > 10:
# print("STDOUT timeout")
stdout.channel.close()
break
# lines = list(filter(None, (lb.decode("utf-8").strip() for lb in stdout.readlines())))
# print(lines)
return stdout.read().decode("utf-8").strip() == "root"
So conceptually it works, but I need it to be done asynchronously against many targets.
I've chosen to use AsyncSSH, and have gone so far as such:
async def amiroot(address: str, username: str, password: str, rootpass: str):
async with asyncssh.connect(
address,
username=username,
password=password,
known_hosts=None,
connect_timeout=10,
login_timeout=10,
) as conn:
print(f"Connected to {address}, sending su")
async with conn.create_process("su -c whoami -", term_type="xterm") as process:
print(f"{address}: su sent, waiting response") ###
while "password" not in (await process.stdout.read()):
await asyncio.sleep(1)
await process.stdin.write(rootpass + "\n")
print(f"{address}: rootpass sent, waiting response")
print(await process.stdout.read())
However I got stuck at the line marked ###
and never even reached the rootpass sent
line. For example:
Connected to 1.2.3.4, sending su
1.2.3.4: su sent, waiting response
And the program just stuck there.
How do I invoke su -c ... -
in AsyncSSH similarly to how I did it using paramiko?