Java security vulnerability OS Injection Veracode - java

I receive a Veracode error when running the static scan: Improper Neutralization of Special Elements used in an OS Command ('OS Command Injection') (CWE ID 78)
The application calls a process with an argument that I receive from the frontend (the application is used internally and this is a userId) .
ProcessBuilder pb = new ProcessBuilder(PROCESS, "-A", argument);
Process p = pb.start(); // Veracode is mentioning this line
How could I manage to fix this Veracode issue ?
Is there a 'safe' way to run a process?

Presumably your userId has a well defined format (numbers, hexadecimal digits, alphanumeric, ...), perhaps it is always the same length.
You have to verify it by matching userId to the appropriate class of characters via regex, and reject anything which is not complying, otherwise, you are open to the following attack:
Enter Username: diginoise; rm -rf /

Sounds like it's an architectural problem in your application. I'm pretty sure you don't want to execute a supposed userid passed by the user as a request parameter as an OS command. This would be OS command injection by design.
The ideal solution would be to avoid creating a new OS process and use built-in Java functionality to achieve your goal.
If you do have to run an external process, do not include user input into what you are running. For example if you had the static string ps aux to run and would do the "grep" bit in Java, the Veracode finding would go away and it would be a lot more secure.
If you absolutely must include user input, make sure it is very strictly validated. Note that for OS command injection, letters only may sometimes be enough, and Veracode will correctly flag that as vulnerable, despite validation being in place. In this case, if you are sure that with your validations, it is not possible to run anything malicious, you can mark the finding in Veracode as "mitigated by design".

Related

Sonar violation properly sanitized before use in this OS command

In my project i got a sonar security violation-properly sanitized before use in this OS command. I have done the pattern check for my inputs, but still the violation is not going away.
if(Pattern.matches("[0-9]+", empNp)){
ProcessBuilder processBuilder = new ProcessBuilder(exeLoc, folderPath, empNp);
It still keeps complaining the empNp is not properly sanitized. Could you please let me know how to handle this. I cannot hard code the empNp because it is dynamic input.How to handle this.
The point of many of the security rules is to draw attention to something that requires human intelligence to determine whether or not the code is truly safe. If you're sure the input has been properly sanitized, then mark this issue False Positive and move on with a clear conscience.

How to validate a filename in JAVA to resolve CWE ID 73(External Control of File Name or Path) using ESAPI?

I am facing this security flaw in my project at multiple places. I don't have any white-list to do a check at every occurrence of this flaw. I want to use ESAPI call to perform a basic blacklist check on the file name. I have read that we can use SafeFile object of ESAPI but cannot figure out how and where.
Below are a few options I came up with, Please let me know which one will work out?
ESAPI.validator().getValidInput() or ESAPI.validator().getValidFileName()
Blacklists are a no-win scenario. This can only protect you against known threats. Any code scanning tool you use here will continue to report the vulnerability... because a blacklist is a vulnerability. See this note from OWASP:
This strategy, also known as "negative" or "blacklist" validation is a
weak alternative to positive validation. Essentially, if you don't
expect to see characters such as %3f or JavaScript or similar, reject
strings containing them. This is a dangerous strategy, because the set
of possible bad data is potentially infinite. Adopting this strategy
means that you will have to maintain the list of "known bad"
characters and patterns forever, and you will by definition have
incomplete protection.
Also, character encoding and OS makes this a problem too. Let's say we accept an upload of a *.docx file. Here's the different corner-cases to consider, and this would be for every application in your portfolio.
Is the accepting application running on a linux platform or an NT platform? (File separators are \ in Windows and / in linux.)
a. spaces are also treated differently in file/directory paths across systems.
Does the application already account for URL-encoding?
Is the file being sent stored in a database or on the system itself?
Is the file you're receiving executable or not? For example, if I rename netcat.exe to foo.docx does your application actually check to see if the file being uploaded contains the magic numbers for an exe file?
I can go on. But I won't. I could write an encyclopedia.
If this is across multiple applications against your company's portfolio it is your ethical duty to state this clearly, and then your company needs to come up with an app/by/app whitelist.
As far as ESAPI is concerned, you would use Validator.getValidInput() with a regex that was an OR of all the files you wanted to reject, ie. in validation.properties you'd do something like: Validator.blackListsAreABadIdea=regex1|regex2|regex3|regex4
Note that the parsing penalty for blacklists is higher too... every input string will have to be run against EVERY regex in your blacklist, which as OWASP points out, can be infinite.
So again, the correct solution is to have every application team in your portfolio construct a whitelist for their application. If this is really impossible (and I doubt that) then you need to make sure that you've stated the risks cited here clearly to management and you refuse to proceed with the blacklist approach until you have written documentation that the company chooses to accept the risk. This will protect you from legal liability when the blacklist fails and you're taken to court.
[EDIT]
The method you're looking for was called HTTPUtilites.safeFileUpload() listed here as acceptance criteria but this was most likely never implemented due to the difficulties I posted above. Blacklists are extremely custom to the application. The best you'll get is a method HTTPUtilities.getFileUploads() which uses a list defined in ESAPI.properties under the key HttpUtilities.ApprovedUploadExtensions
However, the default version needs to be customized as I doubt you want your users uploading .class files and dll to your system.
Also note: This solution is a whitelist and NOT a blacklist.
The following code snippet works to get past the issue CWE ID 73, if the directory path is static and just the filename is externally controlled :
//'DIRECTORY_PATH' is the directory of the file
//'filename' variable holds the name of the file
//'myFile' variable holds reference to the file object
File dir = new File(DIRECTORY_PATH);
FileFilter fileFilter = new WildcardFileFilter(filename);
File[] files = dir.listFiles(fileFilter);
File myFile = null ;
if(files.length == 1 )
myFile = files[0];

How to use ExpectJ in synchronized way (waiting for answer with unknown content ) ?

My Java application has to work like this:
User select bash commands in GUI and press "send."
Application return distinct and independent answers for each command
(e.g. we could store them in different files).
Commands each run interactively, not in a batch (it can't be
something like "ls\n pwd \n" etc)
After each command, the application will wait and check if the
results are ok. If so, it will send the next command.
We need to execute su on the remote host.
I've used ExpectJ (with a little hack of output stream). It has resolved points 1,3,4,5.
But there is a problem with point 2. In my app I need to get separated answer. But we will not know their length. Command prompts can be different. Anyone knows how to "hack" ExpectJ so it will be some how more synchronized? I am looking for acting like this : send , wait for full answer, send, wait... I've tried some basic synchronization tricks but this end in timeouts and connection lost usually.
This question is related to my older one :
Java library to run multiple unrelated commands on a remote server via ssh
the problem basically is that expectj sends and listens at the same time, buffering inputs and outputs in separate threads, so you have to know when the response has ended so you can delimit each request/response block. If you don't care about expect "interact" mode, you can try to hack expect4J, expect-for-java (https://github.com/ronniedong/Expect-for-Java) or even apache mina sshd.
I am facing exactly the same problem right now, and since I need interact(), I don't have any other option right now. So, this solution below is not elegant, but may do the job. Too bad we don't have a decent expect java implementation. I hope we will in java 8, when (I hope) we'll have closure.
ExpectJ ex = new ExpectJ(50);
Spawn spawn = ex.spawn(new SshSpawn("192.168.56.101", 22, "alice", "password"));
String command = "hostname -s;expr 123456788 + 1";
spawn.send(command+"\n");
spawn.expect("123456789");
String lsResults = spawn.getCurrentStandardOutContents().split("123456788 \\+ 1\r\n")[2].split("123456789")[0];
String[] lsRows = lsResults.split("\r\n");
for(int i=0;i<lsRows.length;i++){
System.out.println(i+":"+lsRows[i]);
}

How to Clear Console in Java?

I have been pulling my hair for this since quite long time. I have researched for an hour on how to clear a console in Java.
All I found was dirty hacking either by printing a bunch of lines or executing this
Runtime.getruntime.exec("cls/clear");
However, nothing seems to be working for me. Isn't there really any a way of clearing the console in Java like in C (clrscr();). Isn't there any external library by which this can be achieved.
Please let me know if anyone has ever done this before using a proper function, library etc. instead of dirty hacking.
If your terminal supports ANSI escape codes, this clears the screen and moves the cursor to the first row, first column:
System.out.print("\033[H\033[2J");
System.out.flush();
This works on almost all UNIX terminals and terminal emulators. The Windows cmd.exe does not interprete ANSI escape codes.
Try this code
import java.io.IOException;
public class CLS {
public static void main(String... arg) throws IOException, InterruptedException {
new ProcessBuilder("cmd", "/c", "cls").inheritIO().start().waitFor();
}
}
Now when the Java process is connected to a console, it will clear the console.
Runtime.getRuntime().exec("PlatformDepedentCode");
You need to replace "PlatformDependentCode" with your platform's clear console command.
The exec() method executes the command you entered as the argument, just as if it is entered in the console.
In Windows you would write it as Runtime.getRuntime().exec("cls");.
Use the following code:
System.out.println("\f");
'\f' is an escape sequence which represents FormFeed. This is what I have used in my projects to clear the console. This is simpler than the other codes, I guess.
You need to instruct the console to clear.
For serial terminals this was typically done through so called "escape sequences", where notably the vt100 set has become very commonly supported (and its close ANSI-cousin).
Windows has traditionally not supported such sequences "out-of-the-box" but relied on API-calls to do these things. For DOS-based versions of Windows, however, the ANSI.SYS driver could be installed to provide such support.
So if you are under Windows, you need to interact with the appropriate Windows API. I do not believe the standard Java runtime library contains code to do so.
You can easily implement clrscr() using simple for loop printing "\b".
If you are using windows and are interested in clearing the screen before running the program, you can compile the file call it from a .bat file.
for example:
cls
java "what ever the name of the compiles class is"
Save as "etc".bat and then running by calling it in the command prompt or double clicking the file

Java exec on Unix

I have the Java code below running on Unix (both AIX and Linux), but it doesn't work. If I run this code the file q1.01 is not compressed, and I don't get any exceptions thrown (The file q1.01 exists, and I expect to find the file q1.01.Z after the command runs.) At the command prompt if I type "which compress" it reports back with "/usr/bin/compress". If I type the command "/usr/bin/compress q1.01" at the Unix prompt it works fine. Any ideas on what might be wrong?
String cmd = "/usr/bin/compress q1.01";
Runtime.getRuntime().exec(cmd);
[Later edit: the problem was in the initial description; the OP was passing a wildcard and not q.01. So my answer below is wrong, except for the part in bold. I'm leaving it so the comments after it will make sense.]
It's trying to run /usr/bin/compress as the program name without arguments.
There are many forms of the Runtime.exec() method. You're using the .exec(String) version, which just takes the executable. Instead, you need to use the .exec(String[]) array version, which takes the executable in String[0] and the parameters in String[1..].
.exec() wants a String array for passing arguments.
Try
String[] cmd = new String[] { "/usr/bin/compress", "q1.01" };
Runtime.getRuntime().exec(cmd);
Note that .exec does not call the local command shell. That means we have to do, among other things, wildcard expansion and even some argument parsing before calling .exec(). This is why you can't just pass it your full command line.
There were a couple of problems. One was that I had tried using wildcards, and since the shell isn't invoked they weren't being expanded. The other problem was that I had created very small test files like this: "echo 'abc' >q1.01". This file was so small that compress couldn't compress it any further and so left it alone. (Stupidly, I think when I typed in the command at the shell I used a different filename, which did compress.)
Thanks everyone for the answers. It did help!
You probably need to use an absolute path to the file. Capture the output though, to see what the problem is - see this page for info on how to do that.
This site may be able to provide some clues.
If the process input stream is null, I suspect that Java wasn't even able to spawn the subprocess. What does Process#exitValue() return?
I'd recommend using strace to see what actually happens on the system-call level. The actual exec() arguments and return code would be especially interesting to see.

Categories

Resources