Im currently using a java application to run commands on a unix box by invoking an instance of the bash as follows --
proc = Runtime.getRuntime().exec("/bin/bash", null, wd);
and Im executing commands on the box by Printwriter as follows --
PrintWriter out = new PrintWriter(new BufferedWriter(new OutputStreamWriter(proc.getOutputStream())), true);
Now, as a requirement I need to ssh onto another host, invoke an instance of that host's bash and run some commands. If this can be done without having to enter the password, it would be great. If not, how do I make the application to enter the 'password' at the right time? Reading the output of the shh command and based on that, writing out the password does not seem appealing.
Any pointers on the above would be of great help.
Regards
p1nG
Use a ssh-library written in Java instead of runtime-exec'ing a ssh program.
You can use SSH-2 for java, which seems to be actively maintained.
Alternatively, set up a pubic/private key for password-less authentication, and store the private key in the ~/.ssh folder of the user running the java program.
You can setup password-less SSH authentication. Here is a step by step guide for setting up the same.
http://manjeetdahiya.com/2011/03/03/passwordless-ssh-login/
I can't imagine how you're going to avoid supplying a password. If you could log in to a system without supplying a password just by somehow telling it that supplying a password would be inconvenient for you, this would rather destroy the value of any security. Security Guard: "Do you have an ID that allows you access to this building?" Visitor: "Yes officer, but it's too much trouble to get it out of my wallet." Guard: "Oh, okay then, go rght ahead in."
Rather than exec'ing, you probably want to establish a socket connection and pass messages back and forth cleanly. Or as others have noted, use a library that does the grunt work for you.
Related
I am maintaining an application in our company (written in C#), which runs on a jumphost and provides the functionality to search across different servers and initiate a PuTTY connection to that server. For this the application currently starts the PuTTY process and passes arguments, like the hostname, username and password. The password for each server is retrieved from a password manager service. The arguments are passed to PuTTY through the command line interface. So the purpose of the application is to automate password retrieval and login to different servers.
The problem with the current approach is, that in the Windows Task Manager its possible for an administrator to see all started PuTTY instances and the corresponding credentials as command line arguments.
So far I haven't found any practical solution to circumvent this. These are the things I researched so far:
Instead of passing password argument, using SendKeys to type password into the promt: Unreliable, as there is no way to read the PuTTY output and know when the application is ready for the input to be typed in.
Using Plink instead of PuTTY and passing arguments through stdin: Plink supports stdin / stdout communication, however the terminal functionality is very limited and not usable in practice after the login was successful.
Modifying PuTTY to mask password: I have seen some suggestions, to modify the PuTTY source code, to overwrite the password in the main args, once the application started. However, this solution seems to only work on Linux, not Windows.
Using SSH.NET library to provide my own SSH terminal implementation: The SSH.NET library seems to be similarly to Plink more suitable for issuing commands programmatically, but not for opening a terminal for the user. I guess it would require a lot of work to implement a full terminal.
Some ideas, that might work:
Modify the PuTTY code, so that arguments can be passed through stdin: Could work, but I don't know how easy that would be, as I don't have very good C knowledge.
Use an alternate client, that supports stdin output. The Java library JSch looks quite powerful and seems to already include a terminal. Would it be possible to create a standalone application, that can a receive stdin and use that to open a terminal and auto login?
Any further suggestions would be greatly appreciated. Are you aware of any other Windows alternative to PuTTY, which supports passing credentials in a more secure way?
Following the suggestion of Martin Prikryl I was able to create a minimal example, which creates a NamedPipe in C# and passes it as a pwfile argument to PuTTY:
public void CreatePipe()
{
var server = new NamedPipeServerStream("SecretPipe");
server.WaitForConnection();
StreamWriter writer = new StreamWriter(server);
writer.Write("top!!secret");
writer.Flush();
server.Dispose();
}
Then PuTTY can be started as follows with the pipe as pwfile argument:
putty.exe -l testuser -pwfile "\\.\PIPE\SecretPipe" hostname
Since 0.77, PuTTY can read the password from a file using -pwfile switch.
when I run kinit ganesh#abc.com it asks for the password when I run through the terminal. I am trying to build same as web application using java
Acceptance criteria:-
password should pass through UI and we should able connect to the server. i.e password which we pass through UI should assign asa password.
I would recommend you to use Jsch, you can find this library here
http://www.jcraft.com/jsch
And an example or ssh connection here
http://www.jcraft.com/jsch/examples/Shell.java.html
If you're using OpenSSH ssh client, you can try implementing passing password via a companion program, specified via SSH_ASKPASS variable. Basically, you need SSH_ASKPASS to point to a binary ssh would run, and that binary must output the password on stdout.
Check this answer: How to make ssh receive the password from stdin for more details and a concrete example.
The downside is, you need an external binary - and you need to think about its security. For example, if the binary is a dynamically-generated shell script in /tmp - you need strict filesystem permissions so no one but your ssh child process can read or execute it. And if the binary itself is static and takes password from, for example, an environment variable, you must make sure that SSH won't accidentally pass this variable to remote host (e.g. via accidentally specified SendEnv).
You can use some Java SSH library (like suggested Jsch - there is a list here: SSH library for Java), if that fits your requirements. It should be the most flexible option - in terms of control you have over SSH client behavior, unless you want something Jsch doesn't support.
Also, I'd strongly suggest to consider not using passwords, but your server having a private key, and servers you connect to appending its public key to ~/.ssh/authorized_keys (unless you need password-based logins for exactly this purpose, of course). If that's a feasible scenario, you can avoid sharing any sensitive information entirely, significantly improving the security.
I am writing a Java program that can programmatically SSH into any remote machine and execute commands. I am re-using an existing Java library to do so: https://github.com/shikhar/sshj
The issue I am running into is figuring out how to sudo switch user as such:
"sudo su - [username here]".
If you run this manually in the terminal, you will be prompted with a password. As I understand it, if you are under the sudoers file, and you type your password correctly, you will be able to run the command to switch the user as such. I don't want to have the user to have to type in their password. Ideally, the program shouldn't require any human intervention at all in order to run.
What I would like to achieve is: Programmatically send the password over the socket so the user wouldn't have to type it into standard in. If the user can login to the remote machine using his credentials, the program should be able to pick up on these same credentials and pass it in when sudo asks for a password from the user.
After Googling for a while, I can't figure out how to achieve this with this library. Bare in mind I am not really an expert at the lower-level details of SSH. Anyone have an idea on this one?
Thanks guys.
We've written the Overthere library on top of SSH/J, which supports logging in with sudo with or without a password prompt. Have a look at that to see whether it suits your needs.
That shouldn't be a problem. You can configure sudo to don't require a password for certain users. Have a look at sudo's documentation and sudoers man page.
I am making a Java based form desktop app, a mini login form, that will be able to login into a grand system which is online in asp.net.
The purpose of this app is to install on pcs, and whereever this exe is installed, the website could be logged in, other wise not.
The problem is, i have put the connection string of sql server in it, and employees will install this app on their machines, there is a tool available which decompile JAR and classes. And when i checked my classes in it, it was showing my sql server password. And it can give a chance to them to hack this app, this is really dangerous for us to provide them or give them a chance to get sql server password.
Can you please help, is there any such solution that i could give MD5 encrypted password or some encrypted password in connection string and sql server could be able to understand it.
Thanks
There are a few ways you can handle this.
the user info in your connection string should be limited to execute exactly one procedure: the one that tests if the MAC address is valid. This limits exposure. Not in an ideal way, but it's something.
Don't send a connection string at all. Instead have the java application post the mac address to a web service. The service should connect to the database server to determine authorization. Better than option 1.
Even better: Don't rely on MAC addresses. If you are worried that someone will look at the connection string then it stands to reason they might change their MAC address to mimic another machine. It stands to reason that anyone familiar enough to directly connect to a database server will also be familiar enough to download one of the many freely available tools to spoof their MAC.
Which leads to a comment: I think your doing this wrong. If the entire purpose of the java app is to simply read the MAC to validate whether that particular machine should have access then you have some serious issues with understanding security and I think you really need to evaluate what, exactly, it is you are trying to stop.
You can use integrated authentication, provided that the database server is in the same active directory domain as your users. Simply specify Integrated Security=SSPI in your connection string and grant regular users rights corresponding to what you want them to be able to do in the database (for example, read only access), but no more.
Currently, I am able to authenticate users in a java application by using JAAS and grabbing the ticket-granting-ticket that is sent from a Windows server running Active Directory. This is easily done with the Krb5LoginModule in java.
Now I would like to run an ssh command from my java application and use my TGT to enable ssh not to ask for password. I have seen some tutorials (OpenSSH & Kerberos) for getting ssh to work with kerberos, but they use kinit to get their TGT and the ticket is stored in /tmp/krbcc_XXX. Then after the ticket is generated they can ssh freely.
I could write the TGT to disk and store it in /tmp/krbcc_XXX or I could run the ssh command in a PrivilegedAction, however I don't know if either will work. Is there an accepted way to do this?
Basically, I would like to call something like this and have it not ask me for a password:
// Create Command.
List<String> arguments = new ArrayList<String>();
arguments.addAll(Arrays.asList("ssh", "user#host", "xterm"));
// Run SSH command.
ProcessBuilder process = new ProcessBuilder(arguments).start();
You have to clarify first who will initiate the SSH request. Java or the underlying Linux/Unix system. If you go with the latter, this is not cross-platform and not the Java way. You should use a Java SSH impl which supports Keberos. Everything should go smooth. JSch is a pure Java impl with gss-api-with-mic support.
On the other hand, you could try to get the private credentials from the Subject created with the LoginContext and write it to the default CC file location.. After you have done that, try klist. If it reads the cc file, you're done. If this does not work, you could examine Sun's CC reader code and reverse it. Probably, the sun.security.krb5.internal.ccache.FileCredentialsCache is the interesting one along with its update and save methods. The task is to have the private subject credentials be compatible with the desired class sun.security.krb5.internal.ccache.Credentials.
Note: This solution is completely Sun-dependent. I would go for the first approach or you rather run kinit first.