php.net |  support |  documentation |  report a bug |  advanced search |  search howto |  statistics |  random bug |  login
Bug #76566 curl fails to connect to the right host
Submitted: 2018-07-02 19:35 UTC Modified: 2018-07-03 03:37 UTC
From: a dot nadelle92 at gmail dot com Assigned:
Status: Not a bug Package: cURL related
PHP Version: 7.1Git-2018-07-02 (Git) OS: Irrelevant
Private report: No CVE-ID: None
 [2018-07-02 19:35 UTC] a dot nadelle92 at gmail dot com
Description:
------------
Hi,

When putting this link 

http://jx$(Tqz*Rn9d~@www.example.com:+@www.google.com

to parse_url() function, the host is www.google.com.
Nevertheless, when trying to connect with curl it connects to www.example.com .
I discovered this bug since I was able to bypass hostname filtering and I could do a Server Side Request Forgery.
I tested version 7.1.18, I didn't test the latest one but I do not see a report for such bug. Perhaps, they may be vulnerable the same.

Test script:
---------------
<?php
	/**
     * Get a web file (HTML, XHTML, XML, image, etc.) from a URL.  Return an
     * array containing the HTTP server response header fields and content.
     */
    $url = "http://jx$(Tqz*Rn9d~@www.example.com:+@www.google.com";
    var_dump(parse_url($url));
    function get_web_page( $url )
    {
        $user_agent='Mozilla/5.0 (Windows NT 6.1; rv:8.0) Gecko/20100101 Firefox/8.0';

        $options = array(

            CURLOPT_CUSTOMREQUEST  => "GET",        //set request type post or get
            CURLOPT_POST           => false,        //set to GET
            CURLOPT_USERAGENT      => $user_agent, //set user agent
            CURLOPT_RETURNTRANSFER => true,     // return web page
            CURLOPT_HEADER         => false,    // don't return headers
            CURLOPT_FOLLOWLOCATION => true,     // follow redirects
            CURLOPT_ENCODING       => "",       // handle all encodings
            CURLOPT_AUTOREFERER    => false,     // set referer on redirect
            CURLOPT_CONNECTTIMEOUT => 120,      // timeout on connect
            CURLOPT_TIMEOUT        => 120,      // timeout on response
            CURLOPT_MAXREDIRS      => 2,       // stop after 10 redirects
			CURLOPT_HTTPHEADER     => array("Cookie: ".base64_decode($_REQUEST['cookie']))
        );

        $ch      = curl_init( $url );
        curl_setopt_array( $ch, $options );
        $content = curl_exec( $ch );
        $err     = curl_errno( $ch );
        $errmsg  = curl_error( $ch );
        $header  = curl_getinfo( $ch );
        curl_close( $ch );

        $header['errno']   = $err;
        $header['errmsg']  = $errmsg;
        $header['content'] = $content;
        return $header;
    }
	
	$result = get_web_page( $url );

	if ( $result['errno'] != 0 )
	{
		echo "strange_error ".$result['errno'];
	}

	if ( $result['http_code'] == 200 )
	{
		echo $result['content'];
	}
	else
	{
		echo $result['http_code'];
	} 
?>

Expected result:
----------------
curl connecting to the same host as parse_url() function

Actual result:
--------------
curl is not connecting to the same host as parse_url() function

Patches

Add a Patch

Pull Requests

Add a Pull Request

History

AllCommentsChangesGit/SVN commitsRelated reports
 [2018-07-03 03:37 UTC] requinix@php.net
-Status: Open +Status: Not a bug -Package: HTTP related +Package: cURL related
 [2018-07-03 03:37 UTC] requinix@php.net
Chrome thinks your URL goes to google.com too. Edge refuses to follow a link with it for some unknown but probably stupid reason. The URL doesn't even look valid to me. So from where I stand, cURL is the odd one out.

But we don't control cURL. You'll need to report the problem to them and see what they say about it.
 [2018-07-03 04:11 UTC] a dot nadelle92 at gmail dot com
Hi,

The link is valid. I was able to perform a SSRF to a php based web application.
What they were doing is:

1) check that the host is not internal with parse_url()
2) connect to the host (using the link provided in input) with curl

Since there is a discrepancy between parse_url() and curl, I was able to ping the local network and bypass the parse_url() check. I assume curl is the broken one, since as you said Chrome connected to www.google.com instead of www.example.com

I just contacted the security team of curl, let's see what they say.
 
PHP Copyright © 2001-2024 The PHP Group
All rights reserved.
Last updated: Thu Apr 18 03:01:28 2024 UTC