On-Site Request Forgery (OSRF): A Forgotten Client-Side Attack

On-Site Request Forgery (OSRF): A Forgotten Client-Side Attack

Introduction

On-Site Request Forgery (OSRF) is an older vulnerability that often goes unrecognized. It is similar to Cross-Site Request Forgery (CSRF) in that an attacker can force a user’s web browser to make requests on the attacker’s behalf.

The key difference is the origin of the request:

  • In CSRF, the malicious request is initiated from an attacker-controlled external site (e.g., attacker.com).
  • In OSRF, the malicious request is initiated from the target application itself (e.g., target.com).

The root cause of this vulnerability is the application using unsanitized user-supplied input to construct an internal HTTP request or path used by the browser.


Understanding and Exploiting OSRF

When first encountering OSRF, it can feel very similar to Cross-Site Scripting (XSS) because it often involves injecting data into an HTML element.

Consider the following example of a vulnerable application. The goal for an attacker is to force the user’s browser to send a request to the sensitive endpoint /admin/add. This action is assumed to create a new admin user that the attacker could then use to log into the victim’s application.

The vulnerable code snippet shows that user input, passed via vuln_param, is used directly to create the src attribute of an image tag: .

If an attacker could break out of the single quotes here, it would be an XSS vulnerability. However, even if we assume the input is sufficiently sanitized to prevent XSS (i.e., we cannot break out of the quotes), OSRF may still be possible.

The attacker’s goal is to construct the following request in the user’s browser:

127.0.0.1/admin/add?username=ghost&password=lulz

This request is intended to create a new admin user named “ghost” with the password “lulz”.

Step 1: Path Traversal

Let’s look closely at how the vuln_param creates the final path for the image source. The path starts as images/.

What if an attacker were to input ../../ for the vuln_param?

  • Original Path: /images/
  • Input: ../../
  • Resulting Path: /images/../../

The ../ characters are a path traversal technique that tells the server (or in this case, the browser resolving the path) to go back one directory.

  • images/ is the current directory.
  • ../ moves back from images/ to /.
  • The second ../ moves back from / one more level, which often wraps around or simply resolves to the root directory (/).

[Image showing the browser resolving the path traversal input ../../ to the root path /]

By using path traversal, the browser sends a GET request to the path / instead of the intended /images.

Step 2: Targeting the Admin Endpoint

Now that the attacker can navigate up the directory structure, the next step is to target the sensitive admin endpoint.

The attacker sets vuln_param to: ../admin/add.jpg

  • Original Path: /images/
  • Input: ../admin/add.jpg
  • Resulting Path: /images/../admin/add.jpg

This path resolves to /admin/add.jpg.

[Image showing the browser making a request to /admin/add.jpg]

The browser is now making a request to /admin/add.jpg. If the sensitive endpoint is accessible via a GET request and requires no CSRF token, we can proceed to add the user parameters.

Step 3: Injecting Parameters and Handling URL Encoding

The attacker now constructs the full payload to add the new user. The request is formed by appending parameters to the path:

  • Input: ../admin/add?username=ghost&password=lulz

However, when sending multiple parameters via an injected URL, we must URL encode the ampersand (&) character as %26. If we do not encode it, the browser will assume the & belongs to the first resource request and won’t be passed as a full parameter string to the /admin/add endpoint.

Additionally, because the original code appends .jpg to the end of the input, the password in the URL would become password=lulz.jpg, which is not the desired password. To neutralize this unwanted suffix, the attacker can simply add a dummy parameter at the end:

  • Final Payload (URL Encoded):http://127.0.0.1:5000/?vuln_param=../../admin/add?username=ghost%26password=lulz%26dummy_param=

This final payload successfully achieves the goal: it makes the user’s browser send a request to the /admin/add endpoint, causing the application to add a new user named “ghost” with the password “lulz”.

Since this request is initiated from the user’s browser while they are authenticated, it will contain all the user’s necessary authentication cookies, the application’s Origin header, and other relevant details, making it appear as a legitimate, authorized request.


Summary

If a security tester is able to control part of the URL path used to make an HTTP request within the target application, they likely have OSRF.

To confirm, try injecting the ../ characters, which should cause the browser or server to resolve the path one directory up. If path traversal is possible, you almost certainly have OSRF; you just need to find an interesting and sensitive endpoint to call.

OSRF is a relatively old vulnerability that is often overlooked. It’s surprisingly easy for developers to accidentally implement this vulnerability, and because it is often chained with the victim’s authentication context, it makes OSRF a fairly dangerous and high-impact bug.

Total
1
Shares

Leave a Reply

Previous Post
Server-Side Template Injection (SSTI): Exploiting the Backend View

Server-Side Template Injection (SSTI): Exploiting the Backend View

Next Post
Prototype Pollution: Poisoning the JavaScript Object Chain

Prototype Pollution: Poisoning the JavaScript Object Chain

Related Posts