I'm using os.system() to invoke some openssl command from my ubuntu box. I specify password in line so it looks like:
//python code
os.system("openssl enc -aes-256-cbc ... -k password")
I need to know if is possible to track this command in some shell / bash history file (as it is possible if I type this command into terminal directly, so basically I'm asking if password handling is secure that way)
No, bash only logs commands that are entered interactively.
Commands executed through os.system are not logged anywhere.
No, it does not, however on a multiuser box, passing passwords via command-line parameters is considered bad for security, as other users can (in principle) see them via "ps" etc.
Passing the password via a file descriptor (e.g. stdin) or environment variable is immune to this attack; most programs have support for one of these methods instead. If it bothers you, consider using one of those.
While the arguments are not logged (only interactive commands are logged, and that's in a file that is stored with correct permissions in your home directory) there is still a real danger with passing passwords. Both the command line arguments and the environment variables are visible to all users of the machine who use ps with the correct options. The exact options to do this vary between OSes, so check your local documentation (on OSX, it's ps -wwaxE that spills the beans).
The safe way to pass the password in is either via a pipe and the -pass stdin option to openssl (-k is insecure and obsolete) or via a file with carefully-set permissions and the -pass file:pathname option (replacing pathname with the name of the file, of course). You could also use -pass fd:number but I don't know how easy that is to fit with os.system. All the above are secure (possibly with care) because you can't peek inside pipes and you can properly secure the filesystem.
Of course, once you've taken these steps to secure your invocation of openssl, whether or not it is logged won't matter; it will be secure anyway.
Related
I have numerous test servers. These test servers get re-imaged frequently, and they have the same user account and password after being re-imaged. I want to write a python script that runs a command remotely over ssh on one of these servers, without prompting user for a password, and gathers the output of the command. In some circumstance I want to run one command, get output, analyze the output. In other situation, I want to run several commands at a time (possibly run a script file). I read many postings about running commands remotely, using third party packages (e.g. paramiko). Is there a recommended way to achieve this task without using additional packages ? The server from which my script will be run might not have the package installed.
Or should I used pexpect ?
Ideally I would like to use subprocess and capture the output (providing password as an argument). Of course, my script has to handle the case when the client is logging for first time, and prompted to add ssh key to .ssh/knownhosts file.
Thank you,
Ahmed.
If host key security is not an issue (you are on a trusted network etc), you can bypass the host checking. And if you use key-based authentication there is no need for a password prompt:
ssh -oUserKnownHostsFile=/dev/null -oStrictHostKeyChecking=no -oPasswordAuthentication=no \
-n doctor#tardis some_cmd
This way you can just use subprocess as if you executed some_cmd locally.
I'm trying to integrate gitpython with an IDE, but I'm having some problems with push.
remote_repo = self.repo.remotes[remote]
remote_repo.push(self.repo.active_branch.name)
When I run this command, or just
git push --porcelain origin master
the prompt asks my ssh password.
Enter passphrase for key '/home/user/.ssh/id_rsa':
My problem is:
the prompt may ask or not this password
If a password is required, I need a cross platform solution
How can I workaround it and provide an interface to identify if a password is necessary, and if so be able to provide it?
The cross-platform solution is for you to launch first the ssh-agent and calling ssh-add.
See also "How can I run ssh-add automatically, without password prompt?" for other alternatives like the keychain.
if [ -z "$SSH_AUTH_SOCK" ] ; then
eval `ssh-agent -s`
ssh-add
fi
That will ask you for the passphrase, and store it.
Any subsequent ssh calls which would need the ssh private key (using gitpython or any other tool) wouldn't require to enter the private key passphrase.
In case you would like to have full control over how an ssh connection is made, and if you use git 2.3 or newer, you may instantiate git with the GIT_SSH_COMMAND environment variable set. It points to a script which is called in place of ssh. Therefore you are enabled to figure out whether or not a password is required, and to launch additional GUI to obtain the desired input.
In code, it would look something like this:
remote_repo = self.repo.remotes[remote]
# here is where you could choose an executable based on the platform.
# Shell scripts might just not work plainly on windows.
ssh_executable = os.path.join(rw_dir, 'my_ssh_executable.sh')
# This permanently changes all future calls to git to have the given environment variables set
# You can pass additional information in your own environment variables as well.
self.repo.git.update_environment(GIT_SSH_COMMAND=ssh_executable)
# now all calls to git which require SSH interaction call your executable
remote_repo.push(self.repo.active_branch.name)
Please note that this only works for accessing resources via SSH. In case the protocol is HTTPS for example, a password prompt might be given anyway.
Prior to git 2.3, you can use the GIT_SSH environment variable. It works differently as it is expected to contain only the path to the ssh program, to which additional arguments will be passed. Of course, this could be your script as well similar to what was shown above. I'd like to point out the differences between these two environment variables more precisely, but am lacking the personal experience to do so.
In my sublimetext plugin I have to make a secure http call to fetch some data. For this I want to access mac's keychain to get username and password.
Keyring seems to do the job:
https://pypi.python.org/pypi/keyring#installing-and-using-python-keyring-lib
Should that be my way ahead? Or are there any native mac apis?
There is the security command-line interface. In fact, it looks like keyring just wraps this command to make it more user-friendly.
You're probably looking for the find-internet-password subcommand. For example, you can run
security find-internet-password -w -a my_account_name -s my_server_name
(with the appropriate substitutions for your account and server). The first time (at least) that you run this, OS X should pop up a little window asking if it's okay. If you click "Allow" or "Always Allow", it will output the password as a string. So you probably want whatever scripting interface you have to store it as a variable.
Is it possible to create a raw socket without root privileges? If not, can a script elevate its privileges itself?
I wrote a Python script using a raw socket:
#!/usr/bin/env python
import socket
rawSocket = socket.socket(socket.PF_PACKET, socket.SOCK_RAW, socket.htons(0x0800))
print "Worked!"
Running it with root privileges prints Worked!. However, it gives an error when run with normal user privileges.
I want to execute my script as a normal user, and it should create a raw socket without asking for anything. Is it possible?
As you noted raw sockets require higher privilege than a regular user have.
You can circumvent this issue in two ways:
Activating the SUID bit for the file with a command like chmod +s file and set its owner to root with chown root.root file. This will run your script as root, regardless of the effective user that executed it. Of course this could be dangerous if your script has some flaw.
Setting the CAP_NET_RAW capability on the given file with a command like setcap cap_net_raw+ep file. This will give it only the privileges required to open a raw socket and nothing else.
EDIT:
As pointed out by #Netch the given solutions will not work with any interpreted language (like Python). You will need some "hack" to make it work. Try googling for "Python SUID", you should find something.
There is not a way for an unprivileged process (Python or otherwise) to elevate their own privileges. It's kind of the cornerstone of having this whole privileged/unprivileged users thinga-ma-jig. In regards to raw sockets, from manual page raw(7):
Only processes with an effective user ID of 0 or the CAP_NET_RAW capability are allowed to open raw sockets.
User ID of 0 means root. See here for info about raw sockets on linux.
As pointed out in Faust's answer/comments you won't be able to directly set the CAP_NET_RAW capability for your python program, due to it being a script that gets executed by the Python interpreter, but there may be solutions out on the web that can get around this limitation.
You can also go another path and set up the application using the sudoers file, then run it via sudo
Or my preferred option is just to compile it with Nuitka, then it runs like any other executable and can be assigned run as root etc
I'm tired of doing this.
ssh me#somehost.com
input my password
sudo su - someuser
input my password
cd /some/working/directory
<run some commands>
Is there anyway to automate this? Do I need a special shell? or a shell emulator? can I programmatically drive the shell up to certain point then run manual commands on it?
Bonus points of it's programmed in python for extra hacking goodness
edit: All the answers below focus on the "full automation" part of the question: Where the hard part is what I highlighted above. Here is another example to see if I can capture the essence.
ssh me#somehost.com
<get a shell because keys are setup>
sudo su - user_that_deploys_the_app
<input password, because we don't want to give passwordless sudo to developers>
cd env; source bin/activate
cd /path/where/ur/app/is/staging
<edit some files, restart the server, edit some more, check the logs, etc.>
exit the term
For the ssh/authentication piece, you can setup passwordless authentication by using keys. Then you can simply use ssh and a bash script to execute a series of commands in an automated fashion.
You could use Python here, but if you are executing a series of shell commands, it's probably a better idea to use a shell script, as that's precisely what they do.
Alternately, look into Fabric for your automation needs. It's Python-based, and your "recipes" are written in Python.
I'm not quite sure what you're asking, but what you're probably asking about is getting SSH working in password-less mode using public keys. The general idea is you generate an SSH keypair:
ssh-keygen -t rsa
which gives you id_rsa and id_rsa.pub. You append the contents of id_rsa.pub to the ~/.ssh/authorized_keys file of your target user, and SSH from that point on will not ask for credentials. In your example, this will work out to:
Only once
# On your source machine
ssh-keygen -t rsa
cat ~/.ssh/id_rsa.pub
# Copy this to clip board
# On somehost.com
su - someuser
# edit ~/.ssh/authorized_keys and paste what you had copied from previous step
From now on, you can now just run
ssh someuser#somehost.com "sh -c 'cd /some/dir; command.sh'"
and not be prompted for credentials.
fabric is a fine choice, as others have pointed out. there is also pexpect which might be more what you're looking for.
You can play with autoexpect. It creates expect script (script language intended to handle interaction with user). Run
autoexpect ssh me#somehost.com
followed by rest of commands. Script script.exp will be created.
Please note, that exact results of input and output will be recorded by the script. If output may differ from execution to execution, you'll need to modify a bit generated script.
As Daniel pointed out you need to have a secure way of doing ssh and sudo on the boxes. Those items are universal to dealing with linux/unix boxes. Once you've tackled that you can use fabric. It's a python based tool to do automation.
You can set stuff up in your ~/.ssh/config
For example:
Host somehost
User test
See ssh_config(5) for more info.
Next, you can generate a SSH key using ssh-keygen(1), run ssh-agent(1), and use that for authentication.
If you want to run a command on a remote machine, you can just use something like:
$ ssh somehost "sh myscript.sh ${myparameter}".
I hope this at least points you in the right direction :)
If you need sudo access, then there are obvious potential security issues though ... You can use ChrootDirectory on a per user basis inside a Match block though. See sshd_config(5) for info.
try module paramiko. This can meet your requirement.