Relative Path Overwrite

Relative Path Overwrite (RPO) is a technique where an attacker can overwrite the target file of a relative URL. If there is any data on the page that the attacker can control, they can inject malicious CSS.

What can happen?

As with many other vulnerabilities, the risks involved vary from case to case. If the vulnerable page contains any data under the attacker's control, it’s possible to inject CSS, which in turn enables the attacker to trick the victim into carrying out unwanted actions.

If it’s possible to get JavaScript within CSS, it’s also possible to turn this into an XSS. Read more about XSS here.

Example of Relative Path Overwrite

There is a page called friend.php located at https://example.com/friend.php. Due to a popular feature in many frameworks, the very same page may be accessed at https://example.com/friend.php/anything.

The page (friend.php) contains the following code:

<html>
<head>
<link href="style.css" rel="stylesheet" type="text/css" />
</head>
<body>
    Hi, my name is <?php echo $name; ?>.
    Press the green button below to friend me and the red to cancel.
    
    <button id=”green”>...</button>
    <button id=”red”>...</button>
</body>
</html>

When accessing the page through https://example.com/friend.php, the included stylesheet will be loaded from https://example.com/style.css. If the page is loaded through https://example.com/friend.php/anything instead, the stylesheet will be loaded from https://example.com/friend.php/style.css.

As stated before, the URL router on the server side will ignore everything after friend.php/ and the included stylesheet will therefore be loaded from the page itself. By changing the name on a vulnerable social network, the attacker can control the value of $name and, consequently, the stylesheet.

The browser will ignore the fact that the document has the header “Content-Type: text/html”. For this to work, the page’s doctype needs to be missing, as the browser won’t consider it a CSS otherwise.

We can get valid CSS within the HTML page by putting “{}” in front of the CSS, so the result is this:

$name = "{}#green{background-color:red;}#red{background-color:green;}";

The button intended to be green is now red, and vice versa. The victim will unknowingly accept the friend request from the attacker.

Remediation

Instead of a relative path you have to use one of the following path types:

Absolute URL

<link href="//example.com/styles.css" rel="stylesheet" type="text/css" />

This will load the file from the given URL over the current protocol. If the page is loaded over HTTP, the file will be loaded over HTTP, and the same thing with HTTPS.

Network location

<link href="https://example.com/styles.css" rel="stylesheet" type="text/css" />

It loads the given URL, including the protocol, without any strange behaviors.

Absolute Path

<link href="/styles.css" rel="stylesheet" type="text/css" />

This will append the requested file to the current domain. It will result in https://example.com/style.css as the domain + protocol in question is https://example.com and the wanted file is style.css.

Resources

Related articles