Preferences

I don't expect much from anti-malware companies, but this is one of those moments that made me absolutely dumbfounded that someone actually thought embedding an entire un-sandboxed JS engine with SYSTEM privileges was in any way a good idea. I actually had to get out of bed, open IDA, and start a Windows VM just to check that this wasn't some sort of elaborate hoax!

This isn't some MIDI parser logic, it's an entire JS interpreter that can parse DOM elements! How in Earth did this even get pushed out to a release? Did we learn nothing since the last time [1]?

1: https://bugs.chromium.org/p/project-zero/issues/detail?id=12...


Because low-effort JS developers are now everywhere. Just as JS should not be found in the server yet is now prevalent, JS is now finding its way into other places where it shouldn't be. You can't have an entire industry push this terrible ecosystem, then expect security companies to miss out on the fun. Locating and hiring C++ engineers at a scale is something that has become very, very difficult.
That is a really bad take.

Executing code written in any language -- dynamic, static, compiled, interpreted -- would be problematic here.

> That service loads the low level antivirus engine, and analyzes untrusted data received from sources like the filesystem minifilter or intercepted network traffic.

Forget JS. Do not load or execute code from untrusted sources in an unsandboxed environment with system permissions. This is about capabilities, not syntax. If your main takeaway is, "they should have used a C interpreter instead", then you have entirely missed the point.

I agree with you that no interpreter should be running there. It’s bad design.

But how many C/C++ engineers would think to design a system that runs a min interpreted code, vs JS ones? The take isn’t as bad as you think.

> But how many C/C++ engineers would think to design a system that runs a min interpreted code

Multiple people, in this very thread, including you[0]. And apparently at least one Avast engineer and their upper management.

I'll requote/paraphrase another commenter[1] down-thread: it wasn't JS devs who wrote a custom interpreter inside a privileged C/C++ program. It was a C/C++ developer who thought, "I can handle this."

It's very important when calling out security failings to point out the real failing. If people are reading this and trying to take away security advice, I don't want their takeaway to be, "so my custom LUA interpreter is fine."

[0]: https://www.hackerneue.com/item?id=22545385

[1]: https://www.hackerneue.com/item?id=22545945

Re-read the comment. GP is not saying to make an interpreter for C++, they are saying that there should be no interpreter. If the language is compiled there's no need for one. C++ can obviously be insecure, but the scale of a JS interpreter + the fact that it's meant for executing arbitrary code leads to a huge security flaw that isn't present in just a normal C++ app.
Where did I talk about having interpreted code?
I was testing a pre-release version of one of our products at work, and it was causing (inadvertently) massive slowdowns periodically due to a naive approach to scanning a system for installed applications.

So, I did what any sane devops engineer would do; I throttled the CPU use limit for its cgroup in the systemd service file. Now no more scans.

Except now the UI wouldn't load. Couldn't figure out why. Just an empty white window. Turns out, it's running a node.js server and the whole UI is rendered in HTML/CSS/JS, but because of that it was so non-performant that the UI would effectively not render at all if it couldn't slam your CPU.

I can't think of any native-code, native-widget, control-panel-type UI that would completely fail to render the entire window at all if limited to 10% CPU time, but hey, here we are.

> it was causing (inadvertently) massive slowdowns periodically due to a naive approach to scanning a system for installed applications.

> Turns out, it's running a node.js server and the whole UI is rendered in HTML/CSS/JS, but because of that it was so non-performant that the UI would effectively not render at all if it couldn't slam your CPU.

So was it the naive approach to system scanning, or the web-based UI that was the problem? Because there are some performant desktop applications using web rendering, like VS Code. Though I'm not sure how VSCode would behave if limited to 10% of CPU, because that's kind of a weird scenario.

> But how many C/C++ engineers would think to design a system that runs a min interpreted code,

This is essentially how antivirus software works. Every one of them packages an emulator to execute malicious binaries.

I'd say the number one thing stopping C++ devs from running eval'd C++ code is the lack of a std eval, and that's probably it.

Antivirus software normally matches code patterns to well-known pattern database. It does not investigate the code on the client machine. AV software houses run their own labs, where emulation is used to inspect suspected malicious code.
To my knowledge every single major AV packages a local emulator. We have long, long moved beyond a world where AV does basic pattern matching.

Frankly, I am far less concerned with the js interpreter than I am the rest of the codebase.

http://computervirus.uw.hu/ch11lev1sec4.html

https://www.blackhat.com/presentations/bh-europe-08/Feng-Xue...

http://joxeankoret.com/download/breaking_av_software_44con.p...

Given the prevalence of undefined behaviour, a C/C++ system should be assumed to contain arbitrary code execution vulnerabilities until proven otherwise. So in practice most C/C++ programs that process data can interpret code, even if they weren't intended to.
I don't know why people freak out so much about undefined behavior - yes it's not defined in the language standard and that's quite unfortunate, but it becomes defined as soon as you chose a compiler. And, careful work (and avoiding really hacky things) can let you easily write a C++ program that dodges undefined behavior if you're uncertain how stable your build chain is.

To be honest though, in the modern world, picking a stable compiler like GCC is a good enough choice for life - this isn't the 90s where you might have to dumpster dive to find copies of that specific borland compiler your company decided to tailor their code to.

(edit: All the above holds until you start making assumptions about uninitialized memory, at that point you're really in trouble and, honestly, C++ really should be better about preventing you from using dirty memory)

The behaviour of GCC is by no means clearly defined. Even taking it as given that any memory handling errors will result in arbitrary code execution (accessing uninitialised memory as you say, but also e.g. double free), there are other cases. GCC has been known to compile the addition of two integers into an arbitrary code execution. It has been known to compile code like:

    void doDangerousStuffIfAuthorized(AUTHORIZATION* authorizationPtr){
      AUTHORIZATION authorization = *authorizationPtr
      if(authorizationPtr == null || !isValid(authorization)) return;
      doDangerousStuff();
    }
into something that executes doDangerousStuff() when passed null. When users complain about such things, the answer is that the code was causing undefined behaviour and so what GCC is doing is correct according to the standard.
As much as I am tired of the crappy code produced by some JS developers this time they are innocent. If you had read the article you would have known that the JS code executed here is JS found on the Interent, not any JS written by Avast. The bugs are in Avast's C++ code (or possibly C).
The bugs aren't in the code, and this whole subthread begun from what LeoNatan25 wrote is a tangent. The bugs are in the design, of downloading programs from random untrusted anybodies on the World Wide Web and running them, indeed of downloading programs from random untrusted anybodies on the World Wide Web and running them with elevated privileges. In order to test whether they are malicious, no less.
> If you had read the article you would have known that the JS code executed here is JS found on the Interent, not any JS written by Avast.

I think this makes it worse.

Yes, but it also means that this is not implemented because of "low-effort JS developers".
I have read it. It's not clear what code runs inside the interpreter.

What reason is there to even have such an interpreter in a highly privileged process?

>What reason

Benchmarks. It's faster if you don't push all the scanned data through a process boundary.

If the interpreter was running code written by Avast then it wouldn't be a security issue. Having an interpreter running code you have written vs writing the code in C++ is not necessarily better or worse from a security point of view.
Highly disagree here. Javascript's DOM parsing functionality has but one purpose: presentation manipulation, i.e. rendering. Having something like that running as SYSTEM is a security issue in itself, regardless of where the code comes from.

FFS, even display drivers don't run with full system privileges anymore.

JS has no DOM API, browsers provide JS an API to use. Plus DOM had nothing to do with rendering, it's just tree manipulation APIs.
Generally the interpreter is probably better, once you have enough memory-managed code that it outweighs the number of vulnerabilities in your native code by virtue of its significantly lower bug rate.
I'd expect server-side JS code running on popular VM (v8, spidermonkey) to be safer than custom C++ (sandboxed vs running on the bare os).

And BTW, this is why WebAssembly runtime on the server is a big deal. Being able to painlessly run any untrusted code from "nonsafe language" in a sandboxed environment.

Also, if you read it correctly, Avast is running "wild" Javascript in a custom privileged VM (potentially written in C++)

Your expectation makes no sense. Popular JS VMs have huge attack surfaces, and are prime candidates for gray and black market vulnerability hunts. They are often not maintained, thus once a vulnerability is discovered, the entire app is compromised. In the case of a highly-privileged process, this can be catastrophic.

Contrast this with tailor-made, slim and well tested C++ code. And yes, I do expect security companies to have well-written and well-tested code.

> And yes, I do expect security companies to have well-written and well-tested code.

Your expectation makes no sense, given the vulnerabilities we've seen in AV software in the past decade.

If they insist that executing suspect JS is a good idea, they a) probably should use an established interpreter unless there's good reasons not to and b) not run it privileged.

EDIT: Avast appears to have deactivated this now: https://twitter.com/avast_antivirus/status/12376853435807539...

> Popular JS VMs have huge attack surfaces

No, not really? Depending on the browser they have generally have a small-to-medium attack surface. Yes, they can JIT, but often they can't do much else.

> and are prime candidates for gray and black market vulnerability hunts

Because they are remotely exploitable, nothing more.

> They are often not maintained

The world's deepest pockets and countless hours from the world's smartest minds go into maintaining them…

> once a vulnerability is discovered, the entire app is compromised

Not in modern browsers.

> In the case of a highly-privileged process

Oh good, so not the JavaScript process, right?

How many vulnerabilities have existed in Electron apps, sandboxing and all?

I meant maintained by app developers who include the runtimes, not the runtimes themselves.

> Popular JS VMs...are often not maintained

The V8 engine, in 2020, is one of the most actively-maintained software projects of any kind. And (for better or worse) nearly everyone who needs a JS engine uses that one. This includes - among others - Chrome, NodeJS (which means Electron too), and now Edge. The only major outliers I can think of are JavaScriptCore (iOS/Safari) and SpiderMonkey (Firefox).

The sin committed by Avast was rolling their own version of something, as a less-than-massive-company, when the state-of-the-art implementation is OSS. That has nothing to do with JavaScript the language. You're commenting on things you clearly know nothing about.

Id say it makes a lot of sense. You're comparing a memory unsafe language with a safe one.
The runtimes are also written in “memory unsafe languages” (C++). The runtimes bring a whole lot more code than if you wrote own tailor made code, meant to do something specific, in “memory unsafe languages”.
Can I invoke my @pcwalton card here? :-)
Love when the C++ dev enters the debate and claims with a straight face that security vulnerabilities is problem in other languages.
It's not about C++, it's about selecting a more appropriate tool that JS. JS is often used only because the developer knows nothing else. What's even more ridiculous, often JS is not even the easiest route.

Serious question, what are reasons to use JS in non-web contexts, apart from developer familiarity?

It doesn't matter if it was a Delphi interpreter. Having an unsandboxed interpreter running unsigned code was a stupid move. That some C++ developer thought it wise to do this is perhaps part of the issue.

V8 on the server has a very nice eventloop that's very easy to leverage for high performance while avoiding horrifying overflow issues and fits well for a large majority of web request/response patterns while still offering significant developer speed.

To be fair, this is the case in just about everything. If you know one language or tool, most will use that tool to do what they need instead of learning something else that might or might not be used ever again.

Some even find it fun to bend something that isn't meant to be bent.

It's the only kind of JIT'd code you're allowed to run on iOS without going through Apple's approval process. Pebble apps use JS for any code they need to run on the phone (as opposed to the watch) for this reason.
(Technically there's also WebAssembly as of recently, but it's part of JavaScriptCore so this is somewhat pedantic.)
> @paraboul is on point: JS is often used only because the developer knows nothing else.

I never said that.

Apologies, I misinterpreted. Redacted
JavaScript is one of the fastest scripting languages, for one. It often has pretty decent bindings to native code as well.
JavaScript is the only thing that you can really run on any semi-modern device. TVs, phones, laptops, desktops, servers, the only thing you can expect to execute on all of them is JavaScript. If you write your core libraries in JavaScript, you'll have that much less to worry about re-implementing and maintaining in something else. You'll have flexibility to potentially execute the same code on either client or server, phone or desktop. There are situations where that's pretty useful.

More than that, at least last time I checked, V8 is really fast. It is many times faster than the usable Python implementations, or practically any other memory-managed runtime. Only luajit seemed to sit in the same ballpark when I pulled up the shoot-out a couple years back.

I personally hate all of these facts, but sometimes, they really do mean that prioritizing JavaScript, or at least something that compiles down to JavaScript, is the best choice.

> JavaScript is the only thing that you can really run on any semi-modern device.

Wait, hold on: you can usually run C on most devices.

This is more like a lazy or deeply ignorant use of running a process as root and reflects on the recklessness of the system designer, and not on whatever that process happens to be.
> Because low-effort JS developers are now everywhere.

I take it you're not a big fan of JS? That's a lot like saying your not a fan of hammers. Maybe you aren't good at using them, maybe the noise scares you; maybe you think hammer wielders are all idiots and the only smart people are shovelers. It's a tool, it works better in some situation, worse in other.

Low effort <insert language here> developers are everywhere. Lol. Please just stop. Any language is a bad language if used poorly. Literally, JS is just as bad as C++ in the hands of the incompetent.

I don't think JS devs are the ones embedding JS interpreters into binaries.
Ever heard of Electron?
> Locating and hiring C++ engineers at a scale is something that has become very, very difficult.

AvastSvc.exe is not the place where you need programming 'at scale'.

The problem here is actually that the scanning engine is running as SYSTEM in the first place. Whether having a JS engine/emulator in there is a separate matter. As usual, "endpoint security software" is very poorly engineered. Keep in mind that this is a common pattern among vendors; though some are even worse (e.g. Symantec used to do this directly in kernel space).
I actually agree with your conclusions, however, if they had dropped privileges before running javascript it would be worlds and worlds better. Whoever bootstrapped the C parts should have known this.
In this case, the interpreter is included for analysis of JS code and was seemingly custom made for that purpose, not to leverage JS developers, so your point doesn't apply here specifically.
Part of it is that C++ is poorly taught in most universities. Even if you do get an education in C++, try using any of the modern features like smart pointers on your homework. Your teacher most likely will give you a poor grade.
> Just as JS should not be found in the server

Said who?

> You can't have an entire industry push this terrible ecosystem, then expect security companies to miss out on the fun.

I would expect most security experts to push you to use JavaScript instead of C++, since the former will protect you from a number of rather common security issues in the latter…

> Locating and hiring C++ engineers at a scale is something that has become very, very difficult.

Is it really that hard? Here, I can help: I know C++, and I'll be graduating soon. Hire me ;)

If you haven't spent substantial amounts of time (personal estimate > 10 years) working with C++ writing production code , you certainly don't know C++.

Even if you did all that, odds are that you still don't know C++.

Ok, so I lied, I don't really know C++ because nobody really knows everything about C++. But I have written production C++ code (some of which is used by most of the people here, including you…) so ¯\_(ツ)_/¯. Anyways, this is veering off-topic, so if you or someone else would like to discuss your hiring woes and/or would like to test whether I really know C++ my email's in my profile; I'd be happy to talk to you there.
> If you haven't spent substantial amounts of time (personal estimate > 10 years) working with C++ writing production code , you certainly don't know C++.

Yeah this is part of the reason why I wont even try to learn the language

Don't let them scare you away from learning it; you can absolutely write C++ to a useful capacity in much less time than that.
Ah yes, the "No True C++ Developer" argument
That’s scaremongering. You may not know all of the syntax, but you can certainly write proper C++ code.
Avast was founded in 1988. Now imagine what its codebase looks like.
Be sure to keep on complaining about Apple not allowing interpreters on iOS though
was it intentional that the bug you linked to is assigned and owned by this same dude?
Tavis Ormandy has been dismantling AV software, one after another, for some time now.
Psst…there's a Linux harness to load the DLL.

This item has no comments currently.

Keyboard Shortcuts

Story Lists

j
Next story
k
Previous story
Shift+j
Last story
Shift+k
First story
o Enter
Go to story URL
c
Go to comments
u
Go to author

Navigation

Shift+t
Go to top stories
Shift+n
Go to new stories
Shift+b
Go to best stories
Shift+a
Go to Ask HN
Shift+s
Go to Show HN

Miscellaneous

?
Show this modal