Security Concerns with Runtime.exec() - java

I am using Runtime.exec() to run an executable file. I have been researching and found out that there could be security concerns when using this in a application. Are there any security concerns when using Runtime.exec() to run an executable file?

#Jeanne Boyarsky: Apparently you cannot inject into Runtime.exec() in the way you mentioned, unless Runtime.exec() first spawns a shell (cmd.exe on Windows or sh/bash/csh/ksh on Linux) to run the command. Here is a good link which talks about this.
I wrote a small program to test this out. It takes a command as user input. So if I enter 'pwd' (Linux system) it will print the current directory to the System Console. This works perfectly.
If however I try and run two commands, as is permitted in Linux, such as pwd;id it throws an Exception straight away. The Exception thrown is as follows.
javax.faces.el.EvaluationException: java.io.IOException: Cannot run program "pwd;ls": error=2, No such file or directory
Having said that though there is a situation when this can be a problem. If I have a piece of code as follows:
Process proc = runtime.exec(cmd);
... the user could provide an input of sh -c pwd;id, thus causing a shell to run and then chaining commands inside it.
So in short, best to not use Runtime.exec() if you can help it. If you MUST use it, make sure you canonicalize all user input and allow only specific characters and commands.
Here is a good read on how to write secure code.

The biggest one I can think of is Command Injection. YOu want to whitelist what gets run so someone can't run "rm /" via your Runtime.exec. There are more ways for this to happen than you might think. For example what if a "directory" name is passed in as "foo; rm -r ; ls".
Another one - if this is a web application - is that the permissions for the application (and therefore your Runtime.exec() command line aren't the same as what the person hitting the web page has. Which means the person could delete your Tomcat or insert data into a database or ...

Related

Using 'become' command in Java JSch program to access a restricted directory

Working with Unix server... My requirement is to read the name of the file that is there at /a/b/c/node01/d.ear location on a Unix server and I have do the same through a java program. The problem is that the directory a is a restricted directory and is accessible only to certain users. On the Unix side, I first issue a become command like become a, then supply the password and then using cd command, I reach the d.ear directory and then get to see the name of the file.
How do I do all of this via a Java program?
I don't mind if my Java program calls a shell script that accesses the restricted directory and then reach d.ear and fetch the name of the file and returns the same to the java program. Do we have a way of doing this? Maybe issuing the become command inside the script which is called from the Java program and the password which is asked after become command is supplied as a parameter while calling the script???
Is this approach doable? I am very new to Unix commands and JSch library. Kindly provide the code or any other alternate solutions...
Thanks!!!
As I have suggested you already, your become command seems to behave the same way (from an interface/API point of view) as common *nix su or sudo.
So, use the same solution as for those. There are many questions on Stack Overflow covering use of su/sudo with JSch.
There's even an official JSch example Sudo.java:
http://www.jcraft.com/jsch/examples/Sudo.java.html
In short:
Execute become command
Feed a password to its input
Assuming the become starts a new shell (as su or sudo do), you feed the commands to be executed in the elevated environment to become input (the same was as the password).

How to write to OS system log in Java?

Mac OS has an application called Console, which contains logged messages, errors, and faults. I believe the Windows equivalent is Event Viewer. I'd imagine there is one on Linux as well, but I don't know anything about it or where it is.
Is it possible to get a message from Java output to a system log like this? I'm writing a GUI-based application, so there is nothing running from the command line. The standard System.out or System.err probably won't be of much use in this case, unless I'm missing something.
I have written a simple logging service for my application that writes to a dedicated log file, but I want to have some kind of failsafe in case an I/O error occurs while attempting to write to this file.
I know the IDE will display output via System.out and System.err just fine, but this is for if the end-user encounters a problem like this.
As an example: I've written "codeless language modules" for the application TextWrangler on the Mac. These modules are read by TW at application startup, and if there is an error while processing them, errors get logged and can be viewed in the Mac Console application.
On Linux it is called as syslog. One of the ways that you can achieve logging to console on Mac will be to use log4j 'org.apache.log4j.net.SyslogAppender'.
I think this link should give you some kickstart in this direction.
You can redirect System.out to a log file, and Mac's Console app is the default viewer for files ending in ".log".
One way this is commonly done is with a shell script that would invoke your Java program. In this Java 7 example, the output of invoking the main class MyClass is redirected to mylogfile.log. Everything that's written with System.out will be in mylogfile.log.
#!/bin/bash
for a in /path/to/my/jars/*
do
CLASSPATH=$CLASSPATH:$a
done
java -Xms128M -Xmx128M -XX:MaxPermSize=128M -cp ${CLASSPATH} com.example.package.MyClass >> mylogfile.log

How do I write to the input stream of an already running java program?

I have a CentOS server which is currently running a java jar application. I need to write a php script to communicate with this running program via its input stream. The java program outputs its output to a log file so I don't need access to the output stream.
I don't want to restart the program, just access the running process and interact with it.
Can someone point me in the right direction?
If portability is not a big matter for you, why not creating your own pipe(s)? I don't know much about the java application but have a look at the "mkfifo" function/command.
First, find the ProcessID of the application. You may do it using:
ps -Af | grep java
Since you are using java, you may feel more convenient with the jps command for finding the PID.
I'll assume PID of the running application is 12345. It suffices to issue the command:
cat >/proc/12345/fd/0
And whatever you type in will be put in the standard input of that application. Note that fd contains the file descriptors used by the application, and I suppose the 0-th file descriptor would always be stdin.
Using PHP for writing into the file (and thus being consumed by the application as input) is possible as well.

Creating a console in Java

When I try to use java.lang.System.console(), I get a null pointer. I can still write to out and read from in, but this only works when I run straight from my IDE. When I run the .jar file directly, nothing happens. How can I create a console like I'd see using std::cout for use in Java?
Edit:
I was hoping to just create one, rather than understand why I don't have one, since I need one for my program's operation.
Perhaps you're trying to get the console by double-clicking in the jar
Try creating a batch file that opens the console for you.
You can however create a console using Swing and redirect standard input/output there.
Source: Create Java console inside a GUI panel
How are you running the JAR file exactly? That would be the expected behavior for double-clicking its icon in Windows Explorer, as Kelly alluded to, but not for firing it up from the command line.
From the Console entry in the API (emphasis mine):
Whether a virtual machine has a console is dependent upon the underlying platform and also upon the manner in which the virtual machine is invoked. If the virtual machine is started from an interactive command line without redirecting the standard input and output streams then its console will exist and will typically be connected to the keyboard and display from which the virtual machine was launched. If the virtual machine is started automatically, for example by a background job scheduler, then it will typically not have a console.
java.lang.System.out and java.lang.System.in are the input/output streams for console access. Java won't create a "console" but allows you to interact with the IO streams provided by the operating system.
When you run it from a jar file (like clicking on it from a folder) you'll get the I/O streams of the GUI which don't display anywhere.
Try creating a batch file with a 'java -jar ' command in it. When you run the batch file, you should see the command window. I'm assuming windows here. Another way is to run cmd.exe directly with arguments that keep the window open, i.e. "cmd.exe /c".
Instead of running the jar file directly, open a console (you didn't specify an operating system, but this would be the command line on Windows and a console on *Nix, or Terminal on OS X). Then, run java -jar /path/to/your.jar.
The equivalent of std::cout in Java would be System.out as you probably already know.
EDIT: With regards to your edit, there is code out there to do this. For example, you can use Swing. There's even a StackOverflow answer with more than one working code sample.
See JConsole, which is a general console in java, used for instance by groovy. Or see groovy directly.

Permission error while trying to access an (server) program started by a Java program

I am starting a server application (normally to be started from the Unix command line) by using Runtime.getRuntime().exec("path/mmserver"). My problem is now that as long as my Java program, which started that server runs, the server is correctly accessible (from command line and other programs). But when my Java program exits the sever is not accessible anymore (the process of the server is still running). I just get such a error message when trying to access the server: "Error: permission_error(flush_output(user_output),write,stream,user_output,errno(32))".
The server is a blackbox for me.
I am just looking for other ways to start a new process. And maybe someone has a hint why I get that permission error (even if one doesn't know what that server exactly is ... you rather won't know it).
I'm guessing your server program is trying to write to standard output or perhaps standard error (System.out / System.err in Java terms) which it implicitly inherited from your Java program but which turn into pumpkins when your Java program goes away.
A simple solution might be for your Java program to exec a shell script which starts your server as a background process (using START (Windows) or & (Unix)) with explicitly redirected I/O streams.
The Java library has recently gotten some nice updates to the Process class (I think) that allow you to do a lot of fiddling with the streams, but I don't have much experience there so I can't offer a detailed suggestion.
EDIT: My suggestion from the middle paragraph. Untested, sorry!
File server-runner.sh:
#!/bin/bash
/path/mmserver >/dev/null &
You'll need to chmod +x server-runner.sh, of course.
Then, from your Java program, you exec the script server-runner.sh rather than your mmserver.
If you want to kill mmserver, you'll have to find it in ps -ux and use kill on the process number.

Categories

Resources