Fwd: Low level hooks in JDK for instrumentation of permission checks.
Forgot to cc. Forwarded Message Subject: Re: Low level hooks in JDK for instrumentation of permission checks. Date: Mon, 14 Jun 2021 15:13:15 +1000 From: Peter Firmstone To: jdk-...@openjdk.java.net Clarification, utilize java.security.Provider. So this might use a module declaration or META-INF/services/java.security.Provider, sorry got muddled with typical ServiceLoader usage below. The reason for choosing Provider is that it allows constructor parameters, it's also security related and can require code signing, not sure if that should be a requirement. Another reason for using security provider is to avoid deadlock during Provider initialization, it must be listed as a provider in the java.security file or if security.overridePropertiesFile=true and -Djava.security.properties=file://path/additional.security defines providers, which would be useful for testing. Dynamic loading a provider using Security.addProvider or insertProviderAt causes security checks, each Guard::check call would try to initiate "SECURITY" Provider loading causing deadlock. To avoid deadlock at the very least the "SECURITY" and "PROPERTY" java.security.Guard services would need to be loaded by java.security at startup. grant codebase "jrt:/java.xml.crypto" { permission java.util.PropertyPermission "java.specification.version", "read"; permission java.security.SecurityPermission "putProviderProperty.XMLDSig"; }; Need to be careful with loading and recursive permission checks, it's ok if a permission check fires off permission checks that cause loading of other providers, we just can't ask the provider that is being dynamically loaded to perform permission checks on itself, or any circular relationship between providers. Basically it's good to have separate providers for each permission type as it helps avoid deadlocks. grant codebase "jrt:/jdk.crypto.cryptoki" { permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; }; On 14/06/2021 9:56 am, Peter Firmstone wrote: Some thoughts on hooks: * Utilize the Service Provider API, so as not to expose jdk implementation code. META-INF/services/java.security.Guard * Allow existing Permission classes to remain backward compatible, declare them as services, so that SecurityManager can be degraded as planned and these services are gradually removed. (Removes dependencies on Permission instance types). * Guard implementation is required to have a constructor with two String arguments, (String name, String actions). * Service must implement Guard interface. * Doesn't depend on Permission or any existing implementation classes, completely customizable by the service implementation. * Application developers can also implement hooks using this service. Break up guard service providers into current Permission types: "AWT" "FILE" "SERIALIZABLE" "MANAGEMENT" "REFLECT" "RUNTIME" "NET" "SOCKET" "URL" "FILE-LINK" "SECURITY" "SQL" "LOGGING" "PROPERTY" "MBEAN" "MBEAN-SERVER" "MBEAN-TRUST" "SUBJECT-DELEGATION" "TLS" "AUTH" "KERBEROS-DELEGATION" "KERBEROS-SERVICE" "PRIVATE-CREDENTIAL" "AUDIO" "JAXB" "WEB-SERVICE" I would like to suggest adding a new provider type: "PARSE-DATA" - To be called by any code about to parse data, eg deserialization, XML, JSON, SQL, etc. Granted to users, so that it can only be performed after authentication. -- Regards, Peter Firmstone 0498 286 363 Zeus Project Services Pty Ltd.
Re: Low level hooks in JDK for instrumentation of permission checks.
Some thoughts on hooks: * Utilize the Service Provider API, so as not to expose jdk implementation code. META-INF/services/java.security.Guard * Allow existing Permission classes to remain backward compatible, declare them as services, so that SecurityManager can be degraded as planned and these services are gradually removed. (Removes dependencies on Permission instance types). * Guard implementation is required to have a constructor with two String arguments, (String name, String actions). * Service must implement Guard interface. * Doesn't depend on Permission or any existing implementation classes, completely customizable by the service implementation. * Application developers can also implement hooks using this service. Break up guard service providers into current Permission types: "AWT" "FILE" "SERIALIZABLE" "MANAGEMENT" "REFLECT" "RUNTIME" "NET" "SOCKET" "URL" "FILE-LINK" "SECURITY" "SQL" "LOGGING" "PROPERTY" "MBEAN" "MBEAN-SERVER" "MBEAN-TRUST" "SUBJECT-DELEGATION" "TLS" "AUTH" "KERBEROS-DELEGATION" "KERBEROS-SERVICE" "PRIVATE-CREDENTIAL" "AUDIO" "JAXB" "WEB-SERVICE" I would like to suggest adding a new provider type: "PARSE-DATA" - To be called by any code about to parse data, eg deserialization, XML, JSON, SQL, etc. Granted to users, so that it can only be performed after authentication. -- Regards, Peter Firmstone Zeus Project Services Pty Ltd. On 13/06/2021 8:34 pm, Peter Firmstone wrote: Thanks Alan, I've been thinking that it may be preferable to have hooks that allowed us to inject our own permission checks, rather than retaining existing permission checks. An implementation can override Guard::check without requiring a provider mechanism. The other advantage is the ability to customize Permission implementations, such as allowing address ranges in a SocketPermission implementation and not consulting DNS to resolve host names. Cheers, Peter. On 10/06/2021 11:55 pm, Alan Bateman wrote: On 10/06/2021 07:40, Peter Firmstone wrote: Just a quick question, would it be possible that some JFR hooks might also be useable for an authorisation layer? JFR events can't be used to intercept/veto operations, assuming that is what you are asking. However, it might be that JFR events are monitored as part of some overall security approach that takes into account events recorded for health, performance, or troubleshooting purposes. -Alan
Re: Low level hooks in JDK for instrumentation of permission checks.
Thanks Alan, I've been thinking that it may be preferable to have hooks that allowed us to inject our own permission checks, rather than retaining existing permission checks. An implementation can override Guard::check without requiring a provider mechanism. The other advantage is the ability to customize Permission implementations, such as allowing address ranges in a SocketPermission implementation and not consulting DNS to resolve host names. Cheers, Peter. On 10/06/2021 11:55 pm, Alan Bateman wrote: On 10/06/2021 07:40, Peter Firmstone wrote: Just a quick question, would it be possible that some JFR hooks might also be useable for an authorisation layer? JFR events can't be used to intercept/veto operations, assuming that is what you are asking. However, it might be that JFR events are monitored as part of some overall security approach that takes into account events recorded for health, performance, or troubleshooting purposes. -Alan -- Regards, Peter Firmstone 0498 286 363 Zeus Project Services Pty Ltd.
Re: Low level hooks in JDK for instrumentation of permission checks.
On 10/06/2021 07:40, Peter Firmstone wrote: Just a quick question, would it be possible that some JFR hooks might also be useable for an authorisation layer? JFR events can't be used to intercept/veto operations, assuming that is what you are asking. However, it might be that JFR events are monitored as part of some overall security approach that takes into account events recorded for health, performance, or troubleshooting purposes. -Alan
Re: Low level hooks in JDK for instrumentation of permission checks.
Just a quick question, would it be possible that some JFR hooks might also be useable for an authorisation layer? Regards, Peter. On 9/06/2021 11:35 am, Peter Firmstone wrote: Apologies in advance if this seems like paranoid security. As you are likely now aware, we have been using SecurityManager a little differently than recommended as we adapted it to our requirements. Sometimes it's not always easy to explain or obvious why something is done in a certain way. It's clear we can use StackWalker to implement AccessController functionality. And it's also clear we can use ThreadLocal or Scope Local's to preserve the user Subject across threads. Going forward we will need low level hooks in the JDK for our authentication layer, clearly this is an opportunity to further simplify and improve our authentication layer. Because we use a remote service architecture, with proxy's, the proxy's are dynamically granted permission's after Service Authentication, these permissions also require the user principal to be logged in, we may have a number of services on the stack, for example to participate in a transaction. We have a tool to generate least privilege policy files. There are two reasons we do this: 1. Simplicity of administration and auditing of policy files. 2. Limit the permissions of code, and grant certain permissions to users to ensure users are authenticated before allowing data parsing. An example of item two, is our services require users to be logged in to ensure that any data provided by the user is a trusted data source (we still check the data). We re-implemented a subset of Java Serialization and have a DeSerializationPermission, which is granted to Principals of users. If a user is not logged in, data cannot be de-serialized, because the code alone doesn't have permission to do so. Hopefully modules and packages will have strong encapsulation in future so we don't need permission's like java.lang.RuntimePermission "accessClassInPackage.*" No doubt we will need to create our own Permission's. We would like to be able to limit data parsing, like XML or Java de-serialization, to logged in users only. We don't break encapsulation, in future we will only use reflection to call public methods and constructors (we are currently in the process of doing so). Our build systems use Maven, our build is modular. I would also like to request that all JDK modules be given ProtectionDomain's with CodeSource's for modules with meaningful URL's jrt:java.* or jrt:jdk.* following SecurityManager deprecation. Currently some modules have null ProtectionDomain's to show they have AllPermission. However we don't grant AllPermission to code in practise, we like to grant certain Permission's to Principal's, not code, where the Principal is the source of data, indicating the user has been authenticated and we only grant what's necessary and no more. Examples of permission's granted to JDK modules in POLP policy files, taken from a test harness: grant codebase "jrt:/jdk.security.jgss" { permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; permission java.security.SecurityPermission "putProviderProperty.JdkSASL"; }; grant codebase "jrt:/jdk.crypto.mscapi" { permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; permission java.lang.RuntimePermission "loadLibrary.sunmscapi"; permission java.security.SecurityPermission "putProviderProperty.SunMSCAPI"; }; grant codebase "jrt:/jdk.localedata" { permission java.lang.RuntimePermission "accessClassInPackage.sun.util.locale.provider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.util.resources"; }; grant codebase "jrt:/jdk.security.auth" { permission java.io.FilePermission "C:\\Users\\peter\\Documents\\NetBeansProjects\\JGDMS\\qa\\lib\\jiniharness.jar", "read"; permission javax.security.auth.AuthPermission "modifyPrincipals"; permission javax.security.auth.AuthPermission "modifyPrivateCredentials"; permission javax.security.auth.AuthPermission "modifyPublicCredentials"; permission java.lang.RuntimePermission "accessClassInPackage.sun.security.krb5"; permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; permission java.lang.RuntimePermission "getProtectionDomain"; }; Example of POLP grant to code with principal, code alone cannot access these, in case you are wondering, we use this to secure the RMI Registry using stateless TLSv1.3, it's used by our Service Watchdog, or Service Activation framework called Phoenix, it's the sole use we have of the Java RMI JRMP protocol, in cases where this isn't used we can disable Java Serialization completely: grant codebase "file:/C:/Users/peter/Documents/NetBeansProjects/JGDMS/JGDMS/dist/target/JGDMS-3.1.1-SNAPSHOT/lib/jgdms-rmi-tls-3.1.1-SNAPSHOT.jar", principal
Re: Low level hooks in JDK for instrumentation of permission checks.
Thanks Alan, You've hit the nail on the head. In policy implementations, a null CodeSource in PD, is assigned AllPermission. So it would require adding grant statements for these modules in the default policy file that ships with the JVM. I thought it's an opportunity to make ProtectionDomain a little more useful if it maps to modules. Gut feel is it would be relatively low risk, but as you correctly state, would require testing. I'm not able to lodge on Jira, but I thought this would be worthy update. Regards, Peter. On 10/06/2021 4:22 pm, Alan Bateman wrote: On 10/06/2021 03:49, Peter Firmstone wrote: Hi Sean, Sorry I've confused you. What I should have said is a ProtectionDomain with a null CodeSource. What I mean to ask is, where ProtectionDomain is created with a null CodeSource, in Class::getProtectionDomain() can we have CodeSource's that represents system modules instead of null? A CodeSource with URL's like jrt:/jdk.* or jrt:/java.* for system modules? This is already the case for system modules that are mapped to the platform or application class loaders. I think your question is about modules that are mapped to the boot loader and whether they should get a unique PD that includes a useful code source rather than using a "shared" PD. That would be changing long standing behavior and would require careful analysis to see if anything would break. -Alan
Re: Low level hooks in JDK for instrumentation of permission checks.
On 10/06/2021 03:49, Peter Firmstone wrote: Hi Sean, Sorry I've confused you. What I should have said is a ProtectionDomain with a null CodeSource. What I mean to ask is, where ProtectionDomain is created with a null CodeSource, in Class::getProtectionDomain() can we have CodeSource's that represents system modules instead of null? A CodeSource with URL's like jrt:/jdk.* or jrt:/java.* for system modules? This is already the case for system modules that are mapped to the platform or application class loaders. I think your question is about modules that are mapped to the boot loader and whether they should get a unique PD that includes a useful code source rather than using a "shared" PD. That would be changing long standing behavior and would require careful analysis to see if anything would break. -Alan
Re: Low level hooks in JDK for instrumentation of permission checks.
Hi Sean, Sorry I've confused you. What I should have said is a ProtectionDomain with a null CodeSource. What I mean to ask is, where ProtectionDomain is created with a null CodeSource, in Class::getProtectionDomain() can we have CodeSource's that represents system modules instead of null? A CodeSource with URL's like jrt:/jdk.* or jrt:/java.* for system modules? Hopefully my comments below will make a little more sense now. Regards, Peter. On 10/06/2021 1:07 am, Sean Mullan wrote: On 6/8/21 9:35 PM, Peter Firmstone wrote: I would also like to request that all JDK modules be given ProtectionDomain's following SecurityManager deprecation. Currently some modules have null ProtectionDomain's to show they have AllPermission. However we don't grant AllPermission to code in practise, we like to grant certain Permission's to Principal's, not code, where the Principal is the source of data, indicating the user has been authenticated and we only grant what's necessary and no more. As described in JEP 411, there are no plans to deprecate ProtectionDomain at this time. --Sean
Re: Low level hooks in JDK for instrumentation of permission checks.
On 6/8/21 9:35 PM, Peter Firmstone wrote: I would also like to request that all JDK modules be given ProtectionDomain's following SecurityManager deprecation. Currently some modules have null ProtectionDomain's to show they have AllPermission. However we don't grant AllPermission to code in practise, we like to grant certain Permission's to Principal's, not code, where the Principal is the source of data, indicating the user has been authenticated and we only grant what's necessary and no more. As described in JEP 411, there are no plans to deprecate ProtectionDomain at this time. --Sean
Low level hooks in JDK for instrumentation of permission checks.
Apologies in advance if this seems like paranoid security. As you are likely now aware, we have been using SecurityManager a little differently than recommended as we adapted it to our requirements. Sometimes it's not always easy to explain or obvious why something is done in a certain way. It's clear we can use StackWalker to implement AccessController functionality. And it's also clear we can use ThreadLocal or Scope Local's to preserve the user Subject across threads. Going forward we will need low level hooks in the JDK for our authentication layer, clearly this is an opportunity to further simplify and improve our authentication layer. Because we use a remote service architecture, with proxy's, the proxy's are dynamically granted permission's after Service Authentication, these permissions also require the user principal to be logged in, we may have a number of services on the stack, for example to participate in a transaction. We have a tool to generate least privilege policy files. There are two reasons we do this: 1. Simplicity of administration and auditing of policy files. 2. Limit the permissions of code, and grant certain permissions to users to ensure users are authenticated before allowing data parsing. An example of item two, is our services require users to be logged in to ensure that any data provided by the user is a trusted data source (we still check the data). We re-implemented a subset of Java Serialization and have a DeSerializationPermission, which is granted to Principals of users. If a user is not logged in, data cannot be de-serialized, because the code alone doesn't have permission to do so. Hopefully modules and packages will have strong encapsulation in future so we don't need permission's like java.lang.RuntimePermission "accessClassInPackage.*" No doubt we will need to create our own Permission's. We would like to be able to limit data parsing, like XML or Java de-serialization, to logged in users only. We don't break encapsulation, in future we will only use reflection to call public methods and constructors (we are currently in the process of doing so). Our build systems use Maven, our build is modular. I would also like to request that all JDK modules be given ProtectionDomain's following SecurityManager deprecation. Currently some modules have null ProtectionDomain's to show they have AllPermission. However we don't grant AllPermission to code in practise, we like to grant certain Permission's to Principal's, not code, where the Principal is the source of data, indicating the user has been authenticated and we only grant what's necessary and no more. Examples of permission's granted to JDK modules in POLP policy files, taken from a test harness: grant codebase "jrt:/jdk.security.jgss" { permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; permission java.security.SecurityPermission "putProviderProperty.JdkSASL"; }; grant codebase "jrt:/jdk.crypto.mscapi" { permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; permission java.lang.RuntimePermission "loadLibrary.sunmscapi"; permission java.security.SecurityPermission "putProviderProperty.SunMSCAPI"; }; grant codebase "jrt:/jdk.localedata" { permission java.lang.RuntimePermission "accessClassInPackage.sun.util.locale.provider"; permission java.lang.RuntimePermission "accessClassInPackage.sun.util.resources"; }; grant codebase "jrt:/jdk.security.auth" { permission java.io.FilePermission "C:\\Users\\peter\\Documents\\NetBeansProjects\\JGDMS\\qa\\lib\\jiniharness.jar", "read"; permission javax.security.auth.AuthPermission "modifyPrincipals"; permission javax.security.auth.AuthPermission "modifyPrivateCredentials"; permission javax.security.auth.AuthPermission "modifyPublicCredentials"; permission java.lang.RuntimePermission "accessClassInPackage.sun.security.krb5"; permission java.lang.RuntimePermission "accessClassInPackage.sun.security.util"; permission java.lang.RuntimePermission "getProtectionDomain"; }; Example of POLP grant to code with principal, code alone cannot access these, in case you are wondering, we use this to secure the RMI Registry using stateless TLSv1.3, it's used by our Service Watchdog, or Service Activation framework called Phoenix, it's the sole use we have of the Java RMI JRMP protocol, in cases where this isn't used we can disable Java Serialization completely: grant codebase "file:/C:/Users/peter/Documents/NetBeansProjects/JGDMS/JGDMS/dist/target/JGDMS-3.1.1-SNAPSHOT/lib/jgdms-rmi-tls-3.1.1-SNAPSHOT.jar", principal javax.security.auth.x500.X500Principal "CN=Phoenix" { permission java.util.PropertyPermission "javax.net.ssl.trustStore", "read"; permission java.util.PropertyPermission "javax.net.ssl.trustStorePassword", "read"; permission java.util.PropertyPermission