- Don't blindly accept urls from users as they may point to system files. Curl supports many protocols including
FILE
. The following would show the contents offile:///etc/passwd
.
# Attacker.
$ curl https://www.example.com/display_webpage.php?url=file%3A%2F%2F%2Fetc%2Fpasswd
// display_webpage.php
$url = $_GET['url']; // DANGER!
$curl = new Curl();
$curl->get($url);
echo $curl->response;
Safer:
function is_allowed_url($url, $allowed_url_schemes = ['http', 'https']) {
$valid_url = filter_var($url, FILTER_VALIDATE_URL) !== false;
if ($valid_url) {
$scheme = parse_url($url, PHP_URL_SCHEME);
return in_array($scheme, $allowed_url_schemes, true);
}
$valid_ip = filter_var($url, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false;
return $valid_ip;
}
$url = $_GET['url'];
if (!is_allowed_url($url)) {
die('Unsafe url detected.');
}
$curl = new Curl();
$curl->setProtocols(CURLPROTO_HTTPS);
$curl->setRedirectProtocols(CURLPROTO_HTTPS);
$curl->get($url);
-
Url may point to internal urls including those behind a firewall (e.g. http://192.168.0.1/ or ftp://192.168.0.1/). Use a whitelist to allow certain urls rather than a blacklist.
-
Use
Curl::setProtocols()
andCurl::setRedirectProtocols()
to restrict allowed protocols.
// Allow only HTTPS protocols.
$curl->setProtocols(CURLPROTO_HTTPS);
$curl->setRedirectProtocols(CURLPROTO_HTTPS);
// Allow HTTPS and HTTP protocols.
$curl->setProtocols(CURLPROTO_HTTPS | CURLPROTO_HTTP);
$curl->setRedirectProtocols(CURLPROTO_HTTPS | CURLPROTO_HTTP);
- Request data prefixed with the
@
character may have special interpretation and read from system files.
# Attacker.
$ curl https://www.example.com/upload_photo.php --data "photo=@/etc/passwd"
// upload_photo.php
$curl = new Curl();
$curl->post('http://www.anotherwebsite.com/', [
'photo' => $_POST['photo'], // DANGER!
]);
- Requests with redirection enabled may return responses from unexpected sources. Downloading https://www.example.com/image.png may redirect and download https://www.evil.com/virus.exe
$curl = new Curl();
$curl->setOpt(CURLOPT_FOLLOWLOCATION, true); // DANGER!
$curl->download('https://www.example.com/image.png', 'my_image.png');
$curl = new Curl();
$curl->setOpt(CURLOPT_FOLLOWLOCATION, true); // DANGER!
$curl->get('https://www.example.com/image.png');
- Do not disable SSL protections.
curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false); // DANGER!
curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false); // DANGER!
- Set the following when using the default PHP XML parser to prevent XML external entity injection.
libxml_disable_entity_loader(true);
PHP files in this library are not intended to be accessible by users browsing websites. Prevent direct access to library files by moving the library folder at least one level higher than the web root directory. Alternatively, configure the server to disable php file execution for all library files.
WordPress plugin developers that wish to incorporate the PHP Curl Class library into their plugin, should take special care to include only the "core" library files.
Do one of the following:
Option 1. Download an official release from the releases page and incorporate the files contained in the compressed file into the plugin. The releases include only the necessary php files for the library to function.
Option 2. Manually copy only the src/ directory into your plugin. Be sure not to copy any other php files as they may be executable by users visiting the php files directly.