内容简介:My tour through vulnerabilities in antivirus applications continues with Bitdefender. One thing shouldn’t go unmentioned: security-wise Bitdefender Antivirus is one of the best antivirus products I’ve seen so far, at least in the areas that I looked at. Th
My tour through vulnerabilities in antivirus applications continues with Bitdefender. One thing shouldn’t go unmentioned: security-wise Bitdefender Antivirus is one of the best antivirus products I’ve seen so far, at least in the areas that I looked at. The browser extensions minimize attack surface, the crypto is sane and the Safepay web browser is only suggested for online banking where its use really makes sense. Also very unusual: despitejQuery being used occasionally, the developers are aware of Cross-Site Scripting vulnerabilities and I only found one non-exploitable issue. And did I mention that reporting a vulnerability to them was a straightforward process, with immediate feedback and without any terms to be signed up front? So clearly security isn’t an afterthought which is sadly different for way too many competing products.
But they aren’t perfect of course, or I wouldn’t be writing this post. I found a combination of seemingly small weaknesses, each of them already familiar from other antivirus products. When used together, the effect was devastating: any website could execute arbitrary code on user’s system, with the privileges of the current user ( CVE-2020-8102 ). Without any user interaction whatsoever. From any browser, regardless of what browser extensions were installed.
Contents
Summary of the findings
As part of its Online Protection functionality, Bitdefender Antivirus will inspect secure HTTPS connections. Rather than leaving error handling to the browser, Bitdefender for some reason prefers to display their own error pages. This is similar to how Kaspersky used to do it but without most of the adverse effects. The consequence is nevertheless that websites can read out some security tokens from these error pages.
These security tokens cannot be used to override errors on other websites, but they can be used to start a session with the Chromium-based Safepay browser. This API was never meant to accept untrusted data, so it is affected by the same vulnerability that we’ve seen in Avast Secure Browser before : command line flags can be injected, which in the worst case results in arbitrary applications starting up.
How Bitdefender deals with HTTPS connections
It seems that these days every antivirus product is expected to come with three features as part of their “online protection” component: Safe Browsing (blocking of malicious websites), Safe Search (flagging of malicious search results) and Safe Banking (delegating online banking websites to a separate browser). Ignoring the question of whether these features are actually helpful, they present antivirus vendors with a challenge: how does one get into encrypted HTTPS connections to implement these?
Some vendors went with the “ask nicely” approach: they ask users to install their browser extension which can then implement the necessary functionality. ThinkMcAfee for example. Others took the “brutal” approach: they got between the browser and the web servers, decrypted the data on their end and re-encrypted it again for the browser using their own signing certificate. ThinkKaspersky. And yet others took the “cooperative” approach: they work with the browsers, using an API that allows external applications to see the data without decrypting it themselves. Browsers introduced this API specifically because antivirus products would make such a mess otherwise.
Bitdefender is one of the vendors who chose “cooperative,” for most parts at least. Occasionally their product will have to modify the server response, for example on search pages where they inject the script implementing the Safe Search functionality. Here they unavoidably have to encrypt the modified server response with their own certificate.
Quite surprisingly however, Bitdefender will also handle certificate errors itself instead of leaving them to the browser, despite it being unnecessary with this setup.
Compared to Kaspersky’s, this page does quite a few things right. For example, the highlighted action is “Take me back to safety.” Clicking “I understand the risks” will present an additional warning message which is both informative and largely mitigates clickjacking attacks. But there is also the issue with HSTS being ignored, same as it was with Kaspersky . So altogether this introduces unnecessary risks when the browser is more capable of dealing with errors like this one.
But right now the interesting aspect here is: the URL in the browser’s address bar doesn’t change. So as far as the browser is concerned, this error page originated at the web server and there is no reason why other web pages from the same server shouldn’t be able to access it. Whatever security tokens are contained within it, websites can read them out – an issue we’ve seen in Kaspersky products before .
What accessing an error page can be good for
My proof of concept used a web server that presented a valid certificate on initial request but switched to an invalid certificate after that. This allowed loading a malicious page in the browser, switching to an invalid certificate then and using XMLHttpRequest
to download the resulting error page. This being a same-origin request , the browser will not stop you. In that page you would have the code behind the “I understand the risks” link:
var params = encodeURIComponent(window.location); sid = "" + Math.random(); obj_ajax.open("POST", sid, true); obj_ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); obj_ajax.setRequestHeader("BDNDSS_B67EA559F21B487F861FDA8A44F01C50", "NDSECK_c8f32fef47aca4f2586bd075f74d2aa4"); obj_ajax.setRequestHeader("BDNDCA_BBACF84D61A04F9AA66019A14B035478", "NDCA_c8f32fef47aca4f2586bd075f74d2aa4"); obj_ajax.setRequestHeader("BDNDTK_BTS86RE4PDHKKZYVUJE2UCM87SLSUGYF", "835f2e23ded6bda7b3476d0db093e2f590efc1e9333f7bb7ad48f0dba1f548d2"); obj_ajax.setRequestHeader("BDWL_D0D57627257747A3B2EE8E4C3B86CBA3", "a99d4961b70a8179664efc718b00c8a8"); obj_ajax.setRequestHeader("BDPID_A381AA0A15254C36A72B115329559BEB", "1234"); obj_ajax.setRequestHeader("BDNDWB_5056E556833D49C1AF4085CB254FC242", "cl.proceedanyway"); obj_ajax.send(params);
So in order to communicate with the Bitdefender application, a website sends a request to any address. The request will then be processed by Bitdefender locally if the correct HTTP headers are set. And despite the header names looking randomized, they are actually hardcoded and never change. So what we are interested in are the values.
The most interesting headers are BDNDSS_B67EA559F21B487F861FDA8A44F01C50
and BDNDCA_BBACF84D61A04F9AA66019A14B035478
. These contain essentially the same value, an identifier of the current Bitdefender session. Would we be able to ignore errors on other websites using these? No, this doesn’t work because the correct BDNDTK_BTS86RE4PDHKKZYVUJE2UCM87SLSUGYF
value is required as well. It’s an HMAC-SHA-256 signature of the page address, and the session-specific secret used to generate this signature isn’t exposed.
But remember, there are three online protection components, and the other ones also expose some functionality to the web. As it turns out, all functionality uses the same BDNDSS_B67EA559F21B487F861FDA8A44F01C50
and BDNDCA_BBACF84D61A04F9AA66019A14B035478
values, but Safe Search and Safe Banking don’t implement any additional protection beyond that. Want to have the antivirus check a bunch of search results for you? Probably not very exciting but any website could access that functionality.
Starting and exploiting banking mode
But starting banking mode is more interesting. The following code template from Bitdefender shows how. This template is meant to generate code injected into banking websites, but it doesn’t appear to be used any more (yes, unused code can still cause issues).
var params = encodeURIComponent(window.location); sid = "" + Math.random(); obj_ajax.open("POST", sid, true); obj_ajax.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); obj_ajax.setRequestHeader("BDNDSS_B67EA559F21B487F861FDA8A44F01C50", "{%NDSECK%}"); obj_ajax.setRequestHeader("BDNDCA_BBACF84D61A04F9AA66019A14B035478", "{%NDCA%}"); obj_ajax.setRequestHeader("BDNDWB_5056E556833D49C1AF4085CB254FC242", "{%OBKCMD%}"); obj_ajax.setRequestHeader("BDNDOK_4E961A95B7B44CBCA1907D3D3643370D", "{%OBKREFERRER%}"); obj_ajax.send(params);
We’ve seen NDSECK
and NDCA
values before, it’s the values which can be extracted from Bitdefender’s error page. OBKCMD
can be obk.ask
or obk.run
depending on whether we want to ask the user first or run the Safepay browser immediately (we want the latter of course). OBKREFERRER
can be any address and doesn’t seem to matter. But the params
value sent with the request is important, it will be the address opened in the Safepay browser.
So now we have a way to open a malicious website in the Safepay browser, and we can potentially compromise all the nicely isolated online banking websites running there. But that’s not the big coup of course. What if we try to open a javascript:
address? Well, it crashes, could be exploitable… And what about whitespace in the address? Spaces will be URL-encoded in https:
addresses but not in data:
addresses. And then we see the same issue as with Avast’s banking mode , whitespace allows injecting command line flags.
That’s it, time for the actual exploit. Here, param1
and param2
are the values extracted from the error page:
var request = new XMLHttpRequest(); request.open("POST", Math.random()); request.setRequestHeader("Content-type", "application/x-www-form-urlencoded"); request.setRequestHeader("BDNDSS_B67EA559F21B487F861FDA8A44F01C50", param1); request.setRequestHeader("BDNDCA_BBACF84D61A04F9AA66019A14B035478", param2); request.setRequestHeader("BDNDWB_5056E556833D49C1AF4085CB254FC242", "obk.run"); request.setRequestHeader("BDNDOK_4E961A95B7B44CBCA1907D3D3643370D", location.href); request.send("data:text/html,nada --utility-cmd-prefix=\"cmd.exe /k whoami & echo\"");
And this is what you get then:
The first line is the output of the whoami
command while the remaining output is produced by the echo
command – it displays all the additional command line parameters received by the application.
Conclusions
It’s generally preferable that antivirus vendors stay away from encrypted connections as much as possible. Messing with server responses tends to cause issues even when executed carefully, which is why I consider browser extensions the preferable way of implementing online protection. But even with their current approach, Bitdefender should really leave error handling to the browser.
There is also the casual reminder here that even data considered safe should not be trusted unconditionally. That’s particularly the case when constructing command lines, properly escaping parameter values should be the default, so that unintentionally injecting command line flags for example is impossible. And of course: if you don’t use some code, remove it! Less code automatically means fewer potential vulnerabilities.
Timeline
- 2020-04-15: Reported the vulnerability via the Bitdefender Bug Bounty Program .
- 2020-04-15: Confirmation from Bitdefender that the report was received.
- 2020-04-16: Confirmation that the issue could be reproduced, CVE number assigned.
- 2020-04-23: Notification that the vulnerability is resolved and updates are underway.
- 2020-05-04: Communication about bug bounty payout (declined) and coordinated disclosure.
- 2020-05-12: Confirmation that fixes have been pushed out. Disclosure delayed due to waiting for technology partners.
以上就是本文的全部内容,希望本文的内容对大家的学习或者工作能带来一定的帮助,也希望大家多多支持 码农网
猜你喜欢:本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
JSP & Servlet学习笔记
【台湾】林信良 / 清华大学出版社 / 2012-5 / 58.00元
本书是作者多年来教学实践经验的总结,汇集了教学过程中学生在学习JSP & Servlet时遇到的概念、操作、应用或认证考试等问题及解决方案。 本书针对Servlet 3.0的新功能全面改版,无论是章节架构与范例程序代码,都做了全面更新。书中详细介绍了Servlet/ JSP与Web容器之间的关系,必要时从Tomcat源代码分析,了解Servlet/ JSP如何与容器互动。本书还涵盖了文本处理......一起来看看 《JSP & Servlet学习笔记》 这本书的介绍吧!
随机密码生成器
多种字符组合密码
HSV CMYK 转换工具
HSV CMYK互换工具