How to disable Java security manager? - java

Is there any way to completely disable Java security manager?
I'm experimenting with source code of db4o. It uses reflection to persist objects and it seems that security manager doesn't allow reflection to read and write private or protected fields.
My code:
public static void main(String[] args) throws IOException {
System.out.println("start");
new File( DB_FILE_NAME ).delete();
ObjectContainer container = Db4o.openFile( DB_FILE_NAME );
String ob = new String( "test" );
container.store( ob );
ObjectSet result = container.queryByExample( String.class );
System.out.println( "retrieved (" + result.size() + "):" );
while( result.hasNext() ) {
System.out.println( result.next() );
}
container.close();
System.out.println("finish");
}
Output:
start
[db4o 7.4.68.12069 2009-04-18 00:21:30]
AccessibleObject#setAccessible() is not available. Private fields can not be stored.
retrieved (0):
finish
This thread suggests modifying java.policy file to allow reflection but it doesn't seem to work for me.
I'm starting JVM with arguments
-Djava.security.manager -Djava.security.policy==/home/pablo/.java.policy
so specified policy file will be the only policy file used
The file looks like this:
grant {
permission java.security.AllPermission;
permission java.lang.reflect.ReflectPermission "suppressAccessChecks";
};
I spent last 3 hrs on this and don't have any ideas how to make this work.
Any help appreciated.

You could try adding this to the main() of your program:
System.setSecurityManager(null);
Worked for me for a "trusted" WebStart application when I was having security manager issues. Not sure if it will work for your db4o case, but it might be worth a try.
EDIT: I'm not suggesting that this is a general solution to security manager problems. I was just proposing it as a way to help debug the original poster's problem. Clearly, if you want to benefit from a security manager then you should not disable it.

Do you really have two '=' signs in your java.security.policy command line option? That won't work. Make sure you are setting the property as
-Djava.security.policy=/home/pablo/.java.policy
To actually disable the SecurityManager, simply leaving off the java.security.manager system property altogether should be enough.
Update: As I was reading the documentation for policy files to learn more about the "==" syntax, I noticed that unless the policy file is in the current working directory, it needs to be specified as a URL (including scheme). Have you tried prefixing the policy path with the "file:" scheme?
I was also puzzled because (assuming you are running as user "pablo"), it looks like that policy should be loaded by default from your home directory, so you shouldn't need to specify it at all. On the other hand, if you are not running as the user "pablo", maybe the file is not readable.

I found this example of how to make private fields and methods accessible to your code. Basically, it distills down to the use of Field.setAccessible(true) and Method.setAccessible(true)
Field example:
Field privateStringField = PrivateObject.class.
getDeclaredField("privateString");
privateStringField.setAccessible(true);
Method example:
Method privateStringMethod = PrivateObject.class.
getDeclaredMethod("getPrivateString", null);
privateStringMethod.setAccessible(true);
You could also look at using Groovy with your Java code as it (currently) circumvents much of the access level restrictions of Java code. Although, this message board posting seems to suggest this 'feature' may change in future versions of Groovy.

Related

File.exists() returns false for file (directory) that actually exists

TLDR: File.exists() is buggy and i would like to understand why!
I am facing a weird issue (as so often happens) in my Android App. I will try to be as brief as i can.
First, i will show you the code and then provide some additional info. This is not the full code. Just the core of the issue.
Example code:
String myPath = "/storage/emulated/0/Documents";
File directory= new File(myPath);
if (!directory.exists() && !directory.mkdirs()) {
throw new IllegalArgumentException("Could not create the specified directory: " + directory.getAbsolutePath() + ".");
}
Most of the time this works fine. A few times however the exception is thrown which means that the directory did not exist and could not be created. Out of every 100 runs, it works fine on 95-96 times and fails 4-5 times.
I have declared the permissions for storage/read external storage/write external storage in my manifest and asked for the permissions on runtime. The problem does not lie there. (If anything i have too many permissions at this point :D ). After all, if it was a permission issue it would fail every time but in my case it fails at a rate of 4% or 5%.
With the above code i am attempting to create a file that points to the 'Documents' folder. In my app i am actually using String myPath = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS).getPath();
In the specific device where the error occurs this path happens to be "/storage/emulated/0/Documents" and this is why i hardcoded it in the example code i gave you.
If i use a file explorer app on the device (i.e. 'Astro file manager' i can see that the folder does exist and has some contents and also confirm that the path really is "/storage/emulated/0/Documents".
This has never happened to me locally. Only the users of the app experience the issue and i know the issue exists thanks to Firebase/Crashlytics. The users have the exact same tablet as the one i am using for development, namely a Lenovo TB-8504X. (I work for a company and we provide both the software and the hardware).
So, do you have any thoughts on why this issue occurs?
Has anyone ever experienced something similar?
Could the path to the 'Documents' folder sometimes be "/storage/emulated/0/Documents" and sometimes become something else on the same physical device?
I am an experienced Android developer but i am quite novice in Android architecture and the Android filesystem. Could it be that on start-up (when device is powered on or after a reboot) the filesystem has not yet 'mounted' the 'disk' at the point when my code checks if the directory exists? Here i am using the terms 'mount' and 'disk' as loosely as possible. Also my app is actually a launcher/parental control app so it is the first thing that gets fired when device starts. I am almost conviced that this does not make sense at all but at this point i am trying to see the greater picture and explore solutions that transcend typical Android development.
I would really appreciate your help as this issue is starting to get on my nerves.
Looking forward to any helpful responses.
Thanks in advance.
EDIT (27/08/2019) :
I came across this Java Bug Report although it is pretty outdated. According to this, when operating on NFS-mounted volumes, java.io.File.exists ends up performing a stat(2). If the stat fails (which it may do for several reasons), then File.exists (mistakenly) assumes that the file being stat'ed does not exist. Could this be the source of my troubles?
EDIT (28/08/2019) :
Today i am able to add a bounty to this question in an attempt to draw some more attention. I would encourage you to read the question carefully, look through the comments disregarding the one that claims that this has to do with costumer support from Realm. Realm code is indeed the one using the unreliable method but what i want to know is why the method is unreliable. Whether or not Realm can work around this and use some other code instead, is beyond the scope of the question. I simply want to know if one can safely use File.exists() and if not, why?
Once again, thank you all in advance. It would be really important to me to get an answer even if it is overly technical and involves a deeper understanding of NFS file systems, Java, Android, Linux, or whatever!
EDIT (30/08/2019) :
Because some users suggest replacing File.exists() with some other method, i'd like to state that what i am interested in at this point is understating why the method fails and not what one could use instead as a workaround.
Even if i wanted to replace File.exists() with something else, i am not able to do that because this piece of code resides in RealmConfiguration.java file (Read-only) which is part of the Realm Library that i use in my app.
To make things even more clear i will provide two pieces of code. The code i use in my activity and the method that get's called in RealmConfiguration.java as a consequence:
Code i use in my activity :
File myfile = new File("/storage/emulated/0/Documents");
if(myFile.exists()){ //<---- Notice that myFile exists at this point.
Realm.init(this);
config = new RealmConfiguration.Builder()
.name(".TheDatabaseName")
.directory(myFile) //<---- Notice this line of code.
.schemaVersion(7)
.migration(new MyMigration())
.build();
Realm.setDefaultConfiguration(config);
realm = Realm.getDefaultInstance();
}
At this point myFile exists and the code that resides in RealmConfiguration.java get's called.
The RealmConfiguration.java method that crashes :
/**
* Specifies the directory where the Realm file will be saved. The default value is {#code context.getFilesDir()}.
* If the directory does not exist, it will be created.
*
* #param directory the directory to save the Realm file in. Directory must be writable.
* #throws IllegalArgumentException if {#code directory} is null, not writable or a file.
*/
public Builder directory(File directory) {
//noinspection ConstantConditions
if (directory == null) {
throw new IllegalArgumentException("Non-null 'dir' required.");
}
if (directory.isFile()) {
throw new IllegalArgumentException("'dir' is a file, not a directory: " + directory.getAbsolutePath() + ".");
}
------> if (!directory.exists() && !directory.mkdirs()) { //<---- Here is the problem
throw new IllegalArgumentException("Could not create the specified directory: " + directory.getAbsolutePath() + ".");
}
if (!directory.canWrite()) {
throw new IllegalArgumentException("Realm directory is not writable: " + directory.getAbsolutePath() + ".");
}
this.directory = directory;
return this;
}
So, myFile exists in my activity, the Realm code get's called and suddenly myFile no longer exists.. Again i wish to point out that this is not consistent. I am noticing crashes at a rate of 4-5% meaning that most of the time myFile exists both in the activity and when the realm code makes it's check.
I hope this will be helpful.
Again thanks in advance!
First of all, if you are using Android, bug reports in the Java Bugs database are not relevant. Android does not use the Sun / Oracle codebase. Android started out as a clean-room re-implementation of the Java class libraries.
So if there are bugs in File.exists() on Android the bugs would be in the Android codebase, and any reports would be in the Android issue tracker.
But when you say this:
According to this, when operating on NFS-mounted volumes, java.io.File.exists ends up performing a stat(2). If the stat fails (which it may do for several reasons), then File.exists (mistakenly) assumes that the file being stat'ed does not exist.
Unless you are using NFS, that bug report is not directly relevant.
It is not a mistake / bug. It is a limitation.
At the file system level, it is a fact of life that Linux supports many different kinds of file system, and that many of them behave in unexpected ways ... compared to an "ordinary" file system. It is not possible for the JVM to hide all of the weird filesystem-specific edge cases at the Java API level.
On the API level, File.exists cannot report any errors. The signature doesn't allow it to throw an IOException, and throwing an unchecked exception would be a breaking change. All it can say is true or false.
If you want to distinguish the various reasons for a false, you should use the newer Files.exists(Path, LinkOptions...) method instead.
Could this be the source of my troubles?
Yes it could, and not just in the NFS case! See below. (With Files.exist, an NFS stat failure would most likely be an EIO, and that would raise an IOException rather than returning false.)
The File.java code in the Android codebase (version android-4.2.2_r1) is:
public boolean exists() {
return doAccess(F_OK);
}
private boolean doAccess(int mode) {
try {
return Libcore.os.access(path, mode);
} catch (ErrnoException errnoException) {
return false;
}
}
Note how it turns any ErrnoException into a false.
A bit more digging reveals that the os.access call is performing a native call which makes an access syscall, and throws ErrnoException if the syscall fails.
So now we need look at the documented behavior of the access syscall. Here's what man 2 access says:
F_OK tests for the existence of the
file.
On error (at least one bit in mode
asked for a permission that is denied, or mode is F_OK and the file
does not exist, or some other error occurred), -1 is returned, and
errno is set appropriately.
access() shall fail if:
EACCES The requested access would be denied to the file, or search per‐
mission is denied for one of the directories in the path prefix
of pathname. (See also path_resolution(7).)
ELOOP Too many symbolic links were encountered in resolving pathname.
ENAMETOOLONG
pathname is too long.
ENOENT A component of pathname does not exist or is a dangling symbolic
link.
ENOTDIR
A component used as a directory in pathname is not, in fact, a
directory.
EROFS Write permission was requested for a file on a read-only
filesystem.
access() may fail if:
EFAULT pathname points outside your accessible address space.
EINVAL mode was incorrectly specified.
EIO An I/O error occurred.
ENOMEM Insufficient kernel memory was available.
ETXTBSY
Write access was requested to an executable which is being executed.
I have struck out the errors that I think are technically impossible or implausible, but the still leaves quite few to consider.
Another possibility is something (e.g. some other part of your application) is deleting or renaming the file or a (hypothetical) symlink, or changing file permissions ... behind your back.
But I don't think that File.exist() is broken1, or that the host OS is broken. It is theoretically possible, but you would need some clear evidence to support the theory.
1 - It is not broken in the sense that it is not behaving differently to the known behavior of the method. You could argue until the cows come home about whether the behavior is "correct", but it has been like that since Java 1.0 and it can't be changed in OpenJDK or in Android without breaking thousands of existing applications written over the last 20+ years. It won't happen.
What to do next?
Well my recommendation would be to use strace to track the syscalls that your app is making and see if you can get some clues as to why some access syscalls are giving you unexpected results; e.g. what the paths are and what the errno is. See https://source.android.com/devices/tech/debug/strace .
I have had a similar issue, but with a higher trouble rate, where the Anti Virus was locking FileSystem, and thus failing any requests (almost instantly)
the workaround was using java.nio.Files.exists() instead.

How to resolve External Control of File Name or Path (CWE ID 73)

I am working on fixing Veracode issues in my application. Veracode has highlighted the flaw "External Control of File Name or Path (CWE ID 73) " in below code.
Thread.currentThread().getContextClassLoader().getResourceAsStream(lookupName)
How do I validate the parameter? If I need to use below ESAPI validation, then what is the exact parameter I should be passing in getValidFileName() method. Currently I am passing the parameters as below.
ESAPI.validator().getValidFileName(lookupName, lookupName,
ESAPI.securityConfiguration().getAllowedFileExtensions(), false);
Correct me whether I am following the right approach for fixing this issue.
There are several suggestions at: https://community.veracode.com/s/article/how-do-i-fix-cwe-73-external-control-of-file-name-or-path-in-java
You can use hardcoded values, if these files are stored in the server side.
(i.e.: in a HashMap).
Another solution is to use a custom validator (from veracode page) :
// GOOD Code
String extension = request.getParameter("extension");
File f = new File(buildValidAvatarPath(extension))
#FilePathCleanser
public String buildValidAvatarPath(extension) {
String[] allowedExtensions = new String[]{"jpg","gif","png"};
String extension = "png"; // Default extension
for (String allowedExtension: allowedExtensions) {
if (allowedExtension.equals(request.getParameter("extension"))) {
extension = request.getParameter("extension");
}
}
// See "Note on authorization"
User user = getCurrentUser();
if (!userMayAccessFile(user, path)) {
throw new AuthorizationException("User may not access this file", user);
}
File(configPath + "avatar." + extension)
return path;
}
Okay, so the problem is that you are allowing user-control of that file path. Imagine its on a UNIX box and they enter:
../../../../../../../etc/shadow
Whatever user privileges are granted to the user running that java Thread is possible to expose to the user in question. I don't know what processing is going on in your application, but the danger is that you need to prevent user control of that lookup variable.
The call you're making is consistent with the single test in ValidatorTest.java, which is definitely a deficiency in code coverage on our behalf.
Now, there's an excellent chance that even if you use this call that Veracode might still flag it: the default file list in ESAPI.properties will need to be either truncated for your use case, or you'll have to create your own Validator rule for legal file extensions for your specific use case.
Which brings up the next bit: There's a lot of mischief that can happen in regards to file uploads.
In short, to be actually secure about file uploads will require more than what ESAPI currently offers, which is unfortunately, only an extension check. In your particular case, make sure you try some directory traversal attacks. And use that OWASP link to help analyze your application.
Given that the OP wants to clear the issue in Veracode, you would want to chain a couple calls:
ESAPI.validator().getValidDirectoryPath() and ESAPI.Validator.getValidFileName()
But be sure you've properly truncated the extension list in HttpUtilities.ApprovedUploadExtensions in validator.properties as the default list is too permissive, at least until we release 2.1.0.2.
I have to stress however that even with this particular combination there is absolutely nothing ESAPI does to prevent a user from renaming "netcat.exe" to "puppies.xlsx" and bypassing your validation check, that's why the rant on the first part of this answer.
ESAPI's file validation is NOT secure, it's quite simply better than nothing at all.
Doing this correctly requires more work than just using 1-2 calls to ESAPI.
DISCLAIMER: as of this writing I am the project co-lead for ESAPI.
You can change file name by sanitizing it as below code snippet:
private static String sanitizeFileName(String name) {
return name
.chars()
.mapToObj(i -> (char) i)
.map(c -> Character.isWhitespace(c) ? '_' : c)
.filter(c -> Character.isLetterOrDigit(c) || c == '-' || c == '_' || c == ':')
.map(String::valueOf)
.collect(Collectors.joining());
}

Java Create Undeletable File

Is there any method to create a file in java that cannot be deleted.
I have googled it and found processes involving the cmd.
However, I require a pure "java" way that can be done on any platform.
Thanks in advance.
Thank you for your help.
I finally got it right.
I used the following code to deny access to user
public static void main() throws IOException
{
Path file = Paths.get("c:/b.txt");
AclFileAttributeView aclAttr = Files.getFileAttributeView(file, AclFileAttributeView.class);
//System.out.println();
UserPrincipalLookupService upls = file.getFileSystem().getUserPrincipalLookupService();
UserPrincipal user = upls.lookupPrincipalByName(System.getProperty("user.name"));
AclEntry.Builder builder = AclEntry.newBuilder();
builder.setPermissions(EnumSet.of(AclEntryPermission.APPEND_DATA, AclEntryPermission.DELETE, AclEntryPermission.DELETE_CHILD, AclEntryPermission.EXECUTE, AclEntryPermission.READ_ACL, AclEntryPermission.READ_ATTRIBUTES, AclEntryPermission.READ_DATA, AclEntryPermission.READ_NAMED_ATTRS, AclEntryPermission.SYNCHRONIZE, AclEntryPermission.WRITE_ACL, AclEntryPermission.WRITE_ATTRIBUTES, AclEntryPermission.WRITE_DATA, AclEntryPermission.WRITE_NAMED_ATTRS, AclEntryPermission.WRITE_OWNER));
builder.setPrincipal(user);
builder.setType(AclEntryType.DENY);
aclAttr.setAcl(Collections.singletonList(builder.build()));
}
Try the method setPosixFilePermissions() and set the permissions to read only for all the classes of users. Refer this - http://docs.oracle.com/javase/7/docs/api/java/nio/file/Files.html#setPosixFilePermissions%28java.nio.file.Path,%20java.util.Set%29
If you want to create a file that can't be accidentally overwritten, then look at the various answers to this: How do i programmatically change file permissions?
If you want to create a file that the current program cannot delete at all (but a privileged one could), it might be possible by setting permissions appropriately on the parent directory, or possibly using SELinux Mandatory Access Control cleverness.
If you want to create a truly undeleteable file, then you are out of luck. I am not aware of any operating system that supports creation of files that can never be deleted. It would be an "anti-feature".
I would also agree with #Teifi's comment. Create a file that cannot ever be deleted on the user's machine is not acceptable ... unless done by, or with the authorization of the system's administrators. I would call any software that did that "malicious" too.

How can I control the usage of a custom jar library?

I need a way to essentially secure my jar library to allow registered apps to use it in their projects and deny usage to apps that weren't approved by me.
It is fine if I hard code things in the lib for each distribution. I currently have this jar obfuscated.
What are good approaches to restrict the usage of a jar?
One idea was to lock the lib to a specific package so if the developer tries to use it in another project they can't. But I'm not sure if they can easily provide a custom fake Context to make it work...
To me the best approach if you would like your library to stay standalone (without involving the network for checking or downloading pieces of the library, I mean) would be to make mandatory the use of an initializer class that would receive a token from the client application.
This would be crackable as the token validity test would be performed by your lib: one may modify the lib in a way is would just skip that test, but this would be made harder by the obfuscation. But this is probably sufficient, unless using your lib without having registered it is a really critical issue.
So you would have something like:
boolean Initializer.initLib(String passcode)
That would prevent the lib to work unless passcode is correct.
You can make the obfuscation more efficient by avoiding checking that way:
public void initLib(String passcode) {
if (passcode == A_GIVEN_PUBLIC_STATIC_THAT_STORESTHE_CODE) {
// do the proper initializations
}
else {
throw new RuntimeException("Bad passcode, sorry!");
}
}
But doing that way instead:
public void initLib(String passcode) {
final char[] PASS_ENCRYPTED = "f5uhjgf56ik8kv214d5".toCharArray();
final char[] PASS_MINUSMASK = "bc".toCharArray();
final int PASS_SHIFT = 11;
final int PASS_MASK_MINUS = 2;
for (int ctr = 0; ctr < PASS_MINUSMASK.length; ++ctr) {
final char next = PASS_ENCRYPTED[PASS_SHIFT + ctr - PASS_MASK_MINUS];
if (passcode.charAt(ctr) != next - (PASS_MINUSMASK[ctr] - 'a')) {
// make the lib unusable by some inits. But it should look as a proper initialization
return;
}
}
// make the lib usable by some inits.
}
This looks stupid, but if you have a look at the obfuscated code, you will see a big difference. This code is just an example (it accepts "hi" as a valid passcode), any algorithm would be fine as long as its obfuscated version is not too straightforward to reverse.
Now the question is: what passcode?
As the library's protection concerns the developpers of the client apps that will use it, and not the final users of these apps, you cannot rely on any piece of data specific to the devices on which the applications will run. So no IMEI or anything like that.
If these developpers are trustworthy that's fine. A fixed passcode is sufficient.
But if they are subject to give this passcode to other people to allow them using your library, this is more difficult. In this case I don't think you can solve it without a real "industrial" process such as registering the client apps and their code checksums, for example. Such a process needs a specific design and cannot be solved "just by the code", but as it also has a cost (time, resources, involvment of the client...) you can only consider this if the use of library is very critical.
Can't you make your jar call your server with a specific code and the application name, to check if they are registered ?
When you build an Android app with a jar, that jar is compiled into the app and becomes a part of it. You can't just copy the jar out of the package and use it elsewhere. Unless I'm not understanding the question, this shouldn't be an issue you need to worry about.

Accessing Windows Registry [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
read/write to Windows Registry using Java
I need to access Windows registry from Java.. Also I need to copy some registry entries and may have to enter new registry variables using Java..
some one help me please...
I'd recommend the Java Native Access (JNA) library. It's a pretty nice wrapper around JNI. According to this mailing list post, they've already got a contributed wrapper around the native Windows registry function calls.
If you add the JNA libraries to your project, the relevant source you'll want is the Registry.java class. From there, just call methods on that class to investigate the Windows registry.
As a side note, make sure when you use JNA that you use Platform.isXxx() to make sure your code can actually query the registry on the particular platform.
An example will be like this:
import com.ice.jni.registry.*;
public class DeleteEnvironmentVar{
public DeleteEnvironmentVar(String variable, String value) throws Exception {
RegistryKey machine = Registry.getTopLevelKey("HKEY_LOCAL_MACHINE");
RegistryKey environment = machine.openSubKey("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment", RegistryKey.ACCESS_WRITE);
try {
if ( value == null ) { //Delete the variable in case value is empty
environment.deleteValue(variable);
}
}
catch( NoSuchValueException nsve ) {}
catch( NoSuchKeyException nske ) {}
}
}
The Preferences class is the Java preferred way of writing to the registry. However, I haven't actually used it, so I don't know if it allows access to the entire registry or just a section specific to the JVM or your application. If it doesn't, then it sounds like for your purpose you'll be needing to look at the JNI solutions posited by others here. If it does work, then you have a platform-independent method of storing off your settings if you ever port it.

Categories

Resources