Tutorial for secure programming in React that would cover major vulnerabilities

The emergence of security vulnerabilities is a constant in software development, so it is important that cybersecurity specialists learn to identify potential security risks and some incident prevention mechanisms.

This time, experts from the International Institute of Cyber Security (IICS) will show you how to use the React open source JavaScript library to address the main security risks currently in place. As you’ll remember, React is a library maintained by Facebook and created to create user interfaces to facilitate the development of applications on a single page. There are currently more than a thousand cybersecurity researchers collaborating with this project.

CROSS-SITE SCRIPTING (XSS)

The cross-site script (XSS) is a type of client-side vulnerability that can lead to serious problems, cybersecurity experts point out. XSS attacks occur when a threat actor can trick a website into running arbitrary JavaScript in the target web browser, and there are variants such as mirrored XSS or stored XSS

The mirrored XSS attack is performed on a link that contains text data that the browser processes as code. For example, a form field in which a special request text is entered on the client side.

On the other hand, the stored XSS is a scenario in which an attacker accesses a server and when code executed on the server generates what reaches the client’s web page. Typical vectors of these attacks are the loading of comments and images on servers.

In the past, hackers used the Samy worm to exploit XSS vulnerability in MySpace, becoming one of the most spreading viruses in history. Malicious scripts are most often used to send spam and redirect users to fraudulent sites, cybersecurity experts point out.

SECURITY FLAW 1: TAKING CONTROL OVER THE STATUS OF THE ORIGINAL PAGE DURING SERVER RENDERING

Sometimes, when we form the initial state of the page, which is dangerous, we create a document based on a JSON string. This vulnerability looks like this in your code:

<script>window.__STATE__ = ${JSON.stringify({ data })}</script>

This is dangerous because this method will convert the data provided to you into a string shape that will be displayed on the page. If it contains fields that an unauthorized user can edit, such as the user name or user information, you can include the following in those fields: JSON.stringify (){data}

{ username: "pwned", bio: "</script><script>alert('XSS Vulnerability!')</script>" }

This pattern is often used when rendering server-side React applications using Redux. It was introduced in the official Redux documentation, with the result that many of the sample app tutorials and templates found on GitHub still use it.

How to identify any vulnerability during a code review?

Cybersecurity experts recommend looking for calls to methods that accept variables that may contain unauthorized data on the label. Here is an example that used to be in the Redux documentation: JSON.stringify script ()

function renderFullPage(html, preloadedState) {
    return `
        <!doctype html>
        <html>
            <head>
                <title>Redux Universal Example</title>
            </head>
            <body>
                <div id="root">${html}</div>
                <script>
                    window.__PRELOADED_STATE__ = ${JSON.stringify(preloadedState)}
                </script>
                <script src="/static/bundle.js"></script>
            </body>
        </html>
        `
}

And here’s a snippet of the sample app that was found on GitHub:

function htmlTemplate( reactDom, reduxState, helmetData ) {
    return `
    <!DOCTYPE html>
    <html>
    <head>
        <meta charset="utf-8">
        ${ helmetData.title.toString( ) }
        ${ helmetData.meta.toString( ) }
        <title>React SSR</title>
        <link rel="stylesheet" type="text/css" href="./styles.css" />
    </head>
    
    <body>
        <div id="app">${ reactDom }</div>
        <script>
            window.REDUX_DATA = ${ JSON.stringify( reduxState ) }
        </script>
        <script src="./app.bundle.js"></script>
    </body>
    </html>
    `;
    
}

Sometimes this vulnerability is a little harder to detect. The following code will also be unsafe if the appropriate sandbox escape is not performed: context.data

const RenderedApp = htmlData.replace('{{SSR}}', markup)
    .replace('<meta-head/>', headMarkup)
    .replace('{{data}}', new ArrayBuffer(JSON.stringify(context.data)).toString('base64'))

When rendering the server, pay attention to what is being rendered. If what the user enters does not escape and is sent to the DOM, it can be dangerous.

How to protect yourself against this attack?

One of the main protection methods is to use the npm serialize-javascript module, designed to delete JSON output. If you are rendering to a server outside of Node.js, you must select the appropriate package for the language you are using.

The following is the installation command for the mentioned module:

$ npm install --save serialize-javascript

After that, you must import it into a file and rewrite the previously vulnerable code:

<script>window.__STATE__ = ${ serialize( data, { isJSON: true } ) }</script>

More details can be found in other tutorials.

SECURITY FLAW 2: MALICIOUS LINKS

A tag <a> can contain a hrefthat attribute to take users from one website to a completely different page. These links may also contain malicious scripts that could trigger severe damage to the target system. You can test these functions by copying the following code into your browser string: javascript: stuff().

data:text/html, <a href="javascript: alert('hello from javascript!')" >click me</a>

Cybersecurity experts mention that this means that if the content of the links is installed according to user input, an attacker may add malicious code to the compromised systems. Then, if the user follows the wrong link, the attacker’s script will start in the browser.

This is not a flaw that only affects React-based applications, but it is one of the most common issues for React developers when they expect the corresponding value to automatically escape properly. It should be noted that upcoming versions of React will include mitigations for these kinds of flaws.

How to detect any vulnerability?

Can project users add links to pages that other users can navigate to? If so, try adding a “link” to the page as follows:

javascript: alert("You are vulnerable to XSS!")

If the corresponding message box is displayed when you click the link, the project is vulnerable to XSS attacks. Try it every time you can add links. Probably not all of these locations are vulnerable.

Protection mechanisms

Cybersecurity experts mention that removing the javascript: data prefix can solve this problem. This is an example blacklist policy that is not working properly.

Hackers have devised all sorts of methods to bypass these security mechanisms, so you need to use advanced whitelisting protocols.

Another cybersecurity strategy is to add an additional layer of protection to your project is to use a custom link opening mechanism in the new browser tabs. However, experts do not recommend using this strategy as the only line of defense for the project.

SECURITY FLAW 3: DANGEROUSLYSETINNERHTML CONSTRUCTION ERRORS

DangerouslySetInnerHTML is the name by which a React configuration is known that can be very dangerous for developers. Consider the following example, found on a site from the first page of Google search results:

<script dangerouslySetInnerHTML={{ __html: `window.__PRELOADED_STATE__ = ${JSON.stringify(initialState)};`}}></script>

This is an example of the first vulnerability described in this article, but with a peculiarity that should draw the attention of cybersecurity experts. This example uses dangerouslySetInnerHTML as a method to clear data and prevent XSS attacks, which is not recommended; you can find more information about this setting in the React files.

Another example of this happening all the time is finding a security vulnerability by adding the Markdown framework to a site using dangerousSetInnerHTML. To protect ourselves from this condition, we can use a special rule.

How to identify vulnerabilities during a code review

Before submitting pull requests, you can search your code for the evaluation and HTML strings dangerouslySetInnerHTML (that’s how I’m also looking for console.log commands) or use the appropriate linter rule.

Ensure that each time you use the dangerouslySetInnerHTML setting, only trusted data is loaded into the page. More information can be found in other tutorials.

CONCLUSIONS

React is built on JavaScript, so those interested in learning React should understand how well they know JavaScript. Developers often make mistakes that demonstrate their little knowledge of JavaScript, so they are prone to configuration errors in React.

Cybersecurity experts recommend that developers deepen their use of JavaScript before using React. To learn more about information security risks, malware variants, vulnerabilities and information technologies, feel free to access the International Institute of Cyber Security (IICS) websites.