📜 ⬆️ ⬇️

Client application security: practical tips for Front-end developer

As you know, the majority of BlackHat hacker attacks are aimed at compromising the server data of web applications and services. At the same time, the client part of the attack today is not less. According to the dry definition, any attack is a set of measures by the hacker aimed at the network and data transfer, data and their substitution, infrastructure and technical features of the implementation of a web application. Therefore, international companies require development engineers to take a more responsible and careful approach to client application security.


Using the example of my project, I will talk about how client applications are attacking today and how you can avoid these threats.


Top 10 threats for 2013 - 2017
Top 10 threats for the years 2013 - 2017.

As you can see, among the main threats are injections, error handling, authentication bypass, and insecurity of sensitive data. The threat of using components with known vulnerabilities is still relevant. New threats also appeared: hacking of the access control mechanism, unsafe deserialization and data serialization, insufficiently detailed logging and monitoring.


In 2001, Marc Kerfi and Dennis Gruvz founded the OWASP (Open Web Application Security Project). This is an international OpenSource project for sharing experience on combating vulnerabilities in client applications, in which a huge number of application security engineers take part. The OWASP community fills the portal with a variety of vulnerability information articles, training materials, tools for testing and repelling attacks. It describes the real attacks, reveals their aspects and describes what needs to be done to prevent threats.


To understand what threats are dangerous for the project, it is necessary to thoroughly test it. To do this, the network has applications, frameworks and online services that automatically identify certain vulnerabilities. For local testing, I recommend using applications and frameworks, and for testing projects in operation, it is very useful to add online services.




But even if the testing tools did not tell you in the reports about significant vulnerabilities (which is unlikely), pay attention to storing sensitive data in the version control system, building the application, authentication mechanism, password hashing algorithm, encryption functions and monitoring the entire web application. In this case, it is better to play it safe and not blindly trust automatics.


Git


First, let's talk about sensitive data in Git. In the ideal case, a separate secret storage is allocated for storing sensitive data. From it, when assembling for commissioning, confidential data is tightened and stitched into the application. Today, Hashicorp Vault, Keywhiz, Docker secrets, Azure Key Vault and several others are popular.


But what if you do not have such a repository? You can use tools to encode and hide files with secrets that will enhance the capabilities of version control systems.


The first thing that comes to mind is the BlackBox universal solution. It can be used with any version control system, for example, Mercurial, Git, etc. In addition, there are two extensions for Git: git-crypt and git-secret. I recommend using the second one, because it seemed to me most convenient to use and more understandable in terms of description in official documentation. After installing the git-secret, you need to initialize it in the Git-repository. Don't forget to specify the extension used in the .gitattributes file. Next, configure the availability of secrets: determine the users you want to provide access to sensitive data. Then add files with sensitive data and git-secret-hide them through git-secret-hide . You can get hidden files through git-secret-reveal.


brew install git-secret //
git secret init //
git secret tell your@gpg.email  //
git secret add <files...> //
git secret hide  //
git secret reveal  //

Webpack


Another way to eliminate threats is to configure the webpack correctly. To protect against XSS, XEE and similar attacks, you need to think about adhering to the CORS (Cross-origin resource sharing) and CSP (Content Security Policy) policies. In both cases, it is important to observe the headers in order to verify the authenticity of certain scripts that are used in the project. Browsers have mechanisms for verifying the reliability of one or another source, for example, Safari will issue warnings at every step if CORS and CSP are configured incorrectly.


There are two ways to comply with CORS and CSP. The first is to configure the headers of the response to requests in the server part. The second is to prescribe both policies through meta tags and attributes. The latter method is recommended if you have lazy back-end developers, they are always busy and they are not up to security policies. Meta tags can be written immediately when building the application. This will help us with such plugins as html-webpack-plugin, html-webpack-exclude-assets-plugin, script-ext-html-webpack-plugin, csp-html-webpack-plugin and crypto. In addition, if you have third-party resources in the project (for example, links to external fonts used in CSS; resources loaded from CDN, etc.), I recommend using webpack-subresource-integrity-plugin. Thus, you will inform the browser that the loaded resources in the script are reliable, there are no implementations in them, they are whole and uncorrupted. And even if someone has introduced malicious data into the resource, and you have loaded it, you should be prepared for this and secure your project from such threats.


I want to pay special attention to the sequence in which and how instances of classes for plugins are created. The sequence must be exactly this:


 const SHA256 = (str) => CRYPTO.createHash('sha256').update( str, 'utf8').digest('base64'); const sha256Str = SHA256( '' + Date.now() ); […] new HtmlWebpackPlugin({   filename: 'index.html',   template: 'public/index.html' }), new ScriptExtHtmlWebpackPlugin({    custom: [{           test: /\.js$/,           attribute: 'nonce',           value: 'nonce-' + sha256Str    }] }), new HtmlWebpackExcludeAssetsPlugin(), new CspHtmlWebpackPlugin({    'base-uri': '\'self\'',    'object-src': '\'none\'',    'script-src': ['\'self\'', '\'unsafe-eval\'', '\'nonce-' + sha256Str + '\''],    'style-src': ['\'unsafe-inline\'', '\'self\''] }, {    devAllowUnsafe: false,    enabled: true,    hashingMethod: 'sha256' }), new SriPlugin({    hashFuncNames: ['sha256', 'sha384'],    enabled: true }), […] 

Then, when assembling, the meta tag http-equiv=content-security-policy appears in the <hed> tag. The content attribute will contain directives that tell which scripts and resources can be trusted.


The base-uri directive shows which base URL is used to download scripts, CSS, images and other things.


Objects are usually not loaded, so in the directive object-sr c put none .


The script-src directive applies to JS scripts.


Do not forget to prescribe each type attribute nnce-<hshVlue> . And the hash needs to be calculated using the SHA256 or SHA512 algorithm.


As for the style-src directive, our project has a feature: we use styled-components to prescribe CSS for each component and isolate them from each other. And therefore, it is necessary to indicate that we use unsafe-inline and self in style-src , otherwise the styled-components will fall off.


')


For the script tag, the attributes will be automatically set nnce-<hshVlue> , integrity and cross-origin . They tell the browser that resources are being pulled from reliable sources. Otherwise, if the browser sees that the resource does not correspond to CSP or CORS, then it simply does not load this script or CSS file, but in the console it will write something like: “Pay attention to this script, to this line where you initialize him. Look, you have something wrong! " .


The MDN , OWASP and W3C documentation has recommendations on how to enforce CSP and CORS policies. In addition, any penetration testing toolkit will report compliance with the CORS and CSP rules in the project. Any framework or tool that will conduct automatic testing of the project will indicate shortcomings.


User Authentication


We use OpenID Connect and the Kerberos protocol. A fairly common standard is OpenID used to authenticate external users.


Kerberos is more suitable for the internal network, in the bank it is used for automatic authentication of employees. Suppose there is a local machine on which an employee of the organization works. He once authenticated on this machine, and then he will not need to enter his login and password again: the employee logs into any application and the system authenticates it immediately. Kerberos has fine tuning for the local machine, and this is difficult because you have to configure it for each computer and each browser. If Internet Explorer normally tightens default settings, and Chrome tightens IE settings, then Firefox has to be configured separately. Safari on MacOS X itself will find the settings, and for Safari on Windows you will need to specify them manually.


You need to check your application in all browsers, whether it works everywhere as needed. For example, if I work on Windows, I put Safari locally and test my project in it, and if I work on a Mac, I raise Windows on a virtual machine to drive the application on the corresponding browser versions.


Authentication in modern applications can be implemented using the Passport.js and express-session packages, as well as the Auth0 SDK.


If you are unable to develop an authentication service through OpenID Connect or any other protocol, then use a proxy layer, such as Auth0 and the like, so that authentication occurs through a third-party company that specializes in providing users with secure access to Internet resources.


When we add an application to Node.js, I recommend using Passport.js, express-session, etc. packages on the server. To ensure security on the client, we independently raise the component for authentication. In the authentication form, do not forget to specify the autocomplete off attribute to exclude auto-completion of form fields.


Password Hashing


The OWASP website recommends not using password hashing mechanisms built into databases. For this, it is better to use packages such as Argon2, PBKDF2, ccrypt and bcrypt. In my practice, I use Argon2 - this is a wrapper for GCC, PGP / GPG, etc. algorithms, but it is required to install the GCC package first. Argon2 use pattern:



 1.  GCC >= 4.8 install $ brew install gcc 

 2.     - $ npm install -g node-gyp 

 3.   Argon2 $ npm install argon2 

 4.   import * as ARGON from 'argon2'; ARGON.generateSalt().then( (salt: string) => {  ARGON.hash('some-user-password', salt)    .then((hash : string) => {       console.log('Successfully created Argon2 hash:', hash);       // TODO: store the hash in the user database  }); }); argon2.verify( 'previously-created-argon-hash-here', 'some-user-password').then(() => {  console.log('Successful password supplied!');  // TODO: log the user in }).catch(() => {  console.log('Invalid password supplied!'); }); 

Obfuscation


Obfuscation allows you to modify the code so that it can not be disassembled into its components. After all, attackers - and not only they - very often use reverse engineering: the programmer takes a JS-file and begins to analyze the source code. Thus, he can learn the methods used or understand the mechanism of the work of a script to inject malicious code. Or use these mechanisms to hack a web application and conduct an invisible attack.


Hackers do not climb on the rampage. First, they conduct resource exploration, determine vulnerabilities and attack vector. For example, they manipulate data or exploit vulnerabilities contained in transport protocols. The attack vector can be directed to the vulnerabilities of one or another operating system; there are a lot of them in any UNIX system. But vulnerabilities can only be exploited if the administrator has poorly configured security policies, such as incorrectly specifying URLs that go outside.


So, reverse engineering is used for reconnaissance. It is impossible to completely eliminate it, but it can be very difficult. For this purpose, various obfuscators are used, in my case - javascript-obfuscator. On its base, a webpack plugin was made - webpack-obfuscator. Also for webpack created obfuscator-loader. This package has recommended settings of different levels of paranoia: low, medium and high, they can be found on the official website. If you use this obfuscator, then remember that it works very poorly with the minification mechanism built into the webpack. Do not use minification and obfuscation together, otherwise the obfuscator can completely break the script code.


In addition, obfuscator increases the volume of the script and its loading. Here you need to decide for yourself: either you increase security, stability and reliability, but lose in convenience and speed; or take care of speed, but forget about safety, about following any guidelines.


Logging and monitoring of threats


There is such a threat as using packages with known vulnerabilities. Threat analyzers such as npm audit, Snyk and LGTM will help in such situations. Npm audit is a standard utility that is built into npm, but you have to constantly call this command or come up with crutches. Therefore, I advise you to use Snyk. This project has its own database with vulnerabilities. When you start checking, Snyk refers to this database and confidentially uploads the report to your Snyk project, which is inaccessible to outsiders. True, you can check your project for free only 300 times, and when you check for each pre-commit, these 300 free attempts end very quickly. Therefore, it is better to run the check on pre-push or pre-merge hooks.


Man - the most important vulnerability of any system. Therefore, be sure to check the project before starting to build the application, because even the source code may contain something malicious. It is good when only one person has access to the project, but usually we work as teams. And what if a “well-wisher” appeared who decided to leave the company “beautifully” and leave a trace behind him? This, too, must be borne in mind.


I recommend using the Snyk package from the very beginning of the project, and run the check from the console. Everything is simple: after installation, set the username and password to the account, but the testing itself can be performed as follows:



 ./node_modules/.bin/snyk wizard --dev 


 { ... "scripts": {  ...  "test": "npm run test:snyk && npm run test:jest",  ...  "test:snyk": "snyk test --dev",  ...  "prepare": "npm run prepare:snyk",  "prepare:snyk": "snyk protect" }, "husky": {  "hooks": {   "commit-msg": "commitlint -E HUSKY_GIT_PARAMS",   "pre-commit": "npm run test:snyk && npm run lint && npm run test:jest",   "pre-push": [    "npm run test:snyk",    "npm run lint",    "npm run test:jest",    "npm run build:production"   ],   ...  } }, "snyk": true } 

Above, we looked at local security checks. I recommend using LGTM to check packages for known threats. Use this project in conjunction with GitHub or Bitbucket (I have not tried it yet, it was not necessary), and the code will be checked immediately with each push.


Application monitoring


In the field of Front-end, the tools have already been settled, tools for every taste are available for logging and monitoring the client part. The most famous are Sentry, TrackJS and InsightOps. Sentry server can be deployed on its physical servers. For example, in our two projects a separate server was used, fully configured for logging the operation of applications. We went to the URL and threw all the logs there. If an error occurs in the application, it is wrapped in a try catch block and sent to the Sentry server through the methods of the raven package. Everything is simple and convenient. If you see incomprehensible URLs in Sentry that you did not register, if you see introductions or incomprehensible messages, it means that you are being hacked. In my practice, this is met regularly. For example, one of the projects - a service for circumventing ad blockers and antiviruses - was constantly trying to counteract and hack it.


I also recommend using Grafana for monitoring. It is important to consider a system of criteria and indicators that will be monitored by the system. We tuned in for traffic, for advertising returns, for the degree of ad rendering, for the number of banners that came from Yandex, and so on. (projects in Rambler Group). We needed to understand how Yandex works with our requests, because it is a third-party service, which means it should be monitored, because if it refuses, the entire project can collapse completely.


If you monitor all communication with third-party services, then very quickly you will find any error. A story from my practice: we saw that the answers to advertising had suddenly ceased to come from Yandex. It turned out that they had technical malfunctions and the entire advertising network lay tight. And it was not Yandex that informed us first, but we called them and asked to see what was happening with their services.


What is the best monitor? Take a small URL, list the GET parameters and send a GET request to this URL. In the server part, process this URL, write the log to the database and raise the monitoring on Grafana. It's simple.


That's all. In the future I will try to continue writing on the topic of protecting web applications from threats. Anyone who has read to the end - I wish security to your projects)))


List of sources for reading on the topic:


www.owasp.org/index.php/Main_Page


tproger.ru/translations/webapp-security


S. Hawks. Even Faster Single Page Application: security


Seacord, Robert C. The CERT C secure coding standard / Robert C. Seacord. - 2008


Chetan Karande. Securing Node Applications - 2017


Steven Palmer. Web Application Vulnerabilities Detect, Exploit, Prevent - 2011


Robert Shimonski, Sean-Philip Oriyano. Client-Side Attacks and Defense - 2012


Marcus Pinto, Dafydd Stuttard. Hacker's Web Application Handbook: Finding and Exploiting Security Flaws, 2nd Edition - 2011


Karl Duuna. Secure Your Node.js Web Application - 2015

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


All Articles