Introduction

In our previous courses, we took a deep dive into client-side validation when working on the user registration feature. However, it’s crucial to note that client-side validation can be bypassed with tools like cURL. cURL (short for “Client URL”) is a command-line utility used to transfer data to and from servers. It offers a straightforward way to send customized HTTP requests without relying on browser-based checks. Attackers can leverage cURL to deliberately circumvent client-side restrictions, emphasizing the importance of robust server-side validation. Let’s now shift our focus to the snippets part of our application and demonstrate secure server-side validation using TypeScript.

Understanding Server-Side Validation

Server-side validation is your final gatekeeper to ensure that data is clean and meets the expected requirements. Even if malicious users bypass client-side checks, robust server-side validation will stop unsafe or malformed data from compromising your application. TypeScript’s strict typing, combined with libraries like Zod, offers a structured way to define and enforce these rules.

Vulnerable Code Example

Below is a snippet of our “save snippet” endpoint. Currently, there is no server-side validation in place to verify the data contained in the request body:

Since the snippet is directly created from user input, attackers could insert malicious data (e.g., harmful scripts) into these fields.

Gaining the Token

To interact with protected endpoints like the "save snippet" endpoint, users must first obtain a JSON Web Token (JWT) by logging into the application. JWT is a compact, URL-safe means of representing claims to be transferred between two parties. It is commonly used for authentication and information exchange. In our application, we have implemented JWT support to handle user authentication. This token is crucial for authenticating requests and ensuring that the server can verify the user's identity and permissions. Without it, requests will be rejected as unauthenticated.

To obtain the JWT, you can use the following cURL command to send a login request to the endpoint:

Replace "someusername" and "somepassword" with valid credentials stored in your database. If the credentials are correct, the server will respond with a JSON object containing the token:

This token must be included in the "Authorization" header of subsequent requests to protected endpoints, such as when creating new snippets:

Exploiting the Vulnerability

Even with the correct token, the lack of server-side validation allows attackers to exploit the endpoint. Using cURL, they can bypass client-side validation and send raw requests with malicious payloads:

This request, despite being authenticated, can inject harmful scripts into the application. Without proper server-side validation, these payloads could be stored or rendered elsewhere, leading to cross-site scripting (XSS) or other injection-based exploits. This highlights the critical need for robust server-side validation to protect against such vulnerabilities.

Summary

In this lesson, we explored the importance of server-side validation to protect web applications from attacks. We highlighted the limitations of client-side validation, which can be bypassed using tools like cURL. We examined a vulnerable code example where the lack of server-side validation in a "save snippet" endpoint could allow attackers to inject malicious data. We also discussed the role of JSON Web Tokens (JWT) in authenticating requests to protected endpoints. Finally, we demonstrated how attackers could exploit the vulnerability by sending raw requests with harmful payloads, emphasizing the need for robust server-side validation to prevent such exploits.

Sign up
Join the 1M+ learners on CodeSignal
Be a part of our community of 1M+ users who develop and demonstrate their skills on CodeSignal