Java Security: JEP: 411: Deprecate the Security Manager for Removal - What about Serialization?

Peter Firmstone peter.firmstone at zeus.net.au
Mon May 3 22:42:59 UTC 2021


Clarification inline below

On 4/05/2021 8:35 am, Peter Firmstone wrote:
> On 4/05/2021 5:12 am, Sean Mullan wrote:
>> -bcc jdk-dev
>> -cc security-dev
>>
>> On 4/30/21 10:04 PM, Peter Firmstone wrote:
>>> <SNIP>
>>>
>>> In our software we use a ProtectionDomain to represent a remote 
>>> server, because a thread only runs with the user's Subject (and that 
>>> Subject must be carefully preserved for other threads), there is no 
>>> way to represent the remote Server's Subject in a local domain , 
>>> other than with a ProtectionDomain.   Our software is peer to peer, 
>>> clients can be servers and servers can also be clients.  Code to 
>>> interact with the server is downloaded via Maven and loaded.  Any 
>>> permission's granted to a user, are injected into the stack when run 
>>> as the client Subject, to authenticate the user for the server and 
>>> establish a secure connection, calls made by the client are run with 
>>> the user's Subject on the server, again for access control 
>>> purposes.  This functionality is beyond the capability of Java RMI, 
>>> we aren't using Java RMI to do this.  This is very important to 
>>> allow us to make fine grained access control decisions, or perform 
>>> event notification callbacks over secure connections, without this 
>>> feature, we can't make a secure connection with a callback, and you 
>>> know what happens when you have to do something, but cannot do it 
>>> securely?   We only grant network access directly back to the 
>>> server, downloaded code has been verified and is not expected to 
>>> cause denial of service, by consuming resources etc, but we don't 
>>> want to grant third party access to files, or random network 
>>> connections, we still have privacy obligations for third party 
>>> information.
>>>
>>> We can allow a third party to use unsigned certificates to sign 
>>> their jar files or use a checksum and we verify them using a secure 
>>> connection to the server, prior to loading. We then dynamically 
>>> grant permissions to the server's self signed Certificate (used to 
>>> sign the jar file), or a ProtectionDomain, after authenticating the 
>>> server and receiving a check sum or certificate from it.  So the 
>>> client authenticates the server using signed TLS certificates (EG by 
>>> letsencrypt.org or a trusted CA). We use self signed certificates on 
>>> Jar files if we sign them, we are actually trusting the server 
>>> entity in this case, eg a trusted company, but also placing 
>>> restrictions on them.
>>
>> I am probably missing something, but I don't understand how this is 
>> secure if you are using TLS server certificates as the basis for 
>> authenticating signed code. These are two very different use cases.
>
>
> Clarifying the level of trust:
>
>  1. You have a trusted party, whom you trust to write their own code.
>  2. You run that code on your systems dynamically.
>  3. You trust the other party, but you either haven't or it's not
>     practical to audit their code.
>  4. Using the principle of least privilege, you limit the ability of
>     the other party's code to ensure they are unable observe data they
>     shouldn't, eg a third party with whom you also do business.
>  5. While a trusted party (eg a supplier) could write code that caused
>     denial of service, eg using up all available memory, there is no
>     motivation for them to do so.  However there may be motivation for
>     them to see quotes on your system from another supplier if they
>     have access to it.
>
> The code is loaded dynamically, but before the jvm loads it, we 
> authenticate the party that is asking us to load their code, after 
> which we are basically asking them the question, is this the code you 
> want us to load?  Please check that it hasn't been tampered with.   
> The trusted party gives us a checksum, or a self signed certificate 
> they used to sign the jar, we are then satisfied that we have received 
> the software unaltered from the trusted party and not a MITM attack, 
> so we load it.   However we limit the permission of this software 
> using the principle of least privilege.   They don't get file 
> permissions, they are only allowed to connect to the server they used 
> to authenticate with.  If a third party uses the same jar file, they 
> don't gain the permissions granted to other parties, as it will be 
> loaded into a separate ClassLoader with the permissions granted to 
> that party only.
>
Just to clarify, these are software logic interactions.

>
>>
>>> If we remove access control, third parties will be able to open 
>>> local network connections and freely and use Java Serialization over 
>>> unsecured connections, exposing us to an attacker who can use a 
>>> gadget attack. Presently they cannot open a network connection, 
>>> access files or do much of anything without Permission.  All those 
>>> protections will be removed with this JEP.
>>>
>>> from 
>>> https://community.letsencrypt.org/t/do-you-support-code-signing/370
>>>
>>>> Code-signing certificates as they’re used today are part of systems 
>>>> that try to decide whether a software source is malicious or 
>>>> legitimate. I don’t think Let’s Encrypt could easily play that kind 
>>>> of role when issuing certificates free of charge with an automated 
>>>> process without checking the real-world identity of the applicant. 
>>>> We could confirm that a code signing certificate applicant controls 
>>>> a domain name like iurewnrjewknkjqoiw.biz 408 
>>>> <http://iurewnrjewknkjqoiw.biz>, but that doesn’t give users or 
>>>> operating system developers much ability to know whether software 
>>>> that that applicant publishes is trustworthy or malicious.
>>>
>>> The JVM is one of very few platforms that has sufficient capability 
>>> to allow us to do this.
>>>
>>> If I could chose my pain, I would chose to remove Java Serialization 
>>> first, before SecurityManager because while I understand the 
>>> maintenance burden needs to be reduced for the ongoing viability of 
>>> the Java platform, security is still of utmost importance, as the 
>>> vulnerabilities of Java Serialization killed of client development.
>>
>> I don't think it is appropriate to block deprecation of the Security 
>> Manager until serialization is removed. Note that we have added 
>> mechanisms such as Serialization Filters [1] to help applications 
>> secure their serialization dependencies and that do not require a 
>> Security Manager to be enabled. We also are continuing to look at 
>> other improvements in this area, as well as introducing new features 
>> such as Records that can be serialized more securely [2].
>
> I'm not suggesting blocking deprecation of SecurityManager, I'm 
> requesting blocking removal of SecurityManager until after 
> Serialization has been removed.   So deprecate SecurityManager, just 
> don't mark it for removal yet.  Please mark SecurityManager for 
> removal after Serialization has been removed.   What follows is the 
> reasoning for my request.
>
> We currently use SecurityManager and policy to prevent un-trusted 
> connections which could otherwise use serialization or access 
> sensitive data.    We only allow a limited subset re-implementation of 
> serialization over trusted connections and permission must be granted 
> before it can be used.  No trust established (TLS), then no 
> Serialization.  Because we load code dynamically, we will not be able 
> to profile it in advance, so we cannot create serialization whitelists 
> because we have no way of knowing class names in advance, our only 
> choice will be to disable Serialization entirely.   At least with 
> security policy, we can establish the permissions in advance.
>
> Presently the dynamically loaded code, contains a list of requested 
> Permissions in META-INF, however they may not be granted, the security 
> policy has a list of Permission's that are allowed to be granted based 
> on the remote principal, the permissions granted will be the 
> intersection of these two lists, requested and allowed permissions.  
> We can log permissions that are not granted.  This occurs dynamically 
> at runtime.  A Permission requested may also be a subset of the 
> Permissions allowed, because of implies checks.  So dynamically loaded 
> code really does operate under least privilege principles.  You can't 
> do that with Serialization filtering.
>
> Prior to the introduction of the Serialization's filtering mechanism, 
> I re-implemented a subset of Java Serialization, focused on addressing 
> vulnerabilities caused by gadget attacks.
>
> We did this when other companies solutions to addressing Java 
> vulnerabilities was to remove Java altogether, which is why Java 
> applets are no longer used.  Instead, we knuckled down and addressed 
> the vulnerabilities.
>
> I had to remove circular links because they introduce security 
> vulnerabilities, I also limited the number of bytes the stream can 
> download before it must be reset, otherwise an IOException is thrown 
> and control is returned to the caller.  It uses constructors, and all 
> classes are expected to validate invariants.  We've discussed it 
> previously.  Apart from Collection classes, serial form of existing 
> classes has not been altered, instead classes have new Constructor's 
> that are used to validate their de-serialized fields.  All fields have 
> also undergone their own validation process.  J.B. called it atomic 
> serialization, when we first discussed it, so that's what we call it.
>
> My first step was to re-implement deserialization and use that for 
> some time with the new deserialization public API,  I'm currently 
> implementing a public API for serialization.  After this I will 
> introduce more serialization protocols that use the same API, at that 
> time I may have to change the serial form of some classes, as Java 
> serialization had a lot of complex features that other serialization 
> protocols lack.  The deserialization api, is capable of supporting 
> multiple serial forms, to allow class implementations to change them.
>
> Certain Java Collection classes are vulnerable to denial of service 
> attacks, so they are not serialized, instead I have serializers that 
> transfer the data, which is validated during deserialization, before 
> populating the Java Collection classes via constructors.  This means 
> any Collection class can be serialized, even those that don't 
> implement Serializable, they all have the same serial form, so their 
> serialized form basically respects the Collection interfaces of Map, 
> Set and List, their bytes can be compared for equality, for example if 
> two Map's are equal, their serialized bytes will also be equal.
>
> Furthermore serialization filters have the same complexity flaws as 
> the Security Manager model, but in our case we use SecurityManager to 
> grant a limited set of privileges that we are able to establish prior 
> to loading dynamic code.    We already have a profiling tool that 
> generates policy files.
>
> Once SecurityManager is removed, third party code will have all 
> permission's granted to the JVM, so they will be able to view files 
> and make network connections.   The serialization filters offer a 
> similar level of complexity, but with less protection and less time 
> for tool development.  No doubt this will require us to rethink the 
> structure of our software and access control to sensitive data.
>
> Once we fixed Policy performance issues and created profiling tools 
> for initial creation of policy files, which are used as a guide to 
> create the requested permission lists and enable permissions to be 
> granted dynamically at runtime, security becomes a significant benefit 
> rather than a burden.
>
> To quote waratek: reference 
> https://www.waratek.com/java-serialization-filtering/
>
>> To configure Serialization Filtering, the application needs to first 
>> be fully profiled. *Profiling* an app can be a complex process that 
>> requires specialized tools and has to be performed by domain experts. 
>> Typically, the process requires the app to run normally for a period 
>> of time in order for all its paths to be executed. A dynamic 
>> profiling tool can log the class names that are required for normal 
>> operation. This list of class names will then be the basis of 
>> configuring the white/black list of the Serialization Filters. And 
>> even after going through this process, there is no guarantee that all 
>> of the execution paths were run and all the required class names were 
>> logged. Of course, the same process needs to be performed every time 
>> a new release goes into production or even when a third-party library 
>> must be upgraded. The lifecycle of this process becomes even more 
>> complex since such any change in the Serialization Filters will first 
>> need to go through QA and UAT before it reaches production.
>>
>> The Serialization Filtering mechanism follows a very similar approach 
>> to the Security Manager 
>> <https://docs.oracle.com/javase/7/docs/api/java/lang/SecurityManager.html>. 
>> The Security Manager also works based on a whitelist 
>> <https://docs.oracle.com/javase/tutorial/security/tour2/step3.html> 
>> and suffers from the same scalability problems. Java’s Security 
>> Manager has proved to be unsuitable for enterprise, large-scale 
>> environments, given that *it moves the responsibility of protecting 
>> the system to the user*. The user is responsible for understanding 
>> the application’s security requirements and technical details and 
>> correctly configuring the security policy, which in essence is a 
>> whitelist of permissions. Such security policies are typically very 
>> complicated in enterprise applications that change frequently and 
>> integrate with numerous different systems and components. The 
>> *operational cost* of correctly configuring and maintaining such 
>> security policies is so high that Security Manager is rarely deployed 
>> in production environments [6 
>> <http://www.hpl.hp.com/techreports/98/HPL-98-79.pdf>] [7 
>> <http://tomcat.apache.org/tomcat-7.0-doc/security-howto.html>].
>>
>
> I would elaborate that the above problems with SecurityManager have 
> been address in practice, as we've had many years to address them, 
> these solutions are not included with Java of course.  The 
> responsibility is not with the user, but developers and administrators.
>
> Also it has become apparent to me, that Java is following in the 
> footsteps of Unix.   First workstations were replaced by cheaper PC's, 
> so the workstation market was lost, then the PC version of Unix, Linux 
> ate Unix's lunch in the Server market. Java no longer has a client 
> market, no longer on phones or the browser, some desktop deployments, 
> it has largely retreated to servers.  Be careful not to diminish 
> Java's market too much, lest Android eat Java's server market lunch.  
> Android has a newer fine grained security model, I don't know if it 
> can be applied to a server environment.   I don't mean to be 
> inflammatory, just giving you ammunition, should you require it.
>
> -- 
> Regards,
>   
> Peter Firmstone
> Zeus Project Services Pty Ltd.
>
>
>>
>> --Sean
>>
>> [1] 
>> https://docs.oracle.com/en/java/javase/16/core/serialization-filtering1.html#GUID-3ECB288D-E5BD-4412-892F-E9BB11D4C98A
>> [2] https://inside.java/2021/04/06/record-serialization-in-practise/

-- 
Regards,
  
Peter Firmstone
0498 286 363
Zeus Project Services Pty Ltd.



More information about the jdk-dev mailing list