[security] Request splitting/SSRF in php-openid

isciurus isciurus at gmail.com
Fri Dec 26 00:59:20 UTC 2014


Hi,

php-openid library treats %0A/%0D characters in hostname of an openid
endpoint URL as valid and decodes them into special characters \r\n right
before making a discovery request to that location. When it uses curl to
make web requests, and I guess this is a recommended way, libcurl passes
these invalid URLs to the TCP stream in certain cases, for example, when it
is configured to work through proxy. With this discovery logic php-openid
allows to craft arbitrary requests inside the org network or to a loopback
server interface, which exposes the infrastructure to the outside and is
quite bad.

For some reason, hostnames are converted in an unsafe way:
https://github.com/openid/php-openid/blob/0ef9be71c1ff6114d04bc93d5156c00b25653a1b/Auth/OpenID/URINorm.php#L205

  function Auth_OpenID_pct_encoded_replace($mo)
  {
      return chr(intval($mo[1], 16));
  }
  ...
  if (strpos($host, '%') !== -1) {
      $host = strtolower($host);
      $host = preg_replace_callback(
                Auth_OpenID_getEncodedPattern(),
                'Auth_OpenID_pct_encoded_replace', $host);       //
<------------

..in contrast with path:

  function Auth_OpenID_pct_encoded_replace_unreserved($mo)
  {
      $_unreserved = Auth_OpenID_getUnreserved();
      $i = intval($mo[1], 16);
      if ($_unreserved[$i]) {
          return chr($i);
      } else {
          return strtoupper($mo[0]);
      }
      return $mo[0];
  }
  ...
  $path = preg_replace_callback(
         Auth_OpenID_getEncodedPattern(),
         'Auth_OpenID_pct_encoded_replace_unreserved', $path);  //
<----------


Please, have a look at the attached diff, this should resolve the problem.

Thanks,
Andrey Labunets
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.openid.net/pipermail/openid-security/attachments/20141225/96cb5922/attachment.html>
-------------- next part --------------
Index: php-openid/Auth/OpenID/URINorm.php
===================================================================
--- php-openid/Auth/OpenID/URINorm.php
+++ php-openid/Auth/OpenID/URINorm.php
@@ -93,7 +93,17 @@
 
 function Auth_OpenID_pct_encoded_replace($mo)
 {
-    return chr(intval($mo[1], 16));
+    $code = intval($mo[1], 16);
+
+    // Prevent request splitting by ignoring newline and space characters
+    if($code === 0xA || $code === 0xD || $code === ord(' '))
+    {
+      return $mo[0];
+    }
+    else
+    {
+      return chr($code);
+    }
 }


More information about the security mailing list