public function testRemoteWebResource() { $map = array('http://example.com/' => true, 'derp://example.com/' => false, 'javascript:alert(1)' => false); foreach ($map as $uri => $expect) { $this->assertEqual($expect, PhabricatorEnv::isValidRemoteWebResource($uri), "Valid remote resource: {$uri}"); } }
public function render() { $account = $this->externalAccount; $provider = $this->provider; require_celerity_resource('auth-css'); $content = array(); $dispname = $account->getDisplayName(); $username = $account->getUsername(); $realname = $account->getRealName(); $use_name = null; if (strlen($dispname)) { $use_name = $dispname; } else { if (strlen($username) && strlen($realname)) { $use_name = $username . ' (' . $realname . ')'; } else { if (strlen($username)) { $use_name = $username; } else { if (strlen($realname)) { $use_name = $realname; } else { $use_name = $account->getAccountID(); } } } } $content[] = phutil_tag('div', array('class' => 'auth-account-view-name'), $use_name); if ($provider) { $prov_name = pht('%s Account', $provider->getProviderName()); } else { $prov_name = pht('"%s" Account', $account->getProviderType()); } $content[] = phutil_tag('div', array('class' => 'auth-account-view-provider-name'), array($prov_name, " · ", $account->getAccountID())); $account_uri = $account->getAccountURI(); if (strlen($account_uri)) { // Make sure we don't link a "javascript:" URI if a user somehow // managed to get one here. if (PhabricatorEnv::isValidRemoteWebResource($account_uri)) { $account_uri = phutil_tag('a', array('href' => $account_uri, 'target' => '_blank'), $account_uri); } $content[] = phutil_tag('div', array('class' => 'auth-account-view-account-uri'), $account_uri); } $image_uri = $account->getProfileImageFile()->getProfileThumbURI(); return phutil_tag('div', array('class' => 'auth-account-view', 'style' => 'background-image: url(' . $image_uri . ')'), $content); }
/** * See http://tools.ietf.org/html/draft-ietf-oauth-v2-23#section-3.1.2 * for details on what makes a given redirect URI "valid". */ public function validateRedirectURI(PhutilURI $uri) { if (PhabricatorEnv::isValidRemoteWebResource($uri)) { if ($uri->getFragment()) { return false; } if ($uri->getDomain()) { return true; } } return false; }
/** * Format a URI for use in a "Location:" header. * * Verifies that a URI redirects to the expected type of resource (local or * remote) and formats it for use in a "Location:" header. * * The HTTP spec says "Location:" headers must use absolute URIs. Although * browsers work with relative URIs, we return absolute URIs to avoid * ambiguity. For example, Chrome interprets "Location: /\evil.com" to mean * "perform a protocol-relative redirect to evil.com". * * @param string URI to redirect to. * @param bool True if this URI identifies a remote resource. * @return string URI for use in a "Location:" header. */ public static function getURIForRedirect($uri, $is_external) { $uri_object = new PhutilURI($uri); if ($is_external) { // If this is a remote resource it must have a domain set. This // would also be caught below, but testing for it explicitly first allows // us to raise a better error message. if (!strlen($uri_object->getDomain())) { throw new Exception(pht('Refusing to redirect to external URI "%s". This URI ' . 'is not fully qualified, and is missing a domain name. To ' . 'redirect to a local resource, remove the external flag.', (string) $uri)); } // Check that it's a valid remote resource. if (!PhabricatorEnv::isValidRemoteWebResource($uri)) { throw new Exception(pht('Refusing to redirect to external URI "%s". This URI ' . 'is not a valid remote web resource.', (string) $uri)); } } else { // If this is a local resource, it must not have a domain set. This allows // us to raise a better error message than the check below can. if (strlen($uri_object->getDomain())) { throw new Exception(pht('Refusing to redirect to local resource "%s". The URI has a ' . 'domain, but the redirect is not marked external. Mark ' . 'redirects as external to allow redirection off the local ' . 'domain.', (string) $uri)); } // If this is a local resource, it must be a valid local resource. if (!PhabricatorEnv::isValidLocalWebResource($uri)) { throw new Exception(pht('Refusing to redirect to local resource "%s". This URI is not ' . 'formatted in a recognizable way.', (string) $uri)); } // Fully qualify the result URI. $uri = PhabricatorEnv::getURI((string) $uri); } return (string) $uri; }