AvastSvc.exe contains a full, unsandboxed JavaScript/DOM implementation
github.com
github.com
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...
I think this makes it worse.
What reason is there to even have such an interpreter in a highly privileged process?
FFS, even display drivers don't run with full system privileges anymore.
Benchmarks. It's faster if you don't push all the scanned data through a process boundary.
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++)
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.
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...
Therefore when you see an exposed unsandboxed VM, you instantly know it's critical issue.
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?
I meant maintained by app developers who include the runtimes, not the runtimes themselves.
Significantly fewer than you'd find in a comparable C++ application, probably, and with much less effort put into securing things like "if I index into this array am I allowing for an arbitrary write primitive" and "can I safety use this object without giving an attacker code execution". Electron bugs tend to be of the sort like "oops, we can load a file from the filesystem because we forgot a string check", and C++ bugs are "that, but with the other things I just mentioned".
Based on what? On C++ you have complex systems with difficult code to get correctly. With Electron, you have terrible chat apps that take 1GB of memory to display a few chat bubbles that allow remote execution into machines running them.
The data to compare the two is just not there to assume anything like you just did. Meanwhile, electron apps have proven quite insecure, despite not being able to allow arbitrary write primitive by indexing into an array.
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.
Serious question, what are reasons to use JS in non-web contexts, apart from developer familiarity?
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.
Wait, hold on: you can usually run C on most devices.
With JS, you have to worry way less about hardware-specific builds, platform-specific linking implications, differing system behavior and intrinsics, or any of the other substantial hangups that become relevant when you need to distribute a native application across a wide range of devices.
We don't need to repeat the rest of the thread where everyone hops in and says "tut tut, hypothetically, it would be possible for it to not be that way". We're talking about the way things actually are. In an ideal world, JS would've been out of the picture about 3 years after it was born. :)
I never said that.
Some even find it fun to bend something that isn't meant to be bent.
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.
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 ;)
Even if you did all that, odds are that you still don't know C++.
Yeah this is part of the reason why I wont even try to learn the language
You can very well write something without really knowing it. In fact it's more than obvious that the majority of code written these days falls under that category.
Programming is hard and it takes years if not decades to "know" how to do it to an extent that's not harmful. This also applies to learning the tools. Some tools are easier to learn than others. C++ is notoriously difficult to learn.
JavaScript isn't free of this at all, it's also a very complex syntax, due to many years of lumping more and more features without any coherent design. The tooling around JavaScript is notoriously bad and broken. Having to rely on package for basic stdlib functionality, having to understand how nested dependencies can and will collide, etc.—all of that creates much higher cognitive load than having to use C Lion or Visual Studio (not Code) for C++ development.
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.
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.
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."
Avast is (was) running untrusted code in their system, by design. If your intention is to say that they shouldn't run untrusted code, then just say that. Don't waste time talking about whether memory safety matters for untrusted code -- just avoid untrusted code.
A lean C++ solution to the design problem of "how do we run untrusted code" is no better than an interpreted solution. You're focusing on the implementation, not the core design, and it is the core design that's flawed.
The only result of bringing JS up in a conversation like this is going to be to make people doing equally unsafe things in/with other languages feel better about themselves.
No interpreter code should be running there, C, C++ or JS. What I am saying is that this design is made by or for people who are seeking to run JS as part of the business logic, which is ridiculous. I haven't brought up "memory safety" at all. Perhaps read the thread before commenting?
You can, of course, safely use JS for business logic without executing code from unsafe sources, in the same way that you can safely use C#, LUA, Lisp, or any other language. But that aside, your criticism is completely irrelevant to the actual security flaw.
I don't see any indication Avast was trying to use JS for business logic in the first place. I'm sure they over-embed crap for other parts of their interface, but that's not what's happening here. Avast was not loading a custom interpreter to execute their own business logic, they were loading a custom interpreter to analyze user files as part of their virus scan.
> That service loads the low level antivirus engine, and analyzes untrusted data received from sources like the filesystem minifilter or intercepted network traffic.
> Despite being highly privileged and processing untrusted input by design, it is unsandboxed and has poor mitigation coverage.
It wasn't Avast's reliance on JS as a development tool that caused them to say, "maybe we should parse and run arbitrary files on the filesystem in a process with elevated permissions."
It's their business logic that's the problem. Avast's business logic is, "we want to execute untrusted source code to see if it contains viruses." It wasn't a JS engineer saying, "I can't do my job in C++". It was a C/C++ engineer saying, "I know how I can tell if this file is dangerous -- I'll run it in the main process to see what it does."
If you can tell me a safe way to accomplish that business logic in C/C++ or in any other language without process isolation or sandboxing, then I'll concede the point. But I'm pretty sure you can't.
As an aside, an interesting followup to this disclosure would be if someone tested whether or not Avast is also interpreting other languages like LUA that they regard as potentially dangerous. I wouldn't necessarily take it as a given that JS was the only language they were doing this with.
Nope, you've fundamentally misunderstood the issue at hand. The JS is not Avast's business logic. Rather, the program is attempting to analyze and detect malware in JS that the user encounters, similar to how an AV engine might inspect Microsoft Office files for malware. "Low-effort JS developers" had nothing to do with this. "C/C++ engineers" (and/or those above them) made this decision.
Or maybe stop trying to "gotcha" other commenters by making assumptions about what they were trying to say.
> but the scale of a JS interpreter + the fact that it's meant for executing arbitrary code
"the fact that it's meant for executing arbitrary code" is the only part of that statement you need. Avoid executing arbitrary code in unsandboxed/unisolated environments, even in a normal C++ app, even if the code is compiled. The scale doesn't matter.
If you're following best practices and isolating the process, then the number of lines of code shouldn't matter for the actual security. You should assume that a custom-built interpreter designed to run malicious code always has bugs -- whether it's running JS, LUA, whatever -- so you should run that code in a separate, sandboxed process that doesn't have system access.
It's not that the scale doesn't make a difference in complexity, it's that (for the most part) if you find yourself at the point where you're asking questions about the scale, you have already seriously messed up, and you need to go back and rethink your design.
----
The business problem Avast was trying to solve was, "how do we tell whether or not a random Javascript file contains malware?" The answer they came up with was, "we'll run the file in a process with system-access and see what happens."
I'll ask the same question I asked the original commentor: what is a safe way to solve that business problem without process isolation? And if you are correctly isolating the untrusted code, then why does the complexity of the JS interpreter matter?
The JS interpreter isn't there to lay out an interface, it's there to help them understand untrusted code that they find on the filesystem.
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)
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.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.
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...
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.
> 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.
AvastSvc.exe is not the place where you need programming 'at scale'.
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.
Even worse, sometimes the requirements go even farther and require the AV software to be third-party - OS built-in solutions don't count.
At this point, the only safe solution is running proper whitelisting to make sure that only authorized binaries get to run and to keep those binaries up-to-date and, if possible, sanboxed.
If you have such a setup and then you have to install AV like this because of security-theatre, you're making your security much, much worse (because in order to run AV, you have to whitelist it and because AV is apparently written to quality standards that allow running arbitrary user-supplied JS as SYSTEM)
Not so much. I'm required to run AV software on production Linux systems. All it does is write opinions to a log.
Insofar as the only reason we run it is checkbox-compliance, I'm fine with it being useless - certainly not asking for some kernel module or something that could actually block access. But I do find it funny.
A program specifically designed to detect many forms of malware and prevent them from infecting computers, as well as cleaning computers that have already been infected.
A program that monitors a computer or network to identify all major types of malware and prevent or contain malware incidents.
That's not a thing.
I recently updated my Windows app. VirusTotal showed 14 AV products detected my program as malware, when it clearly wasn't. I tried to report the false positives, but the vendors had terrible and inconsistent ways to do this (or even none for some). Even Microsoft's website didn't work when I tried to upload the program ("upload failed - please try again later").
I searched on the internet, and at least I found a workaround which was to recompile a library I used. This fortunately reduced the false positives down to a few products I hadn't heard of.
At this point, it's very hard to trust AV products with anything.
Observations:
- I am not sure this is 'full' javascript engine. I am thinking more inline with static-eval [0]
Example 1: Date.now() returns 'Exception: undefined'
Example 2: console.log([1, 2, 3].map(function(x) { return x; })) returns 'Exception: function(x) { return x; }'
- I couldn't manage to access DOM document.write("<h1 id='x'>html</h1><script>console.log(document.getElementById('x'));</script>");
returns empty
- After reversing DLL little bit, seems like it is used as unpacker ( also it has VBA support )
Still can be some vulnerabilities, but saying running full Javascript/DOM implementation is 100% wrong
I think it's only became like that after the built-in malware detection of Windows 10 became good enough so the antivirus ventors started adding "features" to make themselves stand out and look good on Enterprise comparison charts.
Thinking back on the Windows XP days... You'd be in actual danger if you didn't use one.
[1] https://arstechnica.com/information-technology/2017/05/windo...
https://cve.mitre.org/cgi-bin/cvekey.cgi?keyword=Eset
But from way back it's been RCE prone: https://support.eset.com/en/news325-eset-customer-advisory-v...
Agree that 90% of CVE's are meaningless but unless they've done a lot of sandboxing work in the meantime (guessing not, and up to them to show that) it's hard to trust.
Given the CVEs published, do you feel confident that if the product were robustly fuzzed / reversed+ tomorrow that there wouldn't be low hanging RCE? How safe do you feel running Windows with that product versus without? Personally I trust Microsoft's engineering / SDLC more than ESETs, maybe just me.
Symantec broke Chrome on multiple machines for me.
>The Google researchers found that MsMpEngine contains a component called NScript that analyses any filesystem or network activity that looks like JavaScript. NScript isn't sandboxed and runs at a very high privilege level, and it's used to evaluate untrusted code by default on almost every modern Windows system
Every antivirus is bad.
[1] https://arstechnica.com/information-technology/2017/05/windo...
https://twitter.com/avast_antivirus/status/12376853435807539...
It contains a link to Avast's Coordinated Vuln Disclosure site: https://www.avast.com/coordinated-vulnerability-disclosure and this has a link to Avast PGP key that's served via unencrypted HTTP: http://virfile.avast.com/viruslab/avast-bugs-pgp-key.txt Not only that, the key is a weak 1024 bit DSA key :(
1) https://mobile.twitter.com/buherator/status/1237115773409206...
2) https://www.virustotal.com/gui/file/d0e7e0e0287cd5a6ee36c745...
Through instead of sloppy I would say it's often more on the line of misguided about what is secure and _overconfident_ about their own skill to write code without security vulnerabilities. And if the are no vulnerabilities no sandboxing is needed right (sarcasm).
Through there where and hopefully still are exceptions to this. But don't ask me which ones because I haven't been on Windows for a long time.
Do you have any proof for that or you just like bullshtting people so you appear knowledgable?
You know what, I don't even care if this is made up, it's a great story anyway. It would be a great plot for a movie.
Ivan Vladimirovich is a Soviet computer hacker who creates computer viruses on behalf of AntivirusCorp. One day, he gets a mission that will come to change his life forever...
Another thing to think about is that tons of features that were never added before, are in the products now. Basically being pushed by management because more features = more sales, even if it ends up bloating the product. I remember a few years ago when we were acquired and had to switch AV vendors to McAfee, it made our oldest group of hardware basically unusable (and these were basically kiosk-type machines). The application we were using required IE so we couldn't replace them with Linux machines either.
Have you seen cable TV in the past five years? It's gone so downhill. Half of the content is still in 480p, awkwardly stretched to wide-screen. Commercial breaks seem like they're twice as frequent as they used to be. Shows being aired have drifted even further into reruns-and-reality-TV territory. Even the content of the ads has shifted somewhat, from recognizable brands to injury attorneys who look like they filmed the ad themselves.
You can see the money being drained from the husk of an industry, and you can see the increased desperation as they try to scrape together what money they still can. The same thing is happening with antivirus software.
However as the README says, this is a custom built implementation, built by a company who believes running a JS engine with SYSTEM privileges is a good idea. This means that there are probably exploits available and those do get full access to the system as the highest privileged user.
"In almost 10 years, Sciter UI engine has become the secret weapon of success for some of the most prominent antivirus products on the market: Norton Antivirus and Internet Security, Comodo Internet Security, ESET Antivirus, BitDefender Antivirus, and others. The use of HTML/CSS has allowed their UI to stay in touch with modern GUI trends throughout all these years, and will continue to well into the future.
Sciter Engine is a single, compact DLL of 5+ Mb in size. Application using it are 10+ times smaller than the ones built with Electron or Qt. And size of the distribution matters, one of main Sciter’s customers discovered “golden 40 seconds” rule: for the user, to buy a product, it should not take more than 40 seconds from the click on “download” button to the UI to appear on screen."
---
As mentioned by others, this would be separate from the JavaScript VM mentioned in the OP and would not run as a privileged account (it would just be the UI people interact with).
egui.exe is responsible of the UI interacting with the user and seems to not be running at all if the user never brings up the UI.
Considering the memory usage of the UI (~25 MB), looks like they choose to run a very lightweight UI (tray icon only) with eguiProxy.exe (2 MB) then start egui.exe if the user brings up the UI.
To be noted: the memory usage of the UI is almost the same as ekrn.exe which I suppose is the AV engine (1)
[1] I don't run the full suite and some features have been disabled (SSL MITM, web inspection and email inspection)
Is this another case of a metric becoming a target and thus no longer useful as a metric? The quality of software should be how well it performs its intended purpose, not by the conversion rate of the user funnel.
Seems the original thread is a javascript interpreter for sandboxing and analysing JavaScript in-engine.
UI process doesn't run as system either since there is no gui on that space. you'll find the sciter code in the user processes (tray and app).
Have at it
It lets you call Windows DLL functions from Linux!
https://wiki.winehq.org/Winelib_User%27s_Guide
I've done this myself to exercise a COM DLL from Linux. I had to use Microsofts "OLE/COM Object Viewer" to extract the IDL from the DLL and then compile everything with MIDL and wine-g++, but it worked.
I fail to see how this is a problema and I've been programming with javascript for 8 years...
It can do everything that the user could do, and the user in this case is SYSTEM. I understand SYSTEM can do everything.
It could install a keylogger, for instance.
Hence the existence of a number of Windows tools to get TrustedInstaller privileges, some examples listed in this thread:
https://msfn.org/board/topic/181190-how-to-overwrite-dll-fil...
Writing your own JS engine and then running it as SYSTEM is terrible engineering and very dangerous. There is no reason for why they have to run it as SYSTEM.
Lastly have we confirmed there's no memory or thread protection in place? Most AV reputable AV companies have strong proprietary sandbox code (especially in the scan engine process) which is on par with virtualization in terms of isolation.
Now imagine a company's internal JS implementation without all that engineering effort... vulnerabilities will become apparent immediately
This is like putting a 2 meter wide thermal exhaust port on your death star. On the off chance someone manages to hit it, game over. This process runs untrusted code so if you can get a file opened on the target computer, or even just get the user to go to a malicious website, you can try to attack this. Once you get some payload running yeah you could use bog standard crimeware to sniff out any credit card details entered, export your saved passwords from your web browser, look for any wallet.dat equivalents and run a keylogger waiting for you to decrypt it, drop some ransomware on the system, etc. This gives full control over the system if you find an exploit to it.
But yeah, this isn't immediately a vulnerability, just a poor design decision and a very juicy target.
Except it's probably more like the second Death Star because it's unfinished and there's a gaping hole in the side of it that you can just fly in.
https://bugs.chromium.org/p/project-zero/issues/detail?id=70...
https://docs.microsoft.com/en-us/powershell/module/microsoft...
Edit: sorry swipey keyboard messed up some words.