On 21/06/2023 8:52 pm, Ron Pressler wrote:

On 21 Jun 2023, at 01:36, Peter Firmstone<peter.firmst...@zeus.net.au>  wrote:


I'm just disappointed that we are being prevented from reimplementing a 
replacement authorization layer in Java, without any compromise from OpenJDK 
it's not possible.  We at least need to retain some kind of privilege action 
mechanism.   That doesn't even have to be a privileged action, maybe it could 
be an annotation, that we can find using StackWalker.
Maintaining that information is the very thing that makes the mechanism so 
expensive. Annotations wouldn’t make it any easier, because their placement 
would still have to be tested and maintained. No one is preventing you from 
maintaining that information yourself, and you are free to inject such 
annotations into the JDK to your heart’s content. If it really isn't too much 
work then we all win — we don’t have to do it and test it, and you still get to 
have it.


I wish it was that simple, it's an auditors nightmare.



If data protected isn't of high value, or is of low complexity, a solution of 
appropriate cost will be applied, in many cases that isn't SM, however removing 
SM will reduce security below an acceptable level for a percentage of 
developers and software projects, the number may be small, but the impact will 
be widespread, just look at how widely deployed ElasticSearch and OpenSearch 
are.
That is clearly untrue because even the most security sensitive applications 
already prefer alternatives that they find superior. We’re not sending people 
over to other alternatives; people first abandoned SM in favour of alternatives 
and *then* we figured it’s time to remove SM when few were left using it. I 
believe ElasticSearch are now relying on strong encapsulation to maintain their 
Java-level security invariants.

I would suggest looking into it a little further before dismissing it out of hand or making assumptions.

This discussion on OpenSearch is worth a read. https://github.com/opensearch-project/OpenSearch/issues/1687

    My question is still/why/? That's why I asked@davidlago
    <https://github.com/davidlago>of what actual CVEs JSM mitigated.
    There's some effort to "move security into core", with that,@rmuir
    <https://github.com/rmuir>@uschindler
    <https://github.com/uschindler>what is your argument for not
    removing JSM?

Because currently I don't see replacements for a lot of the functionality. Meanwhile the protection still works so why discard the only security mechanism that you have? I think I explained above, but to summarize for specific vulnerabilities that are of concern (e.g. have happened before), in a world without a security manager, I think the easiest win is to harden the systemd service, Currently it is very weak and insecure:https://github.com/opensearch-project/OpenSearch/blob/main/distribution/packages/src/common/systemd/opensearch.service

These are some of the historically problematic issues that the security manager prevents... aka the worst-of-the-worst:

  * RCE: there's some protection by seccomp etc via systemcallfilter
    which disables fork/exec at OS level. So even without security
    manager, there is at least basic protection from allowing someone
    to execute coin miner or whatever. This piece has to remain as you
    can't block fork/exec with systemd seccomp filters... But I'd
    still recommend to start hardening the systemd service
    with|SystemCallFilter=|to take it further (the seccomp bpf rules
    will "nest" just fine).
  * File/Directory traversal et al: currently the security manager is
    the only thing restricting the filesystem. opensearch does not
    need to be able to access files in users home directories or
    anything like that. If there is a bug in the code that would allow
    this, instead of accessing users private files, security manager
    will deliver a SecurityException. but, alternatively, the
    directories that can be read and written can be nicely restricted
    with systemd service as well (stuff like|ReadWritePaths=|)

I recommend looking at a secure systemd service as an example, and comparing it to the current one, here is a good one:https://github.com/archlinux/svntogit-community/blob/packages/dnscrypt-proxy/trunk/dnscrypt-proxy.service

You may also use|systemd-analyze security opensearch.service|to track your progress, it will suggest improvements.


<SNIP>


Lets discuss how it should be used, and what benefits it provides and the 
situations when you might want to use it.    I only ask that people keep an 
open mind and for the moment, forget all the horror stories.  I realise this is 
academic now, and unlikely to change anything, however documenting it here 
might serve some historical purpose.
Okay, but we, .NET (the other platform that had a similar mechanism), and most 
security experts have lost faith in the approach and gained faith in newish 
OS-level protections that weren’t available when SM was introduced (and also 
offer protection for native code as well as better protection from some DOS 
attacks); no new security sensitive platform seems to take that stack-based 
approach, either. This means that even if we’re wrong on the technical merits, 
such a feature is so far from the mainstream practice that it has no room in a 
mainstream language. If some day it becomes mainstream again things may change.

Still, here’s one thing about the technical aspect: “Trusted” does not mean “free of 
vulnerabilities” but "assumed to not be malicious.” Libraries can and do have 
vulnerabilities, but I think that strong encapsulation is much more effective in 
controlling their blast radius, and it has significant non-security-related 
benefits, too (not that most developers are rushing to apply strong encapsulation to 
their own code, but at least we’re able to encapsulate the JDK itself). By 
“effective” I don’t mean “powerful”, but rather “provides more value on average when 
all aspects are considered”. With strong encapsulation you only need to check that a 
particular code unit that performs an operation on behalf of a user (authorised at 
the application operation level) doesn’t do anything problematic. Other units cannot 
break your unit’s invariants, so only local reasoning is required (true, the size of 
the unit is not as small as could be afforded by a stack-based approach, but it is 
still local and contained). If you’re interested in gadget attacks, I suggest you 
think about how many of them can be prevented by strong encapsulation alone and how 
many could be prevented by a combination of strong encapsulation and OS-level 
protections that apply to the entire process (you can throw in serialization 
filters, too). In other words, don’t think just about what SM could do for you, but 
also think about what the more popular approaches do for you, too (taking your own 
advice of considering how they can be best applied, not misapplied) and then 
consider how much effort should be put to close the *delta* between the two.

I agree with you regarding the benefits of encapsulation.

Prior to serial filters, we reimplemented Java deserialization, we used a standardised constructor signature, and we removed the ability to serialize graphs with circular references, we placed data limits on streams, cumulative limits on array sizes and required a periodical reset, we basically applied strong encapsulation with atomic failure and input validation to serialization to eliminate gadget attacks.

We've got a mature implementation for managing authentication and authorization in a dynamic distributed environment.   It's not a simple problem to solve, so the complexity likely comes from the problem domain, rather than the solution.   I've been using it many years, and over those years, the problems have all been solved one by one, to the point where it's a well understood stable solution for our problem domain.

But the reality is, there are no other existing solutions, so we are unable to migrate, we need an actual concrete implementation, promising future developments are great, but we need a clear migration path, today no such alternative technology exists.  As you pointed out .NET has removed their equivalent, so we can't migrate to .NET either.   Like all problems, someone will come up with a better solution at some point, when they do, we'll migrate to that, until then, we have to continue using what we have. OpenJDK doesn't know the answer, and they don't want the burden of the existing solution, that's fair enough.   We need to be honest with our users, we don't have a future migration path with Java at this time.

Perhaps it will be solved like concurrency was with functional programming, another language will solve it elegantly, hey maybe Java will copy the functionality :)

Anyway, we know where we stand now and that's better than thinking we had a migration option when we didn't.

- Peter.


Code signing is a completely separate topic; expect some developments in that 
area.

— Ron

Reply via email to