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
Welcome back! If you're the original bug submitter, here's where you can edit the bug or add additional notes.
If you forgot your password, you can retrieve your password here.
Password:
Status:
Package:
Bug Type:
Summary:
From: a dot nadelle92 at gmail dot com
New email:
PHP Version: OS:

 

 [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

Pull Requests

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: Sat Dec 21 17:01:58 2024 UTC