src/Url.php
public function checkForOpenRedirect( $urlForTestContents, $testContents, $useAsRegex = false )
   {

      if ( \count( $this->openRedirectionURLs ) < 1 )
      {
         // If no open redirection URLs was found by isPossibleOpenRedirect(…) we are already done here
         return false;
      }

      // Remember the current query parameters
      $oldQuery = $this->query;

      // Getting the query keys
      $keys = \array_keys( $this->openRedirectionURLs );

      // Loop the query keys and assign the replacement url to this query
      foreach ( $keys as $key )
      {
         $this->query[ $key ] = $urlForTestContents;
      }

      // Adjust get_headers() to send a HEAD request
      \stream_context_set_default(
         array(
            'http' => array( 'method' => 'HEAD' )
         )
      );

      // Getting th URL string to call
      $url = (string) $this;

      // Init state flag
      $handleHeaders = true;

      // OK now we can reassign the origin headers
      $this->query = $oldQuery;

      if ( false === ( $headers = \get_headers( $url, 1 ) ) )
      {

         // If the head request fails get headers from GET request
         \stream_context_set_default(
            array(
               'http' => array( 'method' => 'GET' )
            )
         );

         // Get header by GET request
         if ( false === ( $headers = \get_headers( $url, 1 ) ) )
         {
            $handleHeaders = false;
         }

      }
      else
      {

         // reset get_header to use defaut GET request
         \stream_context_set_default(
            array(
               'http' => array( 'method' => 'GET' )
            )
         );

      }

      if ( $handleHeaders && \count( $headers ) > 0 )
      {
         // There are usable headers in response, handle it

         // Make header keys to lower case
         $headers = \array_change_key_case( $headers, \CASE_LOWER );

         if ( isset( $headers[ 'location' ] ) && ( $urlForTestContents === $headers[ 'location' ] ) )
         {
            // Location header to defined URL is defined. Now we know its a open redirection bug usage
            return true;
         }

         if ( isset( $headers[ 'refresh' ] ) && \Niirrty\strContains( $headers[ 'refresh' ], $urlForTestContents ) )
         {
            // Refresh header to defined URL is defined. Now we know its a open redirection bug usage
            return true;
         }

      }

      // We can not work with headers because they dont gives us the required informations.

      // Get the data from URL to check
      $resultContents = \file_get_contents( $url );
      if ( $useAsRegex )
      {
         try { return (bool) \preg_match( $testContents, $resultContents ); }
         catch ( \Throwable $ex ) { unset( $ex ); }
      }

      $regex = '~<meta\s+http-equiv=(\'|")?refresh(\'|")?\s+content=(\'|")\d+;\s*url='
         . \preg_quote( $url )
         . '~i';

      if ( \preg_match( $regex, $resultContents ) )
      {
         return true;
      }

      return $testContents === $resultContents;

   }
public function checkForOpenRedirect( $urlForTestContents, $testContents, $useAsRegex = false )
   {

      if ( \count( $this->openRedirectionURLs ) < 1 )
      {
         // If no open redirection URLs was found by isPossibleOpenRedirect(…) we are already done here
         return false;
      }

      // Remember the current query parameters
      $oldQuery = $this->query;

      // Getting the query keys
      $keys = \array_keys( $this->openRedirectionURLs );

      // Loop the query keys and assign the replacement url to this query
      foreach ( $keys as $key )
      {
         $this->query[ $key ] = $urlForTestContents;
      }

      // Adjust get_headers() to send a HEAD request
      \stream_context_set_default(
         array(
            'http' => array( 'method' => 'HEAD' )
         )
      );

      // Getting th URL string to call
      $url = (string) $this;

      // Init state flag
      $handleHeaders = true;

      // OK now we can reassign the origin headers
      $this->query = $oldQuery;

      if ( false === ( $headers = \get_headers( $url, 1 ) ) )
      {

         // If the head request fails get headers from GET request
         \stream_context_set_default(
            array(
               'http' => array( 'method' => 'GET' )
            )
         );

         // Get header by GET request
         if ( false === ( $headers = \get_headers( $url, 1 ) ) )
         {
            $handleHeaders = false;
         }

      }
      else
      {

         // reset get_header to use defaut GET request
         \stream_context_set_default(
            array(
               'http' => array( 'method' => 'GET' )
            )
         );

      }

      if ( $handleHeaders && \count( $headers ) > 0 )
      {
         // There are usable headers in response, handle it

         // Make header keys to lower case
         $headers = \array_change_key_case( $headers, \CASE_LOWER );

         if ( isset( $headers[ 'location' ] ) && ( $urlForTestContents === $headers[ 'location' ] ) )
         {
            // Location header to defined URL is defined. Now we know its a open redirection bug usage
            return true;
         }

         if ( isset( $headers[ 'refresh' ] ) && \Niirrty\strContains( $headers[ 'refresh' ], $urlForTestContents ) )
         {
            // Refresh header to defined URL is defined. Now we know its a open redirection bug usage
            return true;
         }

      }

      // We can not work with headers because they dont gives us the required informations.

      // Get the data from URL to check
      $resultContents = \file_get_contents( $url );
      if ( $useAsRegex )
      {
         try { return (bool) \preg_match( $testContents, $resultContents ); }
         catch ( \Throwable $ex ) { unset( $ex ); }
      }

      $regex = '~<meta\s+http-equiv=(\'|")?refresh(\'|")?\s+content=(\'|")\d+;\s*url='
         . \preg_quote( $url )
         . '~i';

      if ( \preg_match( $regex, $resultContents ) )
      {
         return true;
      }

      return $testContents === $resultContents;

   }
public function checkForOpenRedirect ( $ urlForTestContents , $ testContents , $ useAsRegex = false ) { if ( \ count ( $ this -> openRedirectionURLs ) < 1 ) { // If no open redirection URLs was found by isPossibleOpenRedirect(…) we are already done here return false ; } // Remember the current query parameters $ oldQuery = $ this -> query ; // Getting the query keys $ keys = \ array_keys ( $ this -> openRedirectionURLs ) ; // Loop the query keys and assign the replacement url to this query foreach ( $ keys as $ key ) { $ this -> query [ $ key ] = $ urlForTestContents ; } // Adjust get_headers() to send a HEAD request \ stream_context_set_default ( array ( 'http' => array ( 'method' => 'HEAD' ) ) ) ; // Getting th URL string to call $ url = ( string ) $ this ; // Init state flag $ handleHeaders = true ; // OK now we can reassign the origin headers $ this -> query = $ oldQuery ; if ( false === ( $ headers = \ get_headers ( $ url , 1 ) ) ) { // If the head request fails get headers from GET request \ stream_context_set_default ( array ( 'http' => array ( 'method' => 'GET' ) ) ) ; // Get header by GET request if ( false === ( $ headers = \ get_headers ( $ url , 1 ) ) ) { $ handleHeaders = false ; } } else { // reset get_header to use defaut GET request \ stream_context_set_default ( array ( 'http' => array ( 'method' => 'GET' ) ) ) ; } if ( $ handleHeaders && \ count ( $ headers ) > 0 ) { // There are usable headers in response, handle it // Make header keys to lower case $ headers = \ array_change_key_case ( $ headers , \ CASE_LOWER ) ; if ( isset ( $ headers [ 'location' ] ) && ( $ urlForTestContents === $ headers [ 'location' ] ) ) { // Location header to defined URL is defined. Now we know its a open redirection bug usage return true ; } if ( isset ( $ headers [ 'refresh' ] ) && \ Niirrty \ strContains ( $ headers [ 'refresh' ] , $ urlForTestContents ) ) { // Refresh header to defined URL is defined. Now we know its a open redirection bug usage return true ; } } // We can not work with headers because they dont gives us the required informations. // Get the data from URL to check $ resultContents = \ file_get_contents ( $ url ) ; if ( $ useAsRegex ) { try { return ( bool ) \ preg_match ( $ testContents , $ resultContents ) ; } catch ( \ Throwable $ ex ) { unset ( $ ex ) ; } } $ regex = '~<meta\s+http-equiv=(\'|")?refresh(\'|")?\s+content=(\'|")\d+;\s*url=' . \ preg_quote ( $ url ) . '~i' ; if ( \ preg_match ( $ regex , $ resultContents ) ) { return true ; } return $ testContents === $ resultContents ; }
Checks, if possible open redirection bug URLs are defined, if one of it its a real open redirection usage.

Attention. It sends a real request to each URL. Do'nt use it inside you're main web application because it
blocks it as long if it gets a answer. Maybe better use it in cron jobs or inside a very low frequenced area!

How it works is easy. All you need is a url and its well known output.

If we replace the possible redirection URL inside the current url with the URL where we know the output and
it redirects to the url with the known output, the bug is used.

@param  string  $urlForTestContents The URL with the known output
@param  string  $testContents       The known output of $urlForTestContents (or a regex if $useAsRegex is TRUE)
@param  boolean $useAsRegex         Should $testContents be used as a regular expression?
@return boolean
Checks if possible open redirection bug URLs are defined if one of it its a real open redirection usage .