Skip to content

Instantly share code, notes, and snippets.

@Zeelot Zeelot/url.php
Created Aug 29, 2012

Embed
What would you like to do?
Fix for security issue in Kohana 3.0.8 - 3.2.1
<?php defined('SYSPATH') or die('No direct script access.');
// Just use this file in application/classes/url.php for a fix until 3.2.2 is out
class URL extends Kohana_URL {
/**
* Fetches an absolute site URL based on a URI segment.
*
* echo URL::site('foo/bar');
*
* @param string $uri Site URI to convert
* @param mixed $protocol Protocol string or [Request] class to use protocol from
* @param boolean $index Include the index_page in the URL
* @return string
* @uses URL::base
*/
public static function site($uri = '', $protocol = NULL, $index = TRUE)
{
// Chop off possible scheme, host, port, user and pass parts
$path = preg_replace('~^[-a-z0-9+.]++://[^/]++/?~', '', trim($uri, '/'));
if ( ! UTF8::is_ascii($path))
{
// Encode all non-ASCII characters, as per RFC 1738
$path = preg_replace_callback('~([^/]+)~', 'URL::_rawurlencode_callback', $path);
}
// Concat the URL
return URL::base($protocol, $index).$path;
}
/**
* Callback used for encoding all non-ASCII characters, as per RFC 1738
* Used by URL::site()
*
* @param array $matches Array of matches from preg_replace_callback()
* @return string Encoded string
*/
protected static function _rawurlencode_callback($matches)
{
return rawurlencode($matches[0]);
}
}
@bobeagan

This comment has been minimized.

Copy link

commented Aug 31, 2012

The issue starts in 3.0.9, not 3.0.8 I believe. Also, for 3.0.x that is affected I think the site function should look like this:

    /**
     * Fetches an absolute site URL based on a URI segment.
     *
     *     echo URL::site('foo/bar');
     *
     * @param   string  site URI to convert
     * @param   mixed   protocol string or boolean, add protocol and domain?
     * @return  string
     * @uses    URL::base
     */
    public static function site($uri = '', $protocol = FALSE)
    {
        // Chop off possible scheme, host, port, user and pass parts
        $path = preg_replace('~^[-a-z0-9+.]++://[^/]++/?~', '', trim($uri, '/'));

        if ( ! UTF8::is_ascii($path))
        {
            // Encode all non-ASCII characters, as per RFC 1738
            $path = preg_replace('~([^/]+)~e', 'rawurlencode("$1")', $path);
        }

        // Concat the URL
        return URL::base(TRUE, $protocol).$path;
    }
@bobeagan

This comment has been minimized.

Copy link

commented Aug 31, 2012

So I apparently can't comment on gists but I pasted the function that was the original and not the modified. Just need to swap out the preg_replace line with the ~e for the preg_replace_callback line from above.

Change this:

$path = preg_replace('~([^/]+)~e', 'rawurlencode("$1")', $path);

To this:

$path = preg_replace_callback('~([^/]+)~', 'URL::_rawurlencode_callback', $path);
@daGrevis

This comment has been minimized.

Copy link

commented Sep 12, 2012

How is this a security issue? Can you please provide some real life example when something can go wrong?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.