My java web application is deployed on server machine. I have a share drive which is accessible from client machine as well as server machine . Using below code i am able to open that drive on server machine :
Spring Controller code :
#RequestMapping(value = "/openAttachment", method = RequestMethod.POST)
public ResponseEntity<List<String>>
OpenFolder(#RequestParam("workflowName") String workflowName ) throws
IOException, InterruptedException {
String folderPath =Constants.workFlowAttachPath+workflowName;
if ((new File(folderPath)).exists()) {
Process p = Runtime
.getRuntime()
.exec("rundll32 url.dll,FileProtocolHandler "+folderPath);
p.waitFor();
}
List<String> msgList = new ArrayList<> ();
msgList.add(Constants.SUCCESSFUL);
return new ResponseEntity<List<String>>(msgList, HttpStatus.OK);
}
Constant used here is :
public static final String workFlowAttachPath="\\\\10.82.31.27\\Area20\\Attachment\\";
But i am unable to open this folder from local machine(browser) on local machine .
Is this possible ? If possible then how ? Thanks in advance.
No, you can't do that. If you're okay with hardcoding windows and system state into your code, you can mount that folder on a drive letter, say, drive 'N:', and then use path:
psf String workFlowAttachPath = "N:\\Attachment\\";
you can mount this on windows with something like:
net use N: \\\\10.82.31.27\\Area20 /PERSISTENT:YES
but I'm just going off of memory on that one so you'd have to check the docs on the net use windows command for the details. You should be able to invoke 'net.exe' via Runtime.getRuntime().exec() but I advise against that. You're already hardcoding IPs and who knows what in this code, might as well take care of mounting the N: drive externally too. This avoids having to deal with errors from the net command from within your java code, which is notoriously hard; windows likes to translate its commands and can throw quite a few weird errors, writing code to invoke windows utilities from java and understand their outputs is a non-trivial job.
Related
I am trying to do hp fortify security scan for my java application. I have few issues and i have fixed it. But i am unable to find the fix for the below issue.
Command Injection
String hostname = execReadToString("hostname").split("\\.")[0];
public static String execReadToString(String execCommand) throws IOException {
try (Scanner s = new Scanner(Runtime.getRuntime().exec(execCommand).getInputStream()).useDelimiter("\\A")) {
return s.hasNext() ? s.next() : "";
}
The method execReadToString() calls exec() to execute a command. This call might allow an attacker to inject malicious commands.
So i have tried with process builder also.
private static void gethostname(String cmd1) throws IOException {
if(Pattern.matches("[A-Za-z]+", cmd1)) {
ProcessBuilder pb = new ProcessBuilder(cmd1);
Process p = pb.start();
BufferedReader reader = new BufferedReader(new InputStreamReader(
p.getInputStream()));
String readline;
while ((readline = reader.readLine()) != null) {
System.out.println(readline);
}
}
}
Even this is giving me an security issue This start() call might allow an attacker to inject malicious commands.
What will be the ideal fix for this issue?
Thanks in advance
Usually this is because you're using user input to frame the command string, wherein user can inject malicious code to manipulate what command is being run ultimately (even if you add validation there will be ways to circumvent that).
In your case you seem to be hardcoding the command so this shouldn't be a problem, however, see the OWASP page on hardcoded command invocation (emphasis mine):
Unlike the previous examples, the command in this example is
hardcoded, so an attacker cannot control the argument passed to
system(). However, since the program does not specify an absolute path
for make, and does not scrub any environment variables prior to
invoking the command, the attacker can modify their $PATH variable to
point to a malicious binary named make and execute the CGI script from
a shell prompt. And since the program has been installed setuid root,
the attacker's version of make now runs with root privileges.
The environment plays a powerful role in the execution of system
commands within programs. Functions like system() and exec() use the
environment of the program that calls them, and therefore attackers
have a potential opportunity to influence the behavior of these calls.
Resolution:
Use native Java APIs / libraries to achieve what you want, instead of running a command - this is probably the best option. Use commands only when unavoidable, eg: 3rd party tools which do not have a Java client library. This approach has the added advantage of being more portable and in most cases, more efficient too. This library might help your scenario.
If you have to run a command, ensure you do not use user-supplied or external data even indirectly to construct it.
Or if you're hardcoding the command to run from the code, use absolute path to the command and do not use environment variables as part of it. For hostname (assuming you use the built-in command) this is usually /usr/bin/hostname but you can find the command path for your environment using which hostname.
I'm setting up a form on my website. I want the PHP code that handles emailing info about the form to me to also run a java program printing information about it. Here is my PHP code
$name = $_POST['name'];
$email_address = $_POST['email'];
$date = $_POST['date'];
$time = $_POST['time'];
$message = $_POST['message'];
$info = array($name, $email_address, $date, $time, $message);
exec('java -jar "C:\SomePathTo\HelloWorld.jar" $info 2>&1' , $output);`
var_dump($output);
And my Java code
public class HelloWorld {
public static void main(String[] args) {
for(int i = 0; i < args.length; i++) {
System.out.println(args[i]);
}
}
}
When my website runs this code I get the following output/error message
array(1) { [0]=> string(197) "Error: Unable to access jarfile C:\SomePathTo\HelloWorld.jar" }
Help!
Obviously, the backslash escaping is not a problem, for the error message lists correct backslashes. If the problem was about backslashes, this would not be the case. (You used single quotes, which strips backslashes of their special meaning.)
Furthermore, we can notice that whatever generated the error message knows that it is looking for a "jarfile". What, in your stack, does that? It is not PHP; it is not the operating system's kernel. Apparently, you are getting Java VM to run. That's probably a good thing.
Why can't the Java VM access your jar file? You might have misspelt its name, but this would be something so obvious that it would have come up when you double-checked the code. It is more likely that this happens because the jar file is somewhere deep in your home directory (I can conclude "deep" from the fact that when you sanitised the filename, you kept the error message's length of 197) where the user context of the Java VM can't read. As you're running PHP through a web server, this would be determined by your web server's configuration, but it is fairly common to have a dedicated user account named something like "www-data" or "Internet Scripts" under which the code runs. You should find out which it is on your system.
Once that has been done, you have a few options. You can grant the user running your PHP (and in this context, Java VM) read access to the jar file. As soon as your jar file wants to access other files, you'll also need to let that user account to access those files, too. (Just make sure it can't overwrite or delete anything important.) Alternatively, you could reconfigure your web server (or ask your web server's administrator to it) so that it would run scripts written by you in your user context.
I've seen plenty of examples of how to prevent Java applications, such as locking a file or creating a socket.
How do I allow multiple instances to run, but check if another one is running?
The reason I need to do this is that I want to clean a temporary folder on exit, but not if there is another process running.
You can use attach API and check for running virtual machines like explained in this blog entry
The other manner of acquiring a VirtualMachine is to ask for the list of virtual machines known to the system, and then pick the specific one you are interested in, typically by name:
String name = ...
List vms = VirtualMachine.list();
for (VirtualMachineDescriptor vmd: vms) {
if (vmd.displayName().equals(name)) {
VirtualMachine vm = VirtualMachine.attach(vmd.id());
String agent = ...
vm.loadAgent(agent);
// ...
}
}
You can use any IPC you like. For example, create /tmp/you_app_name_flag.$$ files ( $$ means pid ) and verify existance of /tmp/you_app_name_flag.* on your app's start.
As above.
I have scoured the web, i also rang mac support and annoyed a mac (OSX Lion) genius (out of desperation).
I have no idea how to do this, I really don't want to have to sit on top of a terminal and give it commands.
Has any one encountered this or got a solution?
Try looking at Greg Guerin's AuthKit library. It is a Mac-specific library that wraps Mac OS X Authorization Services.
Here is an example:
import glguerin.authkit.*;
Privilege priv = new Privilege("system.privilege.admin");
Authorization auth = new MacOSXAuthorization();
try
{
// This will cause an authentication prompt to be
// shown to the user, requesting the "system.privilege.admin"
// privilege.
auth.authorize(priv, true);
// If we reach this point, we can execute privileged programs.
// Load the secured file.
Process proc = auth.execPrivileged(new String[] { "/bin/cat", "/root/securefile" });
InputStream inputStream = proc.getInputStream();
// Use standard I/O mechanisms to read the input.
}
catch (UnauthorizedCancellation e)
{
// User chose not to authorize the application.
// Handle appropriately.
}
The auth.authorize() call will cause the standard "Please enter your password to allow program X to make changes" dialog. The user can cancel if desired, causing glguerin.authkit.UnauthorizedCancellation to be thrown.
This solution has a huge advantage over using sudo or setuid: it only runs the necessary tasks as root.
One last gotcha: the default JNI loader for AuthKit uses the Cocoa/Java bridge, which was removed from Mac OS X as of Snow Leopard. So on recent versions of Mac OS X, the code above will fail with UnsatisfiedLinkError. To work around this, use the following:
// Put this class somewhere:
public class AuthKitLibLoader extends LibLoader
{
#Override
protected File makeFallbackDir()
{
return new File(".");
}
}
// Then, before calling AuthKit (using the above example), do this:
// Hook in our "Snow Leopard-safe" extension to AuthKit (see below).
System.setProperty("glguerin.util.LibLoader.imp", AuthKitLibLoader.class.getName());
Finally, be sure to read the AuthKit documentation for more detail.
If you run the application as the root user, the application will have full access to everything.
This is a dangerous operation however because it gives the application full privileges.
Another option would be to run it as a user that has the needed permissions to the files in question. This can be done by putting the user or the files in the appropriate group.
You probably need to SETUID the application to root.
> su
Enter password:
> chown root:wheel myJavaApp
> chmod ug+s myJavaApp
> exit
Now whenever someone in the wheel group runs myJavaApp, it will run as its owner (root). Just make sure you're in the wheel group (or whatever other group)
Alternatively, you could chmod a+s myJavaApp ... but that would let ANYONE AT ALL run the program as root. I would think carefully about that.
I,m looking for some method that can let me obtain (in windows) the directory where windows is saved (for example in my PC it will return "C:\windows".
I need it because I have to call this method
public static void openFileWithNotepad(String pathFileTxt) throws InterruptedException, IOException
{
if(System.getProperty("os.name").toUpperCase().contains("Windows".toUpperCase()))
{
String program = "C:/WINDOWS/system32/notepad.exe";
Process p = Runtime.getRuntime().exec(program + " " + pathFileTxt);
}
...
}
I want to use some method to switch "C:/WINDOWS" with the OS installation folder, in order to use this program on different pcs.
P.S.: If someone know, I'd like also to know how to use this method on UNIX OSs :)
Thank you for understanding!
Desktop.getDesktop().open(new File(pathFileTxt));
Works for any file for which there is an associated program, on any OS that supports Java 1.6+. See Desktop.open(File) for details.
i believe this should work:
System.getenv("WINDIR")
also, notepad doesn't tend to exist on unix, so i'm not sure where you are going with that...
try
System.getenv("windir")
for windows.
I'm not sure about other OSs.
System.getenv("WINDIR") may work for you.