Skip to content

esc_url_raw misleading documentation, security/SSRF risk #1129

@mal-tee

Description

@mal-tee

Issue Description

The documentation for the URL sanitizer function "esc_url_raw" (https://developer.wordpress.org/reference/functions/esc_url_raw/) states that "The resulting URL is safe to use in database queries, redirects and HTTP requests.".

This is untrue! The output can not be used for HTTP requests, otherwise devs will introduce a Server-Side-Request Forgery vulnerability in their code!

A proper defense would require a lot more checks than those provided by this function, i.e. proper allow listing, DNS pinning, etc.

Furthermore, since the function defaults to wp_allowed_protocols(), a lot of protocols are allowed. There is also no validation on the host or query components. Since gopher is allowed by default, attackers can use it to smuggle content to other protocols like SMTP, see e.g. https://www.silentrobots.com/ssrf-protocol-smuggling-in-plaintext-credential-handlers-ldap/

URL of the Page with the Issue

https://developer.wordpress.org/reference/functions/esc_url_raw/

Section of Page with the issue

https://developer.wordpress.org/reference/functions/esc_url_raw/#more-information

Why is this a problem?

I've encountered applications using this function as the only sanitization step for a HTTP request. This makes them vulnerable.

PoC

nc -l 22
<?php
require_once('wp-load.php');

$result = esc_url_raw("https://fbi.com:22/maliciousdata");
echo $result;
file_get_contents($result);
  1. Execute the script and observer that a request is made to localhost on port 22.

As of today fbi.com resolves to localhost. I.e. this request hits localhost. If something is running on localhost it can be accessed through PHP/Wordpress, even if a firewall shields it from the outside.

Please note that this is a very simple PoC to prove that the sanitize function is unable to sanitize against SSRF attacks and therefore should not be recommended for the HTTP request use case. A real exploit depends on the type of attack an attacker wants to perform/which services he wants to exploit on the internal network.

Suggested Fix

Metadata

Metadata

Assignees

Labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions