It lets the hacker take over the machine because there are strings which are interpreted as (IIUC, I am not a java engineer) variables within a class, and you can express a remote URL to load a class from, apparently (through something like (jndi://... ldap... URL), resulting in fetching code from somewhere and running it, in the service of writing a log message. This is apparently being exploited in the minecraft ecosystem by simply writing chat messages containing the full exploit, which gets executed by both servers and clients.
By my understanding the RCE part of the exploit should not apply to recent java versions if the default options are used (minecraft shipped older version afaik, and all bets are off for unmaintained enterprise applications).
The data extraction however will work on any java version if the server in question has the capability to connect to a server under the control of an attacker, as the network request will be performed even if the JVM options that should avoid the RCE are enabled. Big problem for client applications (as usually most outgoing connections are allowed).
A bit harder to evaluate the impact in the enterprise context as many companies will not allow their servers to connect to "random" endpoints or at least require target-specific proxies to connect to the internet/intranet which makes this harder to exploit.
According to the manpage, -color can be shortened to -c and link shortened to `l`, as `addr` can be shortened to `a`. -br stands for -brief, which knowing makes it easier to remember.
I agree with nhooyr's analysis. The interface{} will anyway transparently "contain" a pointer-to-the-[]byte, in other words, the []byte value itself will be heap allocated.
(Note for anyone new to this that the "[]byte-value" - we say "the byte slice" - is a distinct thing from the "values stored-in-the-byte-slice", which is a heap allocated backing array)
What you're seeing is the LLVM IR for the program being printed. As another commenter noted, you can compile the program with make, which just runs `clang` on that IR.
Indeed, I had to take certain liberties in order to cram the talk into 20 minutes! I hope one of the takeaways was that you don't need to implement a parser to get started playing with this sort of thing.
AFAICT parsing is the easy part, admittedly more than 20 minutes but... (Also AFAICT) Go was specifically designed for easy lexing/parsing as part of their core principals.
After you get from text->AST is when all the magic happens. I've been reading up on this off and on for the last year or so and it's less magic than breaking the problem down into (not quite) simple steps that can be studied individually.
It's actually a quite fascinating field to go diving down the rabbit hole -- there's a lot of "lost" ideas from 20-30 years ago that one could take from pseudo-code to a fairly reasonable compilation pipeline without too much trouble. True, it wouldn't win on any benchmark test against something like LLVM with their millions of person hours invested in the optimation phases but it would be reasonable none the less.
Great, we can control for layout of code, heap, stack and other effects which mess with a performance measurement. However, why do those things have a (statistically significant?) impact in the first place? I guess that hints that with some engineering you could in principle get a speed boost by specifying the layout. "Worst case", you sample randomly and then pick the fastest arrangement, where it is statistically significant.
It could be that the problem arises when trying to measure very small speed increases (small relative differences => noise matters more). But in that case the fact that such a small speed increase is wiped out by random layout effects surely means that time would be better invested in finding a more performant layout?
> why do those things have a (statistically significant?) impact in the first place?
In a word, caches. Not just the instruction / data cache, but also page faults and micro-architectural features like micro-op caches, instruction TLB entries, loop stream buffers, cache-line alignment, and aliasing in the branch predictor tables (which can also be thought of as caches).
I suppose I was musing more along the lines of "why isn't this a solved problem". Clearly, it isn't an easy one or compilers would already take this into account and then the statistical variance would be reduced.
Yes, it's important to measure and control the effects of things like topology/affinity, which can have factors of several effects on HPC program efficiency. You shouldn't suffer much variance on single-node compute, but it's different when you're subject to effects on/of the network fabric and filesystem.
I tried it. If you had a super serious algorithm where you were will to spend any money to test it (a central security algorithm for example), it might be worth it.
The problem I had is that there were many many mutations which led to code which was functionally identical, just a bit slower, or took a different route. You have to manually verify every mutation to check if this.
For one mutation it took me 30 minutes to convince myself the algorithm was still doing the same thing, just in a different way.
I haven't worked with it extensively, but from what I've seen, it's far beyond what most teams should consider. It's basically a more thorough method of measuring test coverage, pointing out cases that have not been covered by your tests yet. However, the number of tests that it would have you write to reach 100% mutation coverage is not justified by the number of bugs you'll catch, unless the impact of any bug is very high (I suppose at NASA?). In fact, the amount of work required to even check which tests you missed is already not justified.
I usually use coverage as a tool to remind me of pieces of code I intended but forgot to test [1], so setting it to an arbitrary percentage is not that useful, in my opinion. If 100% is not feasible usually as well, that makes Mutation Testing in general not worth the effort.
I think mutation testing really shines in code bases that are already heavily tested, because it let's you discover test cases that you don't actually need. Tests are a burden since you have to adapt them when you change the behavior. With mutation testing you can prune your test code by identifying tests that test very similar behavior.
Would that be done based on which (different) tests killed a particular mutant?
Often an integration test would catch the multiple mutations also being caught by (different) unit tests.
I assume that you mean that if a certain (broader) test kills the same mutants as X unit tests, those X tests are not really necessary?
I've looked into https://github.com/boxed/mutmut and https://github.com/sixty-north/cosmic-ray for Python project, and there it is only important that a mutant gets killed, but not how often and by which tests (therefore you can use `pytest -x` to continue with the next mutation after the first test failed due to it).
Me neither, I liked the concept of mutation testing. (I was using this performing changes manually, without knowing this technique has a nice name).
I would appreciate if somebody points out a mutation framework /tools for .net
There's something that used to be called Pex, and now is apparently called IntelliTest [1], but I believe it's only available in the Enterprise edition of Visual Studio.
The crux of it is that the tool does an efficient pairwise merge of all commits from the donor branch onto master. It can also be configured to run the test suite to detect conflicts.
Then you resolve conflicts in pairs of commits, which is only a small amount of work. The histories of your individual resolutions are preserved, so you can pause and resume the task.