Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to enter a password into the terminal password prompt in Python

I am trying to make a simple Python script that enters a given password in the command line after using the 'su' command (or any other command which requires administrator privileges or simply requires a password in order to be executed).

I tried to use the Subprocess module for this as well as pynput, but haven't been able to figure it out.

import subprocess
import os

# os.system('su') # Tried using this too

process = subprocess.Popen('su', stdin=subprocess.PIPE, stdout=subprocess.PIPE)
process.stdin.write(b"password_to_enter")
print(process.communicate()[0])
process.stdin.close()

I was expecting this to enter 'password_to_enter' in the given password prompt after typing the 'su' command, but it didn't. I tried giving it the correct password as well but still did not work.

What am I doing wrong?

PS: I am on Mac

like image 246
FedeCuci Avatar asked Sep 18 '25 08:09

FedeCuci


1 Answers

The su command expects to be reading from a terminal. Running your example above on my Linux machine returns the following error:

su: must be run from a terminal

This is because su tries to make sure it's being run from a terminal. You can bypass this by allocating a pty and managing input and output yourself, but getting this right can be pretty tricky because you can't enter the password until after su prompts for it. For example:

import subprocess
import os
import pty
import time

# Allocate the pty to talk to su with.
master, slave = pty.openpty()

# Open the process, pass in the slave pty as stdin.
process = subprocess.Popen('su', stdin=slave, stdout=subprocess.PIPE, shell=True)

# Make sure we wait for the "Password:" prompt.
# The correct way to do this is to read from stdout and wait until the message is printed.
time.sleep(2)

# Open a write handle to the master end of the pty to write to.
pin = os.fdopen(master, "w")
pin.write("password_to_enter\n")
pin.flush()

# Clean up
print(process.communicate()[0])
pin.close()
os.close(slave)

There's a library called pexpect that makes interacting with interactive applications pretty simple:

import pexpect
import sys

child = pexpect.spawn("su")
child.logfile_read = sys.stdout
child.expect("Password:")
child.sendline("your-password-here")
child.expect("#")
child.sendline("whoami")
child.expect("#")
like image 92
Michael Powers Avatar answered Sep 19 '25 21:09

Michael Powers