Тёмный

Log4j Lookups in Depth // Log4Shell CVE-2021-44228 - Part 2 

LiveOverflow
Подписаться 893 тыс.
Просмотров 70 тыс.
50% 1

Опубликовано:

 

2 окт 2024

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 254   
@jeffvalore5010
@jeffvalore5010 2 года назад
your "secure design" section hits the nail on the head. They made the classic mistake of trusting user input, and never considered "how could this be abused?". JNDI aside, it shouldn't have taken a whole lot of thought to consider that anyone who has access to read the logs but not access the server or code directly, can just log all the server env vars (DB connection strings? AWS creds?) and potentially steal information. IMO this entire substitution "feature" of log4j never should have existed. Even if it was "secure" this is still a lot of bloat for features that a very small subset of log4j users would ever utilize.
@theyreMineralsMarie
@theyreMineralsMarie 2 года назад
Exactly, this is a classic separation of responsibilities problem. No logging framework needs to also have this level of environment lookup functionality.
@Lukas12220
@Lukas12220 2 года назад
Or disable the feature by default
@mskiptr
@mskiptr 2 года назад
Yep, this is a job for plain variables and lambdas and not a separate string evaluation engine
@TheCardil
@TheCardil 2 года назад
Log4j did nothing wrong, apart from having to much features. The culprit here are developers who pass user controlled data to be logged. That should never be done. Those values belong only to the internal database, and shouldn't be leaked to logs. If devs wouldn't log user data, it would be safe to get logs from production. Often that's not possible as they are littered with user owned data.
@hb-man
@hb-man 2 года назад
@@TheCardil Logging uncontrollable user data is what logging is about: "Could not login user 'attackerstring', wrong password." You cannot expect the developer to escape for any special chars to prevent code injection, just because the logging engine has surprising features.
@rjhornsby
@rjhornsby 2 года назад
I’ve always liked your sort of casual handwritten visual style, and it especially shines here. I can more or less read Java, but there’s so much code in just this one tiny - almost incidental - library, it’s nuts. The way you approach highlighting, focus in on small code blocks, and your red/white callouts make it super easy to follow your narration. So, thanks! and Merry Christmas.
@Fardeus
@Fardeus 2 года назад
true.....
@spicybaguette7706
@spicybaguette7706 2 года назад
I'm curious whether anyone ever has needed the _recursive_ lookups... It's a logging library! Not a string substitution one! Why is this even enabled by default in the first place?
@lgfrbcsgo
@lgfrbcsgo 2 года назад
Because someone somewhere thought it would be a good idea to be able to change the log format on the fly without a redeploy?
@ritamdey8427
@ritamdey8427 2 года назад
This was my reaction when I read about this feature! The lookup and complex formatting should've been a add-on library rather than the main one, which should've stuck with logging strings and simple formatting like %t etc.
@karigucio
@karigucio 2 года назад
for real, never would have thought a logging library somewhere in the code checks for infinite recursion
@desmond-hawkins
@desmond-hawkins 2 года назад
The point is to avoid crashes due to the recursion limit being reached, not to explicitly log recursively. It's common to log the details of some objects with toString(), and sometimes people will log objects that have toString methods that are more complex than they should be. To be clear, none of this is about an ideal case, but to prevent a _worse_ case to an already sub-par situation. If you log an object with toString which causes it to dump a whole bunch of information to try to be helpful, and this information is calling methods… you can easily get into one of these situations. Imagine a Circle class, with a center of type Point and a radius of type float. You could have an overzealous toString do something like: return "Circle(center="+center+", radius="+radius+", area="+this.area(); - now if your call to area() does something like log.debug("computing Circle area for " + this); - then you end up blowing up the stack. Purely by accident.
@kawcco
@kawcco 2 года назад
This library is hilariously bloated. Who knows how many other vulnerabilities are hiding in the Log4J Jungle?
@TenderBug
@TenderBug 2 года назад
What terrifies me is how many Apache libraries out there. Even more so other opensource libraries with big community driven projects. Log4J ! Serving Lookups Since 2013
@kawcco
@kawcco 2 года назад
@@TenderBug Agreed. We need to extensive code review and fuzzing of the entire Apache family so that we can cover our bases.
@jhbonarius
@jhbonarius 2 года назад
Have you read many comparible libraries? In my experience al mature libraries are like that. It's both a result from feature creep and common design patterns. The thing is: everybody's now complaining and nitpicking on this one, as something was found. ( a captain hindsight moment. )
@kawcco
@kawcco 2 года назад
@@jhbonarius The fact that they're all like this *is* bad! I'm not defending **anyone** who writes code like this!
@jhbonarius
@jhbonarius 2 года назад
@@kawcco is it your responsibility to defend them? Anyhow, code usually doesn't start out "bad", but 'evolves' into it over time. Call it "code rot". Especially in understaffed projects this can happen, and log4j was understaffed and open source. This is by far not the worst code I've seen. And considering the popularity of log4j, it wasn't disfunctional.
@cdhagen
@cdhagen 2 года назад
This library is a prime example of over-engineering! That's why I don't 100% agree with people who claim that it's just „because a few overworked guys are thanklessly maintaining this thing for free“. Yes, maybe, but who forces them to build crazy features like this into what *should* be a relatively straightforward logging library?
@lal12
@lal12 2 года назад
No I don't agree. Yes the jndi stuff and java indirections are examples of overengineering and insecure practices. However the bug in specific is basically a classic injection bug, which should be a common pattern how to handle this.
@cdhagen
@cdhagen 2 года назад
@@lal12 True, unless you are overwhelmed by your own complexity. ;-) Also, maybe this library would have more maintainers if it weren't so complex. The fact that this "classic injection bug" has gone unnoticed for so many years speaks volumes.
@lal12
@lal12 2 года назад
@@cdhagen well I don't disagree. And Log4j probably has issues with documentation and usage patterns. That being said it is kind of unfair to blame the developers of Log4j instead of the developers of the individual applications.
@DanKaschel
@DanKaschel 2 года назад
They're not slaves to you or anyone. They're allowed to add features. Even ones with bugs. They define what it "should" be, not you.
@cdhagen
@cdhagen 2 года назад
@@DanKaschel Of course, I can't bar them from adding some more of these golden "features" where a logging library makes random calls over the internet depending on what magic string is passend in. Keep up the good work, I guess! 🤡
@tambling3961
@tambling3961 2 года назад
Holy hell this library is bloated like there's no tomorrow 🤯 Besides the security issues I imagine that it must slow down your code by a significant amount... dafuq
@monognome9202
@monognome9202 2 года назад
As a developer, this vulnerability caused so much chaos throughout the weekend in webapps using Java. But you explaining it makes it seem so simple. Amazing video 🙌🏽🔥
@jamess1787
@jamess1787 2 года назад
I'm still astounded at how much is still written in Java. It's wild.
@monognome9202
@monognome9202 2 года назад
A whole lot man. It blows my mind everyday.
@superblaubeere27
@superblaubeere27 2 года назад
Some people take it a bit too far with the OOP. Splitting code in three-liner functions and douzens of classes does not really help the readability of the code haha
@vert3x560
@vert3x560 2 года назад
ppl just don't understand OOP. They make 3 liner functions, and then some monstrosity 500 lines of code and for-ifs. To be honest. Clean Code clearly says: Keep It Simple. So I can imagine rewriting log4j into some clean representation with almost all features in like no more than 10 classes. One class one feature.
@DanKaschel
@DanKaschel 2 года назад
Good OOP would have prevented this issue. There never should have been multiple places where the nolookup needed to be checked for whether to evaluate a lookup.
@VivekYadav-ds8oz
@VivekYadav-ds8oz 2 года назад
5:18 What was the point of having so many classes and factories and functions if the actual functionality is just shoved into one function?
@VivekYadav-ds8oz
@VivekYadav-ds8oz 2 года назад
No wonder it took so much time to detect this vuln. Most people who just wanted to explore the library were probably intimidated away by how bloat it is. Actual function that does the job has 5-10 functions of bloat over it. Can't believe so much CPU time has been wasted on just Java OOP things throughout the computing history.
@telnobynoyator_6183
@telnobynoyator_6183 2 года назад
not as much cpu time as you might think because java optimizes that away later in the vm, it's more of a readability issue
@luis_musik
@luis_musik 2 года назад
@@telnobynoyator_6183 i think you're overestimating how much the compiler can actually optimize away. most oop features (especially stuff like virtual functions etc) are not zero cost.
@telnobynoyator_6183
@telnobynoyator_6183 2 года назад
@@luis_musik The java compiler doesn't optimize those out, but the JVM almost surely does when translating the java bytecode into binary.
@DelusionalLogic
@DelusionalLogic 2 года назад
@@telnobynoyator_6183 "surely"
@telnobynoyator_6183
@telnobynoyator_6183 2 года назад
@@DelusionalLogic In a sure way
@jhbonarius
@jhbonarius 2 года назад
Hahaha, all these endless (and typical Java) abstraction layers... and then you finally come to the parser, and that's just a much too long method written in a C-style way.
@klotzklotz1
@klotzklotz1 2 года назад
I think another interesting aspect of this vulnerability is that, if your organization used "defense in depth" and configured firewalls to block outgoing LDAP connections, exploitation of the vulnerability does not easily work. Unfortunately many people do not restrict outgoing network connections of their servers though :-(
@berndeckenfels
@berndeckenfels 2 года назад
Yes egress filtering, not for “outgoing ldap” but “outgoing anything” since the attack allows arbitrary tcp ports.
@klotzklotz1
@klotzklotz1 2 года назад
@@berndeckenfels ok, if the target port of the outgoing TCP connection is not necessary the LDAP port I stand corrected :-)
@novelhawk
@novelhawk 2 года назад
4:50 Isn't it pretty much unoptimizable? How are you going to find a substring without iterating the string?
@lassipulkkinen273
@lassipulkkinen273 2 года назад
I was wondering the same thing, although from when I was last using Java (years ago) I think there was an Iterator thing that was supposed to have a small performance advantage over c-style for loops by eliminating bounds checking or something... Also, maybe String.indexOf would be even faster if it has an optimized (i.e. non-JIT-ed) native implementation.
@krzysztofdziembaa4982
@krzysztofdziembaa4982 2 года назад
There are string searching algorithms, which may be faster than "brute force", but (according to an email in Newlib's mailing list) for short strings (which are quite popular) the naive algorithm is the fastest. Other algorithms (may) require preprocessing and/or memory to allow faster searches and whether this pays off depends on the processed data. Two-Way algorithm is one of such algorithms and is used in e.g. glibc.
@lassipulkkinen273
@lassipulkkinen273 2 года назад
@@krzysztofdziembaa4982 I knew about those, but I don't think they are useful if the searched-for string is one character. While "${" is technically longer than that, the code *is* optimized to only look for "{" after it's found a "$", and "$" is not a character that's going to appear often in the input, apart from lookups of course. That said, the parsing could just be moved to an initialization stage if the "lookups in format parameter values" misfeature was removed, so... (maybe this is already being done; I don't actually know.)
@ThePC007
@ThePC007 2 года назад
You do it using a finite state machine. Granted, the substring is so short that it likely doesn't matter much anyway.
@einsjannis
@einsjannis 2 года назад
I really enjoyed your videos about log4j I really happy that some one added something new and I actually wad able to learn sth new
@MuhammadBinZafar1
@MuhammadBinZafar1 Год назад
I'm glad that you have 380+ videos. I never want to run out of your videos. I've been listening since 2018🎈. Always enjoyed every single moment with you. Each video is unique, knowledgeable, perfect 🎉. I wish the best for you!
@isitanemail
@isitanemail 2 года назад
I was waiting for something that could explain in depth the full vulnerability,log4j and jndi. These videos helped me a lot in understanding. I would request to release such content more and probably a little quicker to help clear these things. Some other explanation caused a lot of confusion
@ninjanape
@ninjanape 3 дня назад
thanks for these two videos - very informative, very well presented :) !
@lijnk
@lijnk 2 года назад
The main reason the library has all this indirection and events is so it's thread-safe, easy to write new appenders (not everything uses just files and stdout), and so it's unit testable (good dev practices mean the code should be tested). If they didn't have that, then all the log messages would be jumbled up in the same line, it would be impossible to add new appenders like logstash or slack, and whenever a new release is made, the maintainers wouldn't be able to guarantee the project functionally works. With that being said, some eyebrows should have been raised when lookups were performed in the log message itself.
@omri9325
@omri9325 2 года назад
You don't need to defend the bad choices that were made there, the code is still shit.
@ZintomV1
@ZintomV1 2 года назад
@@omri9325 lmao
@lijnk
@lijnk 2 года назад
@@omri9325 The overall structure of any decent logging library is to take log events and pass them to appenders that write them somewhere, which the library does. Of course there's bad code within it, the noLookups section proves this, but saying the entire thing is garbage is about as asinine as saying security is only there to hinder developers. If you believe the whole thing is shit, you're welcome to contribute cleanups as it's open source.
@omri9325
@omri9325 2 года назад
​@@lijnk "saying the entire thing is garbage is about as asinine as saying security is only there to hinder developers" there is no logical progression towards that statement. I'm not going to to touch any of this shitty code, I'll rather contribute to projects that are healthier and have a future. Let that shit die.
@TimLF
@TimLF 2 года назад
I agree log4j is pointless bloat. Spring (86% market share) and Tomcat (61% market share) are not using log4j, netty is using log4j.
@AFchump78
@AFchump78 2 года назад
“I have no clue about Java or maven with dependencies” i felt that in my soul. I went back to 3 deserialization issues after the log4j learning curves to reattempt that exploit after the Java and java development learning curve that log4j caused. Beautiful and tiring at the same time.
@vaisakh_km
@vaisakh_km 2 года назад
😂i trained a complete year in Java and I made many projects in my training period,. But after getting job I never touched it... Now when I tried to make a hlowld , I even forgot to put public static void main in class.... ....😑 All the hard work just vanished innu head... Now I wondering how I did build big spring projects that time...
@hblaub
@hblaub 2 года назад
Really nice Java library. I think we should load custom code per socket from somewhere, too. It's going to be totally safe and sane.
@supermonkeyqwerty
@supermonkeyqwerty 2 года назад
7:25 As a CTF'er by hobby and a developer by day job, I don't think this is a good idea from a library developer perspective in the first place. Whenever you provide 2+ different ways of doing the same thing, you're making code less consistent and harder to refactor in the future. Imagine that at some point in the future, you or your team decides to move off of environment variables and want to use a configuration file instead. You might think of searching for all usages of `System.getenv` in the project and replacing them, but that would leave this `${env:...}` logger config thing incorrectly untouched. Of course, it's only a cost, and that might be outweighed by a payoff. But I don't think that's the case for Log4j's feature, since the added convenience is tiny, developers might already be used to doing it the 2nd way as the standard, and it doesn't generalize. (What if you wanted to use the same string message in the logger and someplace else?) This happens much too often, because it's so easy to lose the forest for the trees. There've been times when I finally stepped back, and then realize that something was completely unnecessary.
@lal12
@lal12 2 года назад
I think people are kind of looking at this issue the wrong way. Yes I agree the log4j is bloated and jndi is a terrible idea. However at the end of the day this is just a classic example of injection, where the user input was passed into the format string instead of as an argument (to use printf terms here).
@supermonkeyqwerty
@supermonkeyqwerty 2 года назад
@@lal12 Honestly, I haven't look at Log4j too closely myself, but does it even have an analogue to printf's `%s`? From its recursive substitute shown off here, I'm not convinced that such an option wouldn't just have the same vulnerability as using the string directly. Either way, whether understanding the entirety of a library's API and possible configuration is the _responsibility_ of a developer or not, it's not something that currently happens or will change anytime soon. I've got no clue what we'll do to prevent something like this in the future.
@berndeckenfels
@berndeckenfels 2 года назад
7:35 I agree that env: lookup for the sake of easier logging is not a good security design, but I think the idea was using lookup in patterns or config declaratively. Looking up messages is just stupid,
@jamess1787
@jamess1787 2 года назад
1) Design for simplicity. 2) get it working 3) revisit project 6 months later realizing you forgot target #1. *Ends up with 1000's of lines for some basic function*
@timelessnesses
@timelessnesses 2 года назад
*f a c t*
@fro334bro
@fro334bro 2 года назад
Sadly, Java idioms and design patterns encourages this extremely bloated and insanely verbose code style. The unnecessary complexity is the prime suspect that caused this vulnerability to be hidden for so long.
@godmodeon666
@godmodeon666 2 года назад
Why is Java so incredibly disgusting. Not the language itself, but the general code style in the culture of the programmers. There is so much indirection and over-abstraction, it is disgusting. That is a library to log things. Why is it so grotesquely overcomplicated. It reminds me of that Fizz Buzz Enterprise Edition meme. It's so disgusting to look at Java code 99% of the time.
@ptechlead
@ptechlead 2 года назад
Hang on, let's not beat around the bush: Java itself is disgusting (Language and VMs), which may have been okay if its users were infinitely wise and result-driven, but they aren't, to say the least. Java is the king of verbosity to help its users always look busy and productive. Java advocates and forces the use of the ugliest programming style, OOP in its ugliest form. Sadly this is what many new programmers are indoctrinated with through and right after collogue, perpetuating this madness. The only arguments for Java would have been security and type safety, but this vulnerability, and the mindset behind the existence and usage of the libraries that enable it shows you that this ship has sailed and sunk a long time ago.
@amyshaw893
@amyshaw893 2 года назад
this thing about using less complex stuff for security reminds me of how i approach coding games. Recently I was working on something in a team, and I was like "ok, we need to play some sounds. we can use a simple sound manager and shove it through unity's inbuild sound system, done." But then this designer comes over and wants to use this huge complicated library that allows you to do mixing on the fly and spatial sound and allows the designer to make complex soundscapes without having to do any code and all this crap and I'm just like "...or we could just play some sounds, and you use audacity to make the sounds, and our git repo doesnt explode from all the new files, increasing clone and pull times"
@anacierdem
@anacierdem 2 года назад
Having the developer pass the contents instead of parsing various things is a much better approach even from a software development viewpoint here. It is inversion of control, which effectively reduces inner complexity.
@Yaxqb
@Yaxqb 2 года назад
This honestly made me fear Java more than Log4shell: inconsistent if-else statements, 1000 layers deep call stack. So much fluff!!! Java attracts people with bad taste. Architectural astronauts. Python for life
@TheNovakon
@TheNovakon 2 года назад
13:51 - THIS IS THE CORE OF THE PROBLEM! The whole format vulnerability is easy to understand but this is treachery!
@santi5655
@santi5655 2 года назад
7:40 totally agree, it's crazy how complex a logging library can be for no reason at all, simplicity is also good for keeping the code maintainable and easy to understand
@T0m1s
@T0m1s 2 года назад
It's a mindset. Java developers seem to want to split their code into as many classes as possible, and this behavior seems to persist even when they switch languages. OOP is cancer.
@john33john33
@john33john33 2 года назад
one thing i learnt from many security issues. Try NOT to write your own parser famous browsers, frameworks screwed up and i ain't outsmart those engineers
@EER0000
@EER0000 2 года назад
Great video, nice to see an actual dive into the code and not just more talking heads. I wish it was easy to keep the codebases clean and simple, but so far any project that I worked on with a team devolved in a mess of dependencies. The hardest part about keeping things simple, is to convince stakeholders that it's worth spending hours to implement (e.g.) centralized logging yourself when there's a library like this already available. They'd rather see me working on a shiny new button than on stuff that nobody sees in the backend.
@passerby4507
@passerby4507 2 года назад
But you can't just write everything in-house. How do you decide what gives?
@EER0000
@EER0000 2 года назад
@@passerby4507 when I was a kid I would be making everything myself using just notepad, because that was the way to flex as a dev. With time and experience you learn which kinds of things are worth doing yourself, and which ones are not. I would never write a pdf converter for example, but I have written a basic SOAP parsing library using standard xml functions.
@fabricio5p
@fabricio5p 2 года назад
Honestly this code feels like they intentionally wanted to go fancy with the architecture and end up with a classic freaking mess
@bluejimmy168
@bluejimmy168 2 года назад
At 13:15, he said keep format string static to fix the problem. What does he mean by that? If a string is static then we dont need user input? If we need user input then it is not static? If I ask a user for input and want to output it back to the user then the string not static anymore? Thanks.
@ruaidhridevery1458
@ruaidhridevery1458 2 года назад
Devs get so much convenience and utility from _eval everywhere_ that preaching the simplicity of being more static is a really hard sell unfortunately. For this style of all-things-to-everyone library, it is nearly impossible for the devs not to embed interpreters.
@31redorange08
@31redorange08 2 года назад
"in depth", continues to explain Java and IDE basics.
@rydmerlin
@rydmerlin 2 года назад
Can you elaborate on how you get to remote execution though?
@stanleycoffey
@stanleycoffey 2 года назад
maybe go watch the black hat talk
@jasontiscione1741
@jasontiscione1741 2 года назад
It happens through object deserialization which uses the remote class loader. The log4j programmers did not actually intend for object deserialization to take place, but it can be triggered. The log4j code creates an InitialContext and passes the JNDI name to lookup(), expecting a value that it will immediately cast to String to be logged. But inside lookup(), Java notices the crafted array with the serialized Evil object stream in the attacker's JNDI response and decides it can return an Evil object to log4j instead of a String, so it loads the Evil class and then proceeds to run the Evil static initializer. This crap was designed for the 90s Internet when Java meant applets.
@jackbendtsen8002
@jackbendtsen8002 2 года назад
Absolutely, simple code means all of the code that your program could run, not just the code you wrote. I feel like not enough people truly understand this. Thank you for your insights beyond the topic at hand.
@ZintomV1
@ZintomV1 2 года назад
2:19 - the reason why most Java applications are way slower than their C++ equivalent (I'd argue even C# equivalent)... Not because of the JIT, but because of needless object creation and abstraction, if you just need a simple string, leave it as such! No need to wrap a class around it!
@omri9325
@omri9325 2 года назад
My theory about that is that most of the java ecosystem was created at a time were design patterns where THE THING, and everyone jumped in adding patterns without even knowing when to add them, people were forced to add them just to not look idiots in front of their peers. When a peer adds something with many patterns/abstractions. you don't doubt that it's too much abstraction, it might be that you are "too stupid" to understand and you let it slide. Languages that evolved in modern times don't include all those AbstractFactoryManagerImpl shit, they add abstractions only when they are needed.
@-morrow
@-morrow 2 года назад
object creation is very cheap in java due to it's memory allocation strategies and is mostly faster than C++ new object creation. besides, for almost all java applications the kinds of speed improvements you get from using C++ instead of java or optimising object creation are dwarfed by the actual bottlenecks (round-trips, db queries, disk seeks, time complex algorithms, etc.)
@jhbonarius
@jhbonarius 2 года назад
@@-morrow you're comparing apples with oranges. Sure maybe the default "object creation" of Java is faster, but C++ is not an object oriented language like Java is. You have much more flexibility. And if you write a custom allocator and pre-allocate, C++ will likely be faster. But: you have to do everything yourself. It's a lower level language.
@jhbonarius
@jhbonarius 2 года назад
Their equivalent? What applications are you talking about? C++ and Java play different roles in the programming ecosystem. They each have their strengths and weaknesses. You wouldn't expect applications to be written twice in each of them, as there's no purpose to that. Instead you would expect larger applications to have parts written in either and some interop between them.
@omri9325
@omri9325 2 года назад
​@@-morrow Bottlenecks like the huge amount of extra memory needed by JVM applications. The classloading system in java is painfully slow on program start-times. The only thing java can do faster than C++ is on optimizing things it learns to predict from the runtime. C/C++ can technically optimize everything better, but with a lot more effort to hand craft them.
@danthe1st
@danthe1st 2 года назад
+1 for mentioning insecure deserialization of untrusted data.
@NewtonMD
@NewtonMD 2 года назад
Hey security researchers, you missed the *"rediculous"* example
@mskiptr
@mskiptr 2 года назад
Tbh, format strings really are an anti-pattern. They conflate two different functionalities and make it less obvious what should happen where. They can be made safe (vide printf in Idris) but in such case it's an absolutely pointless complexity. We should just stick to clear and unambiguous abstractions. If we want to log some string literal, we should be able to just do so right away (without any need for escaping or lookups). If we want to log a value of some variable it should work the exact same way. And if we want logs to be parametrized with the future environment, then we should either use lambdas (Environment -> String), or some specialized data structure and not a string-but-with-an-overloaded-meaning!
@tlouik
@tlouik 2 года назад
respect to everyone who watches this on christmas :O
@borisbo94
@borisbo94 2 года назад
7:40 this is actually how you SHOULD write software. From a software engineering perspective. This is the KISS (keep it simple stupid) principle. This library is over complicated for no reason… But take this aside… you should never parse strings to code.. same as you shouldn’t use exec/eval etc.
@lal12
@lal12 2 года назад
I mean it depends how you mean it, but quite often it is necessary.
@shemmo
@shemmo 2 года назад
8:40 thumb up for this
@Klatuu82
@Klatuu82 2 года назад
and another very good video. thank you for your work.
@marcoantonio7648
@marcoantonio7648 2 года назад
too much time to run Maven oh yeah, I felt that
@LawZist
@LawZist 2 года назад
Java is the most complex language ever! Why every code need to be so long and full of classes and functions and design patterns??
@aspuzling
@aspuzling 2 года назад
I have been coding Java for 15 years and I can tell you this complexity is not inherent to Java. It's possible to write complex code in any language. The problem is the people who have this mindset of "kitchen sink" libraries and frameworks tend to find Java a very productive language. This means that if you want to build a web application and you want basic logging functionality, then you have to choose between log4j and logback both of which have been around long enough that they provide every single logging feature you could possibly need even if most of those features are never needed by 90% of applications. This mindset is also what produced Spring which is an extremely popular but terribly designed framework. Having said this, it's very possible to write clean, non-complex code in Java that is secure. I work on a security focused product and this is what we have done. We have a very strict policy around using 3rd party dependencies. This not only helps us stay secure but massively simplifies our application and makes our lives as developers a lot easier.
@AdamFJH
@AdamFJH 2 года назад
Not all code needs to be long just variable names should be meaningfull and if they need to be long to be meaninful then so be it. Design patterns(when used correctly) makes code more scalable, more reusable, more readable and more maintainable.
@AdamFJH
@AdamFJH 2 года назад
@@aspuzling I've been a java programmer for over 15 years and have never needed to use log4j or logback. The native logger that comes with java works perfectly fine.
@aspuzling
@aspuzling 2 года назад
@@AdamFJH fair enough. We need some of the more advanced features of log4j but I would love to have more options of logging libraries, especially some that focus on performance and security. There's absolutely no reason we can't have that in Java especially as SLF4J is popular and makes it very easy to switch between logging libraries.
@Janos0206
@Janos0206 2 года назад
It's not really Java that's to blame, it's feature bloat and bad/uncoordinated programming
@desmond-hawkins
@desmond-hawkins 2 года назад
Regarding the question at 7:14 about using ${env:HOME} vs log("... {}", System.getenv("HOME")): there's more to it than this trivial use case. While the example given here is of course less risky and still just as easy to read, expressions are also expanded from other places where you're really writing config, not code. For example, when logging structured messages (often to Splunk or similar) you often want not just the log message but also the hostname, the process name, the environment, maybe the cluster and namespace if you use Kubernetes, etc. You can configure Log4j to include such values as named fields in your structured log events, with config like . You're not writing code here, but config: this goes in log4j2.xml. What's the alternative if we block all such expansions? You'd likely have to write your own Layout class and implement each field in code. You could also have your own (non-expanding) config file to map environment variables to event fields, but then (1) now it's a lot more code to write and (2) it's still not as flexible as Log4j since you can't do things like having a field named "cluster-namespace" with the value "${env:K8S_CLUSTER}-${env:K8S_NAMESPACE}". So yes, expression evaluation *is* useful in the sense that you can have advanced logging configuration without code, which covers a vast majority of use cases. Adding any kind of network call to this system is insane, but it is certainly possible for this feature to be flexible and useful without going overboard.
@TheNovakon
@TheNovakon 2 года назад
Why every somebody needs lookups in realtime? We are processing logs on different node - all lookups can stay unresolved and eventually resolved later during processing - because realtime processing slows down a lot
@desmond-hawkins
@desmond-hawkins 2 года назад
@@TheNovakon Being able to query logs in Splunk or Logstash a few seconds after an event happens is *essential,* and working on any system without this ability is much more difficult. What do you do if you have to wait a while for the batch logs to be delivered? What happens during an outage if you don't have access to logs to understand what's going on?
@siimk13
@siimk13 2 года назад
Not to mention that any code change requires a roll out/deploy to production environment whereas with log4j you could just change the log config file and have log4j reload it. Easy as pie.
@desmond-hawkins
@desmond-hawkins 2 года назад
@@siimk13 Good point, and changing code also means extra build time, in almost all cases. It's certainly needed for Java since you have to compile it, but these days even interpreted languages have a "build" time if only to create a docker image or any other kind of package.
@TheNovakon
@TheNovakon 2 года назад
Any example please!!!
@ltxr9973
@ltxr9973 2 года назад
Very good comment about hidden complexity. It's rampant in Java.
@voidedname
@voidedname 2 года назад
I'm a software engineer, and I hate most magic libraries. ORMs are my biggest gripes, log4j is another, spring boot is a huge issue... Magic is always bad, it exponentially increases the mental complexity, all the magic that isn't clear from the code has to be kept in mind. But sadly, in the java world at least, you're more or less forced into using them. There are ways to make the code prettier, I won't get into it. But I absolutely hate invisible side effects. If I want my code to cause side effects then I damn better actually tell it to do that side effect. The reason it's so popular is because it (wrongly) seems like you can write code faster and more efficiently. That is true when prototyping and in the initial phase of a project, but the hidden complexity quickly swallows it after just weeks where you spend an ungodly amount of time and mental effort to maintain and develop further features...
@brunoais
@brunoais 2 года назад
9:17: It may seem weird but I've been screaming about this kind of use of log4j since 2017, I think. However, I haven't seen any of your stuff until 2019. I didn't know log4j had jndi, btw. I stopped using it back in 2016/7, IIRC 12:51: This vulnerability with databases is very very prevalent! I never had such issue If I knew log4j had jndi, I would have known how dangerous the lib is much sooner. Thankfully, someone found it. Still, I wonder how many systems were attacked due to that.
@tunasalmon1243
@tunasalmon1243 2 года назад
The best gift for christmas for an aspiring developer. Thank you so much
@anttijokipii
@anttijokipii 2 года назад
Thanks for you content. It is really good. I have worked as programmer/architect/CEO on multiple decades, but have background from hacking. It is interesting that security and development is actually so separated.
@passerby4507
@passerby4507 2 года назад
Classifying log4j string substitution as syntax sugar isn't exactly fair. It allows for recursive lookups, e.g. have an environment variable store what's supposed to be looked up. Now that may or may not be what you want, but it's not the same thing.
@TheNovakon
@TheNovakon 2 года назад
Please any use-case to have this; ${env:WHATEVER} and put into env variable WHATEVER=${jndi:ldap:...}. ??? Why I need this? However even content of enviroment variable should not be trusted...
@roboknight
@roboknight 2 года назад
Unfortunately, you won't be able to use an XML file, as Log4j does, to enable configurable logging if they just use in-line environment variable look-ups. However, the real question is, do they really need this kind of flexibility in a logger? Maybe or maybe not. Maybe they could have parsed the file way before the library goes and does anything with it to help secure it. But it is difficult to get simpler when you want flexibility. Hard coding does help secure some things, but can also introduce other bugs (buffer over-flows come to mind), simpler or not.
@tehwinsam3522
@tehwinsam3522 2 года назад
Just want to wish everyone merry christmas !
@Dropje86
@Dropje86 2 года назад
Man, you have no idea how many arguments I’ve had with developers about levels of abstraction. The DRY principle has been taken way out of its original intent and people now just add layers of indirection for the sake of it. So often things can be kept much simpler by repeating yourself.
@FalcoGer
@FalcoGer 2 года назад
The principle of single responsibility. A logging library is supposed to log messages. It shouldn't format your string. If you need to format your string, then add a class for that or use the basic language features.
@alessandro.rossini
@alessandro.rossini 2 года назад
Freaking 2013 maan! It's wild!
@dummypg6129
@dummypg6129 2 года назад
When people make feature-rich apps ending up with tons of vulnerabilitu.
@caujka
@caujka 2 года назад
Lovely explanation! Absolutely marvellous! Thanks!
@mateowang6570
@mateowang6570 2 года назад
Very very interesting from a developer perspective. Thank you for this!
@krzysztoflewandowski8262
@krzysztoflewandowski8262 2 года назад
CVE-2017-5645 was kinda first on the same
@wieliewiel2630
@wieliewiel2630 2 года назад
That's alot of cycles for just printing a log message..
@TheMAZZTer
@TheMAZZTer 2 года назад
This huge bug is caused by a desire to have string interpolation in Java, which doesn't have it. The problem is string interpolation is done by the compiler, meaning runtime strings (especially user input) can't trigger interpolation. String.Format looks like Java coders' best bet, but again, keep the format string static! But you won't have issues with recursive format specifiers (I would hope)! Example of string interpolation in other languages: JavaScript: `This is a string ${expression + goes + here}` C#: $"This is a string {expression + goes + here}" Looks very similar to how Log4j does it, but in both cases having ${} or {} in any of the variables won't trigger a string interpolation, so it's safe.
@jasontiscione1741
@jasontiscione1741 2 года назад
The bug was 10% caused by string interpolation and 90% by Java's eagerness to whip out a remote class loader and start executing mysterious crap without being asked, which seemed like a good idea in the 90s.
@passerby4507
@passerby4507 2 года назад
@@jasontiscione1741 Funny thing, python pickle is the exact same.
@kawcco
@kawcco 2 года назад
@@passerby4507 I rarely see `pickle` in real-world code at all, and if it is it's usually for efficiently storing instances of Python's top-level data-types (strings, numbers, sequences, dicts) locally. Sending Java objects over the wire seems to be scarily common, however. I believe this is because Java's standard library lacks a convenient way to send data over the wire without touching XML. Us Pythonistas have `json` and a much easier to use XML lib, while Java users have *multiple*, painful XML libraries that must all be used together and no way to parse JSON without bringing yet another external dependency into the fold.
@amarmohmed1648
@amarmohmed1648 2 года назад
I have the same passion that you had when I was young, and more than that, I saw THE last video and I did not understand anything, so I saw your first video, which is the intro video Please, would you teach me the name of that passion?
@SimGunther
@SimGunther 2 года назад
12:20 Proof that he's a time traveler 😎
@ko-Daegu
@ko-Daegu 2 года назад
this is the most complicated tut on the internet about this.. thanks
@LiamDennehy
@LiamDennehy 2 года назад
@7:39 "Complexity is the enemy of security"
@benlu
@benlu 2 года назад
Lol Java, language of hidden complexity by default
@blizzy78
@blizzy78 2 года назад
What does hidden complexity have to do with Java? Your comment makes no sense.
@benlu
@benlu 2 года назад
@@blizzy78 one example is null, as a statically typed language all types can be null, you have to write twice as much code to handle all the possible nulls everywhere. Java has a history of these kinds of decisions
@LeandroCoutinho
@LeandroCoutinho 2 года назад
"I'm a prophet now!" kkk Great job!!!
@rastabong420
@rastabong420 2 года назад
@14:59 am I watching an old Godzilla film? 😁
@TheBiggreenpig
@TheBiggreenpig 2 года назад
7:35 Yeah, when I learned about the JNDI and environment variable possibilities of log4j, I was wondering why not simply let the programmer retrieve those and pass them as a string. Log4j definitely does more than it should. In no code we ever used any lookup, but we had them enabled unknowingly.
@Ostap1974
@Ostap1974 2 года назад
@13:45 -- was my first thinking as well... Why would anyone ever in any language write a text fromatiing function that has a formatting handler outside of the format string.
@deviousmethod1310
@deviousmethod1310 2 года назад
thank you for another amazing work!
@kallocainsynthemesc4172
@kallocainsynthemesc4172 2 года назад
I'm surprised that log4j is written so unclean. Never bothered to look deep into it.
@Torterra_ghahhyhiHd
@Torterra_ghahhyhiHd 2 года назад
8:37 i think developer like to introduce this kind of complexity for 2 main reasons 1 he want to be needed in the job he is hoping to add new capabilities more power to the program the program like the art of the artist have some subjectivity and is never finish always want to ad some extra features or hidden potential that only the creator can exploit more.
@berndeckenfels
@berndeckenfels 2 года назад
I remember the time when I was reviving the design concepts DJB used in qmail. One was a very careful logging concept. It was going in depth into timestamps (TAI logging has no problems with timezones and leap times) as well es escaping user provided data. It is just important that log messages can’t escape the log format (line feed and separator evasion). Once you are that thorough with design you would not 8ntroduce such lookups and expansion patterns, I always missed such a escaping system and structured handling of log message arguments in the typical java frameworks.
@mrkretschmer
@mrkretschmer 2 года назад
what if I replace the lookup function directly with return null ? =) fixed ?
@protiumx
@protiumx 2 года назад
Great video! I don't understand how companies do not audit their dependencies before adding them to their stacks. I hope it's also a lesson for the big companies that make use of open source libraries to start funding open source projects that add value to their products/business.
@blizzy78
@blizzy78 2 года назад
That's very easy to answer: It takes a lot of time - and therefore money - to audit something. Especially when you're not intimately familiar with the inner workings. That's time and money companies are not willing to spend because it doesn't directly produce earnings.
@jhbonarius
@jhbonarius 2 года назад
Blizzy1978 is completely on the point. Imagine you're a small software development company. In order to get a contract, you have a small margin. You have to deliver within a few months. There's no time to develop every part and framework yourself, let alone test and mature it. Also: doing everything yourself is risky, because you often don't have enough experience with everything. I.e. we don't reinvent the wheel and use libraries everybody is using: if everybody's using them, they're probably mature is the assumption. There's no time and money to audit anything usually. Money doesn't grow on trees and it's a competitive market.
@jhbonarius
@jhbonarius 2 года назад
The part about "keep it simple" is only half true, and misguiding IMHO. You should definitely use abstractions. Reinventing the wheel with elaborate low level object handling is not good: more code to maintain (as all code will rot), easy to make mistakes, as in the same mistakes over and over. And if a developers have to write the same code over and over, they become less interested and concentrated, and are more likely to slip up. Finally, it will likely increase the development time, which not everybody can afford. Especially if it barely adds value.
@travisjg80
@travisjg80 2 года назад
“Keep it simple” is probably the best advice to give when it comes to software development and is a basic software engineering principle. It doesn’t mean to strip out all the functionality to make people rewrite the same functions over and over; that’s the opposite intent due to what you outlined (developers writing the same functions repeatedly will introduce more errors). It means to keep your function concise, simple, and limit what they do (ie, “do one thing, and do it well”) including low-level object handling. Simple functions reduce errors can be used together to build up complexity that is needed for the outputs.
@jhbonarius
@jhbonarius 2 года назад
@@travisjg80 I totally agree, and I think it's the consensus of most (real) senior/experienced developers. However, "keep it simple" doesn't mean you should not use any abstractions, nor reinvent the wheel every time.
@T0m1s
@T0m1s 2 года назад
Each new abstraction has a cognitive cost to the reader and makes it more difficult to understand the system as a whole. You should of course "use" abstractions (as opposed to dumping the entire 1000 lines of code in the main function), but be aware that introducing new "non-standard" abstractions might hurt readability. For example, all developer know what a stack is, it's a safe abstraction to use that doesn't usually complicate the code. Whereas LoggerManagerFactoryCreator might make things a bit difficult to grok.
@jhbonarius
@jhbonarius 2 года назад
@@T0m1s not all developers need to know what a stack is (javascript...). And many managed languages don't allow you to specify where you store the data. Anyhow _every_ feature can be abused. It all comes down to writing good programs. And "good" is not only that it works, but also that it's maintainable testable(/tested), secure, etc. Overengineering is not good, but quick'n'dirty/hacks are its oppositely bad
@T0m1s
@T0m1s 2 года назад
​@@jhbonarius - if you don't know what a stack is, can you really call yourself a developer? Whatever. Replace "stack" with another well-known concept in your corner of the developer world and my point stands. Every novel abstraction that you create will make it slightly more difficult for others to understand the system, and you should only introduce it after serious consideration. Unfortunately, the mainstream developer culture doesn't frown upon developers who are very trigger-happy when it comes to introducing new abstractions, and you get things like log4j.
@LuminousWatcher
@LuminousWatcher 2 года назад
ru-vid.com/video/%D0%B2%D0%B8%D0%B4%D0%B5%D0%BE-iI9Dz3zN4d8.html or make the developer who needs the extra functionality load the modules instead of having it loaded and enabled as standard
@obsidianskin9502
@obsidianskin9502 2 года назад
good stuff
@C10udburst
@C10udburst 2 года назад
wouldn't it make more sense to make the lookups into a different library for example? why is this a part of a logger??
@altairbueno5637
@altairbueno5637 2 года назад
“It took me soo long to learn how to use maven with dependencies” Literally every java developer ever
@ekfliu
@ekfliu 2 года назад
at least it's not gradle.
@altairbueno5637
@altairbueno5637 2 года назад
@@ekfliu its Definetly not Cargo
@FUTUREPES
@FUTUREPES 2 года назад
Explanatory 💝
@nekuskus5218
@nekuskus5218 2 года назад
Thanks for the great explanations! Merry Christmas!
@danbondarenko7894
@danbondarenko7894 2 года назад
Thank you for the great explanation! I especially liked that you went step-by-step through the vulnerable code -- this helps me grasp what it might feel like to write vulnerable code. If you're looking for ideas of what to cover next, then I'd propose explaining what happens within JNDI lookups: when does remote code get executed? what would be a legitimate use case of this remote-code execution part of JNDI? Thanks again.
@icenberg5908
@icenberg5908 2 года назад
Amazing. Thank you.
@drakey6617
@drakey6617 2 года назад
10:47 in my opinion is not always correct. They first arguments can actually also be in registers and not on stack. Stack is used when the first registers are full. At least this is for ARM
@dzaima
@dzaima 2 года назад
"here's how it looks like with a simplified stack in memory"; 32-bit x86 passes everything on the stack, for example
@drakey6617
@drakey6617 2 года назад
@@dzaima Yeah, true. I suspected that this is true for x86; that is why I said "not always" and "for ARM"
@bigmistake5565
@bigmistake5565 2 года назад
What a mess
@code913.
@code913. 2 года назад
It's not about the code being a ridiculous example. It's actually about drive and power
@firetf
@firetf 2 года назад
While i agree with the secure design philosophy, one big reason to have a logger internal formatter is performance. You often have tons of log calls to log levels that are not printed, and then the whole lookup and string formatting can be omitted, while if you do it manually, you would first look up all the things and build the formatted string, just to throw away all that work if it's a log call to debug level but you're on error level.
@olafbuitelaar
@olafbuitelaar 2 года назад
I Also think there is another aspect in this. Which is configurability. Like the environment variable case. It might not be included in the source. But in some production instance its useful to log this information, it can simply be added to the config. Instead of adjusting the code.
@gubgubbubbub
@gubgubbubbub 2 года назад
Awesome, informative video; thank you!
@NareshKommuri
@NareshKommuri 2 года назад
Thank you for sharing, really interesting perspective. Awesome in-depth analysis in few minutes. Cheers!! 👏
@thesenuts4472
@thesenuts4472 2 года назад
As a hacker sorry developers no love it is what it is.
@AniltonNeto
@AniltonNeto 2 года назад
G.O.A.T very well explained :) LOF
@kasuha
@kasuha 2 года назад
That thing with the check for "nolookups" present in one branch and missing in the other displays serious problem with open source software: Neither the implementer nor the reviewer were familiar enough with the method to notice the problem. In many cases, people just don't have competences assigned and they just nudge the product at random places wherever they see it fit while missing in-depth knowledge of the part they're messing with. What's worse, there are already cases of actual vulnerabilities being intentionally pushed into open source projects disguised as fixes. Sometimes they're obvious but there are also really well prepared ones which take a while to be recognized and removed. And who knows how many are there that nobody but the author knows about.
Далее
The Circle of Unfixable Security Issues
22:13
Просмотров 114 тыс.
Log4J & JNDI Exploit: Why So Bad? - Computerphile
26:31
A Vulnerability to Hack The World - CVE-2023-4863
18:00
Generic HTML Sanitizer Bypass Investigation
14:05
Просмотров 141 тыс.
When you Accidentally Compromise every CPU on Earth
15:59