📜 ⬆️ ⬇️

(Not) safe frontend

Intro


Not so long ago I spoke at the FrontendConf 2015 (RIT ++) conference with the topic of this article. And when preparing the report, I began to look for information, and who spoke at all on this topic and what is on the web at the moment.

It turned out that quite a bit of information, more or less one could mention the report by Mike West from Google, mikewest.org/2013/09/frontend-security-frontendconf-2013 , but some kind of "non-penster" look and very little material . And www.slideshare.net/eoftedal/web-application-security-in-front-end where the topic is covered in more detail, but the 2011 presentation. And for 4 years, technology and attacks in place did not stand.

It’s long and difficult to choose topics, what to tell the front-end developers about security, while at the same time touching the backend (in some places it’s still indivisible), we got a report, and here’s a text retelling.
')

What do you talk about?


And really, what is there to talk about? Speaking about hacks and security, involuntarily theses come to mind - they merged the database, got access to the execution of OS commands on the server, read someone else's correspondence. But this is all - server side code. And what can "pile up" a front-end? The main danger, of course, is bypassing the attacking SOP - the Same Origin Policy, the main browser security policy that regulates work in different Origin. But not only, let's understand.


Crossite scripting



Cross Site Scripting
The XSS theme is trashed as much as possible, but usually it’s about incorrect processing of parameters on the server side (an attacker can embed his JS code into the page and execute it, including in the victim’s browser, on behalf of the vulnerable origin, the result is an SOP bypass). And there they identified 2 types of XSS attacks - stored (“evil” js is stored on the server) and reflected (given by the server without saving).

Well, what about the front-end? And here is another case - the attacker's JS is not transmitted to the server (with some exceptions, but the point is not in them), but is embedded in the DOM at the expense of legitimate JS code. Hence the name for the third type of XSS attack, the DOM XSS.

A typical example of vulnerable JS code:

document.write("Site is at: " + document.location.href); 

Now open the page at

 http://victim.com/action#<script>alert('xss')</script>Ń• 

JS will add the value of document.location.href to the tree, where the “malicious” js is inserted. As you can already see from this example, to search for vectors for this type of attack, we need two things: to influence something in the user's browser (sources) and to do something (sinks).

Examples of "sources" (sources):


Sinks examples

For more information on this topic, please click on the links - code.google.com/p/domxsswiki (and get a regular search from here to find potential vulnerabilities) and habrahabr.ru/company/xakep/blog/189210 , an article from my colleague Alexei Tyurin

Here is an example of a vulnerable code (real) from twitter.com ( full story )

 (function(g){var a=location.href.split("#!")[1];if(a){g.location=g.HBR=a;}})(window); 


image
DOM XSS example on twititer.com

Information leaks


It often happens that JS / CSS files contain information about the system infrastructure.

About javascript


When projects become very large and different environments for an application enter (test / dev / prod), the crutches and definition start, including on the client, in what environment you need to work.

An example of such a real file, mail.ru - img.imgsmail.ru/r/webagent/release/loader.js

 var dl = (''+document.location), host = document.location.host, branch = 'master', path = 'release/467', base = 'r/webagent/', probability = [ {"branch": "wa-514", "deprecated":1} ], lastForcedVersion = '20131126154524', isLocalhost = dl.indexOf('localhost') != -1, testServer = host.match(/[^.]+\.((?:f|my\.rapira)\d*)\.mail\.ru/), devServer = host.match(/^.+\.dev\.mail\.ru$/), isRapira = testServer && testServer[1].indexOf('my.rapira') == 0, utf = true,//!!window.IS_UTF, domainProps = {}, domain = '//img.imgsmail.ru', login = getUserLogin(), useBranch = (dl.match(/\Wwa_use_branch=([a-z0-9-]*)/i)||[0,false])[1], useLang = (dl.match(/\Wwa_lang=([az]{2})/i)||[0,false])[1], useOnce = (dl.match(/\Wbranch=([a-z0-9-]*)/i)||[0,false])[1], appVersion = (dl.match(/\Wwa_appver=([\.0-9]*)/i)||[0,false])[1], usedBranch = branch; 

As can be seen from the file, by regulars, you can define domains (and pull down valid ones?) For tests and development. In this case, the information may not be very critical (if mail.ru is up to date), but sometimes there are also such constructions:

 internalDevHOST = '172.16.22.2'; internalProdHOST = '172.16.22.5'; 

And sometimes with external IPs (although internal ones can also be useful, for example, with SSRF).

CSS


CSS is the same. Projects are growing, developers are starting to use various “collectors” who just leave and leave “tasty” information, for example - hackerone.com/reports/2221

 file\:\/\/\/applications\/hackerone\/releases\/20140221175929\/app\/assets\/stylesheets\/application\/browser-not-supported\.scss file\:\/\/\/applications\/hackerone\/releases\/20140221175929\/app\/assets\/stylesheets\/application\/modules\/add-category\.scss file\:\/\/\/applications\/hackerone\/releases\/20140221175929\/app\/assets\/stylesheets\/application\/modules\/alias-preview\.scss ... 

MVC frameworks


Various JS MVC frameworks are becoming more popular: AngularJS, Knockout, EmberJS, etc. They are very cool, they allow you to expand your work with the DOM, create new elements (), create "binding", etc. Naturally, something new could not pass unnoticed by the world of security.

In particular, we are interested in logic-less templates.

 <ul> <li ng-repeat="phone in phones"> <span>{{phone.name}}</span> <p>{{phone.snippet}}</p> </li> </ul> 

Which allow to significantly reduce the number of "copy-paste" and assign values ​​to the specified variables inside the brackets.

Or a mustache, if the bracket is rotated 90 °. Mustache! mustache.imtqy.com

image

This is how the mustache security project, code.google.com/p/mustache-security, appeared , about the security of MVC frameworks. Already have information about:


So let's go back, what bad can happen here? Take AngularJS. For example, there are situations when an attacker just falls just inside these brackets. And of them somehow you need to run your JS, but this is not possible by default. The task is to bypass the sandbox.

Example with AngularJS (1.1.5)

 <div class="ng-app"> {{constructor.constructor('alert(1)')()}} </div> 

So, it’s still not very tricky in the AngularJS version <1.1.5, you could get out of the sandbox and “reach” the window object (in the example above, just call alert (1)), the entire browser window. Google released the fix, and ...

AngularJS (1.2.18), after fixes

 {{ (_=''.sub).call.call({}[$='constructor'].getOwnPropertyDescriptor(_.__proto__,$).value,0,'alert(1)')() }} 

The desired alert (1) is also received!

So what am I. Updating the framework is important not only for functionality, but also for security!

Cookies


Considering this point, we are already starting to touch on a little backend. But quite a bit.
How do cookies are usually set on the server side?

PHP example:
 <?php setcookie('foo','bar1'); ?> 

Python example:
 import Cookie C = Cookie.SimpleCookie() C["foo"] = "bar" print C 


Both in the first and in the second case the server will respond with the header:
 Set-Cookie: foo=bar 

Those. just tell the browser, set the bar value to the foo key. But you need to think it over and check yourself by checklist:
  1. Specify the domain to set cookies. In the example above, IE will set cookies for both the current subdomain and all subdomains. Those. if XSS is found on some “left” subdomain, the data may be compromised. More details .
  2. HttpOnly flag for session values ​​(phpsessid, for example, defaults without it). It is necessary for the browser to deny access to this value from JS (when XSS reduces the risk of theft of the user account)
  3. The Secure flag in case the site works only over HTTPS and there is no need to send important values ​​through an insecure channel.


Switch to HTTPS


The third paragraph was about HTTPS. And let's just discuss this, because it is directed just to work with the browser. Including transitions are usually server administration issues - choosing a certificate, setting up a web server, and when ready - redirecting from HTTP to HTTPS

As it happens in life. Admin puts a redirect when entering the site via HTTP on HTTPS and that's it. But just this moment, the user initially comes in via HTTP and it is at this moment that you can “drop” the redirect to HTTPS and proxy the traffic further, without giving the user the HTTPS version of the site.

Why do people come to the site also via HTTP? Because for all of them in bookmarks everything is also HTTP.

Let's take a look at the cool story :)


The story is right below this picture.

I can not tell you about the "beloved" VK. Now the wave of “hijackings” of accounts in the VC has passed / is going on. Most often, these are just hacked users' routers (there are enough vulnerabilities in the routers) with modified DNS servers, on which VC addresses are different, namely “malicious servers of malicious intruders”. They just use this trick, do not allow the user to visit the HTTPS version of the site, “rejecting” the redirect, since users of the site are still in mortgages on the HTTP version (daw on h_ttps: //vk.com/settings? Act = security yet not forced https).

So how to treat?
For this came up with the HSTS header
 Strict-Transport-Security: max-age=31536000; 

He tells the browser that on this site via HTTP no more request. Specifies the time during which this rule works (and optionally, you can set the distribution of this rule to subdomains).

And if you turn on the paranoid mode and imagine that the first time you visit the site, the traffic is intercepted and the user does not receive this header - then you can add your resource to the HSTS preload list - www.chromium.org/hsts , a list of resources for which the browser will always be visit via HTTPS (i.e. the resource list is “sewn up” directly into the browser, shared between browsers).

HTML5 Security


The article is quite large, do not despair: 0 Talking about HTML5, not only in the context of new elements, but also new API methods, it (HTML5) brought a lot of useful and safe, including on cross domain work. And what did they not invent, and the files “proxy.php” in the root of the server, and other awful crutches.

Window.postMessage ()


Imagine that we have two window objects (for example, the current window and the window from the iframe or after window.open).

A page on the abc.com domain sends a “secret” message to another window.
 otherWindow.postMessage(message, targetOrigin); 


A page on the xyz.com domain listens to messages and checks where they came from
 window.addEventListener("message", receiveMessage, false); function receiveMessage(event) { if (event.origin !== "http://example.org:8080") return; // ... } 


In general, this option is correct - specify origin, where to send (so as not to send to the attacker in the “window”), and receive, checking where the message came from. But in reality, this is rarely the case, and more often you need such a solution for the entire project (all subdomains)

Vulnerable code!
 if(message.orgin.indexOf(".example.com")!=-1) { /* ... */ } 

And sometimes you can find such a vulnerable code. example.com.attacker.com is also matched (attacker's domain). So that:



HTTP access control (CORS)


And again about cross-domain work. CORS is a cool, fashionable, safe thing that is hard to put on. Very difficult, but ... it happens :)

It also allows the browser to tell you how to work around SOP. When cross-domain operation and the first OPTIONS request, the server returns something of the type
 Access-Control-Allow-Origin: * 

Or
 Access-Control-Allow-Origin: example.com 

In the first case, it is reported that it is possible to bypass the SOP to work from any domain, in the second - only with example.com. In this case, you can specify the methods by which it is available, etc.

But by default, the identification data (for example, cookies) the browser still does not send, which is most often necessary. Need to add a headline
 Access-Control-Allow-Credentials: true 

Which will inform the browser that now do cross-domain requests together with cookies (allows you to work with the user session). But! The most interesting thing is that Allow-Origin already confusing: * (any site) + Allow-Credentials do not work together. The browser will not send cookies and this is good (as in this case, the attacker will not be able to perform actions from the user with the session). Those. This option works only when specifically allowed domains.

About "it happens." The developer specifies the allowed domains from the GET parameter (curtain).

Web sockets


Speaking about Web Sockets (WS), first of all, it should be noted that for them there are several standards with quite significant changes. Therefore, there are quite common things here.


Here I’ll just refer to owasp.org, busy reading - www.owasp.org/index.php/HTML5_Security_Cheat_Sheet , albeit incomplete (in addition to service workers - sirdarckcat.blogspot.ru/2015/05/service-workers-secure -open-redirect.html , sirdarckcat.blogspot.ru/2015/05/service-workers-new-apis-new-vulns-fun.html )

Content Security Policy


In general, the browser he is so trusting, from where he was told to upload data - CSS / JS / images, he downloaded from there. It is also useful for an attacker, just connect your malicious js file from another domain during an XSS attack. To reduce the risks of XSS attacks (and not only) came up with Content Security Policy (CSP).

This header tells the browser where you can load resources (for example, js), and where you cannot. Accordingly, an attacker even having the ability to inject js will not be able to perform it (for example, if inline js + external domains from trusted domains are prohibited).

image
Error loading JS file from a domain that is not in the white list

But it so happens that an attacker can still upload his js and execute it, for example, if applications (to a letter, message) are on a domain from the white list.

CSP understood it in more detail many times, including at the last meeting of OWASP Russia in Moscow, presentation - www.slideshare.net/OWASP-Russia/yourprezi-49135416

Flash


image

Am i serious About flash? In fact yes. For some, this is relevant, but for many it historically works somewhere else. Yes, this year already there was one large-scale case with a flush with a “new-old” bug, about which nobody wrote about it in runet :( But let's order.

crossdomain.xml


The most popular flash related is the crossdomain.xml file. This is an xml file that tells the flash application a policy for working with this domain (again, this is about SOP). And here the situation as with CORS will not pass. If it is indicated that any domain has access (together with cookies), it means any. And this, of course, is bad. An example of such a file:

 <cross-domain-policy> <allow-access-from domain="*" to-ports="80"/> </cross-domain-policy> 

A flash drive from any domain can access this resource (where this crossdomain is located) along with the user's cookies. But this is the most frequent case, it is more interesting.

From the experience of bughunting on wamba.com - they had a lot of domains in this file (they moved and changed the name of the resource many times). As a result of the file were domains that have long expired. You could successfully register and attack users of wamba.com. Gave 3 thousand (:

XSS via Flash


XSS is also possible through Flash files. Example of vulnerable AS code
 getURL(_root.URI,'_targetFrame'); 

Example of operation:
 http://victim/file.swf?URI=javascript:evilcode 

Flash will try to go to javascript: and execute arbitrary JS code. SWF is easy to decompile, so the source code is (directly) not needed. You can read more about this method of attack and find a list of available functions at OWASP - www.owasp.org/index.php/Testing_for_Cross_site_flashing_ (OTG-CLIENT-008)

CVE-2011-2461 IS BACK!


Well, now from fresh flash about flash from 2015. This spring Troopers presented a working PoC and tools for analyzing how to exploit one old vulnerability in flash files compiled on Adobe Flex (the vulnerable version). This is a very popular framework for flash developers. Such a vector - we find such a flash drive on a resource (assembled with vulnerable Adobe Flex), generate a special payload (resource) for it and connect it. A flash drive is being executed from the load domain with our payload. The bottom line is the SOP bypass.

To check these files (SWF vulnerable or not) you can use the tool - github.com/ikkisoft/ParrotNG , it is very easy to start
 java -jar parrotng_v0.2.jar <SWF File | Directory> 

More information

The authors of the study found such flash drives on Google and on other well-known resources (for example, Qiwi, Yandex). His "cut down" :)

Infrastructure leaks


The same leaks are possible as in the cases with JS / CSS. Servers, API keys, etc.

JSONP Information Disclosure


I already wrote about this in the article about the security of the API, but it is worth repeating, for completeness of this article.
Sometimes the API is provided not only for some end user, and sometimes for sending data within the project. This is often found on large, large sites with different domains. And somehow it is necessary to interact on the client side between domains, and then JSONP comes to the rescue. This is such a JSON with the necessary ones on domain 1, which turns into a callback. When accessing a domain, 1 user will send his cookies, and you can check whether he is authorized and give the necessary data. On the second domain is inserted a similar JS

 <script type="application/javascript" src="http://server1.example.com/api/getUserInfo?jsonp=parseResponse"> </script> 


with the already defined parseResponse function. But the bottom line is that an attacker can also insert this script on his domain, define his callback and, if there is sensitive data, use it somehow. A perfect example of using such a vulnerability is shown in the article “Fighting anonymity . ”

X-Frame-Options


It seems about this 1000 and once said, but again we repeat. Each resource without add. settings can be shown in the frame. The frame is loaded with the current user's cookies, i.e. in the frame it opens the resource authorized (if logged in, of course). This frame is built in by the attacker on his page, something that calls for action is drawn over (press a button, etc.), the user clicks, but in fact he clicks on the elements in the frame (for example, he subscribes to groups). The attack is called Clickjacking.

X-Frame-Options in the response of the web server allows


image

The article about clickJacking on VK

Extensions / SmartTV


To expand the capabilities of the browser there are plug-ins (for example, Flash), and there are extensions. The latter are written using just HTML / CSS / JS, which is the point of this article. Applications for SmartTV are written in a similar way using the enhanced API of TVs (for example, access to the camera). And naturally, and then you can nakosyachit. I have already talked about the security of extensions, and we will discuss the security of SmarTV applications (and attack vectors for SmartTV users) later. I leave only the video



For dessert


Well, if for some readers from the front-end it is “I JUST WRITE CSS and INSERT PICTURES! TELL ME ABOUT SECURITY! ”... this is the story.

In the transition (in "typical" conditions) by reference
 <a href=“http://external.com”>Go!</a> 

The browser in the request will give the referer, the address of the previous page. And what about styles, pictures, etc.? Are they loaded passing referer or not? I suggest right now to stop reading and answer the question for myself.

Answer
Yes transmitted

What is bad? On the hackerone.com resource, the layout designer inserted the comic into the password recovery page (where the user comes with the token in the GET parameter) from ... an external resource. As a result, the owner of this resource, when downloading this comic, saw in his access.log all tokens for resetting passwords. With the necessary account automation, you can quickly "hijack".
And it would seem - "I just insert the pictures in html" (:

Presentation from performance

Source: https://habr.com/ru/post/259389/


All Articles