andrew1515
andrew1515

Reputation: 107

How to protect the frontend from XSS, caused by data from a REST API?

I have the following situation:

Lets have a REST API with a POST endpoint, e.g.: POST /users. Then I send the following request body to this endpoint:

{
  "data": {
    "firstname": "<script>alert('John')</script>",
    "lastname": "<script>alert('Doe')</script>"
  }
}

These data are then saved to the users SQL table, to the columns firstname and lastname.

Now I have a simple PHP web application (a classic, non-single page, server side rendered PHP web app), which has access to this users table too. Now when he pulls out the above inserted firstname and lastname and then renders them to a HTML view, the <script> tags will be rendered too, the code between <script> tags will run in the browser, so the alerts will be shown. Obviously, I don't want this, because it is an XSS vulnerability. The question is, what is the right way to avoid this vulnerability:

  1. Sanitize the POST request on the backend - so escape the <script> tags from the data before the data are saved to the DB

or

  1. Don't sanitize the POST request on the backend - so save the data with the <script> tags to the DB as they are. Then when the PHP webapp loads the data from the DB, he should escape the <script> tags before he renders the data to the HTML view.

In my opinion, the second approach is the right approach, because XSS is an issue only for the frontends, however, the REST API endpoints can be called from non-frontend apps too, where the avoiding of the XSS vulnerability with escaping the <script> tags is irrelevant. And maybe, some services will need to get the full HTML code from the backend and not only its escaped version. But what do you think?

Thank you so much!

Upvotes: 2

Views: 1154

Answers (2)

wbrycki
wbrycki

Reputation: 151

You should do BOTH sanitising on the backend (when the data gets stored into your db or another storage layer) and on the frontend as well.

Storing XSS code in the backend is not a common practice, even OWASP XSS Cheatsheet says: "Frameworks make it easy to ensure variables are correctly validated and escaped or sanitised.

However, frameworks aren't perfect and security gaps still exist in popular frameworks like React and Angular. Output Encoding and HTML Sanitization help address those gaps."

The React XSS Protection Guide says: "Validate all data that flows into your application from the server or a third-party API. This cushions your application against an XSS attack, and at times, you may be able to prevent it, as well.:

There are many different reasons for that.

  1. You can start using another UI where XSS checks are not so well implemented (then sanitising already on the backed will definitely help)
  2. There will be an exploit or a backdoor in some future version of your UI Framework (What are the odds? Anyone heard of log4shell?).
  3. Some other apps could start to connect to your db or you may export the data to them (no one would be grateful if such data contains malicious code)
  4. You are using some other web app for builds or log presentation which applies formatting, it will be venerable to those attacks.
  5. There may be potential law problems as in some jurisdictions storing or transmitting malicious code can be against the law.
  6. Storing text in a database. "If it is stored in a database, the developer will have to sanitize that text anyway. It can often save a lot of pain to do both XSS and Structured Query Language (SQL) injection filtering in the same place since the developer must already do SQL Injection filtering upon input".[1]
  7. "There is one other advantage to input encoding. Input encoding can become a central place for all filtering, which ensures there is a single choke point for all of the filtering, rather than many output filter locations"[1]

[1]: “Cross Site Scripting Attacks Xss Exploits and Defence”, page 401, section about input encoding

Upvotes: 0

Evert
Evert

Reputation: 99523

You are right, generally you will want to:

  1. Validate incoming data before storing (for example, is this a real email address?)
  2. Escape right before output

Escaping should always happen right before, because you don't know during your INSERT statement how it should be escaped. Maybe your data only appears in HTML, but perhaps later on you will also want the same data to appear in a .csv export. JSON file, HTTP header, URL. Each format will have their own rules for escaping.

Upvotes: 3

Related Questions