DEV Community

Vlad Ataman
Vlad Ataman

Posted on • Originally published at dev-academy.com

React XSS

XSS attacks or Cross-site scripting are a type of attack in which malicious code is injected into a web page and then executed.

This malicious code can steal your cookies, modify the content or take control of an entire webpage.

The content of this article:

  • Attacks
  • DOM-based XSS attacks
    • eval
    • href
    • dangerouslySetHTML
  • Simple protection from XSS attacks
  • React XSS protection

Attacks

Starting about mid-2012, the research community started using two new terms to help organize the types of XSS.
Types of XSS attacks since mid-2012:
Types of XSS attacks

DOM-based XSS attacks in React

These attacks belong to the subset of Client cross-site scripting as the data source is from the client side only.

DOM-based XSS attacks in React
I will show you three examples of DOM-based XSS attacks in this article.
We will look at eval, href and dangerouslySetHTML vulnerabilities.

eval

The eval() function evaluates a string and returns its completion value.
The issue of the eval function is that you can paste malicious javascript code inside and execute it.
Let’s make an example, here is a code snippet in JSX code

import React, { useState } from 'react';

const Eval = () => {
    const [data, setData] = useState();

    const handleType = (e) => {
        setData(e.target.value);
    };

    const handleSubmit = () => {
        eval(data);
    };

    return (
        <div>
            <p>Place this code inside input: <code>alert('Hacked')</code></p>
            <input
                type='text'
                name='firstName'
                value={data}
                onChange={(e) => handleType(e)}
            />
            <button onClick={() => handleSubmit()} className="button">Submit</button>{' '}
        </div>
    );
};

export default Eval;
Enter fullscreen mode Exit fullscreen mode

And below is a result of the code snippet
eval result
We use the user's browser and user input to execute a simple alert function and in real life, the attacker can use another javascript malicious code to make something terrible with your webpage, cookies.

href

href is an attribute of an element. The <a> element defines a hyperlink, which is used to link from one page to another.
As an example, we can embed user input inside a href and this is an issue. You can see in the code snippet below, we use a data variable to fill href attribute and data fills with an input element.

import React, { useState } from 'react';

const Href = () => {
    const [data, setData] = useState();
    const handleType = (e) => {
        setData(e.target.value);
    };

    return (
        <div>
            <p>Place this code inside input: <code>javascript: alert('Hacked');</code></p>
            <input
                type='text'
                name='text'
                value={data}
                onChange={(e) => handleType(e)}
            />
            <a href={data} className="button">Click Here</a>
        </div>
    );
};

export default Href;
Enter fullscreen mode Exit fullscreen mode

Execution of code:

href result

dangerouslySetHTML

This is a property in HTML code that you can use HTML elements in react code instead of innerHTML function. The content of dangerouslySetHTML is dynamic and skips the comparison against the virtual DOM. As you can understand it is the third XSS vulnerability. Below is a code and result of execution

import React from 'react';

const DangerouslySetInnerHTML = () => {

    const placeHtml = () => {

        return {

            __html: "<img onerror='alert(\"Hacked!\");' src='invalid-image' />",

        };

    };

    return (

        <div>

            <p>We inserted img inside div using dangerouslySetInnerHTML property and add js code in onerror attribute</p>

            <div dangerouslySetInnerHTML={placeHtml()} />

        </div>

    );

};

export default DangerouslySetInnerHTML;
Enter fullscreen mode Exit fullscreen mode

Result of render:
dangerouslySetHTML result

Simple protection from XSS attacks

You can replace reserved characters (such as < and >) with their respective character entities (&lt; and &gt;).
As a result, the code is rendered, no JavaScript code can't be executed, and character entities will be converted to their respective reserve characters.
Also, you can use “sanitize” user inputs using a library called dompurify.

React XSS protection

As you can see the most vulnerable place is input and we have an article about controlled and uncontrolled components in React documentation.
Below you can read a blockquote from the React official documentation:

In the form elements are either the typed ones like textarea. input or the selected one like radio buttons or checkboxes, whenever there is any change, made it is updated accordingly through some functions that update the state as well.
We recommend using controlled components to implement forms. In a controlled component, form data is handled by a React component.
In HTML, form elements such as , , and typically maintain their own state and update it based on user input. In React, mutable state is typically kept in the state property of components, and only updated with setState().
The alternative is uncontrolled components, where form data is handled by the DOM itself.
To write an uncontrolled component, instead of writing an event handler for every state update, you can use a ref (createRef) to get form values from the DOM.

Summary

Protecting your React application to prevent cross-site scripting is not a one-step process. The best way to protect React applications from XSS attacks is to prevent them earlier in your codebase. You can create a list of recommendations for your teammates.

Here is my list:

  1. Use dangerouslySetHTML and createRef in very specific use cases.
  2. Don't mutate DOM directly as we can make it with React.
  3. Use React functionality instead of writing personal techniques. READ documentation.
  4. Validate all data that you have and income data (from user and from API)
  5. Don't create your personal sanitization libraries, select the best among other libraries from trusted developers.

Top comments (0)