Skip to content

Massive security vulnerability with Autoloaders  #6

@nickl-

Description

@nickl-

This is huge!!!

Makes XSS and SQLI seem like way too much effort in comparison.

Exploit: PHP include & require exposes the current context to the included file.

i.o.w. you have unrestricted access to $this == (the autoloader instance) from within the include

HOWTO:

Add the following inside a file which will be included by the autoloader

<?php
     echo "<h2>Reflection knows:</h2><pre>",  \ReflectionObject::export($this, true),  "</pre>";

Result:

from using Symfony's UniversalClassLoader, for example, but same goes for any other autoloader as I have not seen one with even the slightest consideration for this vulnerability:

Reflection knows:

<?php
/**
 * UniversalClassLoader implements a "universal" autoloader for PHP 5.3.
 *
 * It is able to load classes that use either:
 *
 *  * The technical interoperability standards for PHP 5.3 namespaces and
 *    class names (https://github.com/php-fig/fig-standards/blob/master/accepted/PSR-0.md);
 *
 *  * The PEAR naming convention for classes (http://pear.php.net/).
 *
 * Classes from a sub-namespace or a sub-hierarchy of PEAR classes can be
 * looked for in a list of locations to ease the vendoring of a sub-set of
 * classes for large projects.
 *
 * Example usage:
 *
 *     $loader = new UniversalClassLoader();
 *
 *     // register classes with namespaces
 *     $loader->registerNamespaces(array(
 *         'Symfony\Component' => __DIR__.'/component',
 *         'Symfony'           => __DIR__.'/framework',
 *         'Sensio'            => array(__DIR__.'/src', __DIR__.'/vendor'),
 *     ));
 *
 *     // register a library using the PEAR naming convention
 *     $loader->registerPrefixes(array(
 *         'Swift_' => __DIR__.'/Swift',
 *     ));
 *
 *
 *     // to enable searching the include path (e.g. for PEAR packages)
 *     $loader->useIncludePath(true);
 *
 *     // activate the autoloader
 *     $loader->register();
 *
 * In this example, if you try to use a class in the Symfony\Component
 * namespace or one of its children (Symfony\Component\Console for instance),
 * the autoloader will first look for the class under the component/
 * directory, and it will then fallback to the framework/ directory if not
 * found before giving up.
 *
 * @author Fabien Potencier 
 *
 * @api
 */
Object of class [  class Symfony\Component\ClassLoader\UniversalClassLoader ] {
  @@ /path/to/src/ClassLoader/UniversalClassLoader.php 61-319

  - Constants [0] {
  }

  - Static properties [0] {
  }

  - Static methods [0] {
  }

  - Properties [5] {
    Property [  private $namespaces ]
    Property [  private $prefixes ]
    Property [  private $namespaceFallbacks ]
    Property [  private $prefixFallbacks ]
    Property [  private $useIncludePath ]
  }

  - Dynamic properties [0] {
  }

  - Methods [17] {
    /**
     * Turns on searching the include for class files. Allows easy loading
     * of installed PEAR packages
     *
     * @param Boolean $useIncludePath
     */
    Method [  public method useIncludePath ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 75 - 78

      - Parameters [1] {
        Parameter #0 [  $useIncludePath ]
      }
    }

    /**
     * Can be used to check if the autoloader uses the include path to check
     * for classes.
     *
     * @return Boolean
     */
    Method [  public method getUseIncludePath ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 86 - 89
    }

    /**
     * Gets the configured namespaces.
     *
     * @return array A hash with namespaces as keys and directories as values
     */
    Method [  public method getNamespaces ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 96 - 99
    }

    /**
     * Gets the configured class prefixes.
     *
     * @return array A hash with class prefixes as keys and directories as values
     */
    Method [  public method getPrefixes ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 106 - 109
    }

    /**
     * Gets the directory(ies) to use as a fallback for namespaces.
     *
     * @return array An array of directories
     */
    Method [  public method getNamespaceFallbacks ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 116 - 119
    }

    /**
     * Gets the directory(ies) to use as a fallback for class prefixes.
     *
     * @return array An array of directories
     */
    Method [  public method getPrefixFallbacks ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 126 - 129
    }

    /**
     * Registers the directory to use as a fallback for namespaces.
     *
     * @param array $dirs An array of directories
     *
     * @api
     */
    Method [  public method registerNamespaceFallbacks ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 138 - 141

      - Parameters [1] {
        Parameter #0 [  array $dirs ]
      }
    }

    /**
     * Registers a directory to use as a fallback for namespaces.
     *
     * @param string $dir A directory
     */
    Method [  public method registerNamespaceFallback ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 148 - 151

      - Parameters [1] {
        Parameter #0 [  $dir ]
      }
    }

    /**
     * Registers directories to use as a fallback for class prefixes.
     *
     * @param array $dirs An array of directories
     *
     * @api
     */
    Method [  public method registerPrefixFallbacks ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 160 - 163

      - Parameters [1] {
        Parameter #0 [  array $dirs ]
      }
    }

    /**
     * Registers a directory to use as a fallback for class prefixes.
     *
     * @param string $dir A directory
     */
    Method [  public method registerPrefixFallback ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 170 - 173

      - Parameters [1] {
        Parameter #0 [  $dir ]
      }
    }

    /**
     * Registers an array of namespaces
     *
     * @param array $namespaces An array of namespaces (namespaces as keys and locations as values)
     *
     * @api
     */
    Method [  public method registerNamespaces ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 182 - 187

      - Parameters [1] {
        Parameter #0 [  array $namespaces ]
      }
    }

    /**
     * Registers a namespace.
     *
     * @param string       $namespace The namespace
     * @param array|string $paths     The location(s) of the namespace
     *
     * @api
     */
    Method [  public method registerNamespace ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 197 - 200

      - Parameters [2] {
        Parameter #0 [  $namespace ]
        Parameter #1 [  $paths ]
      }
    }

    /**
     * Registers an array of classes using the PEAR naming convention.
     *
     * @param array $classes An array of classes (prefixes as keys and locations as values)
     *
     * @api
     */
    Method [  public method registerPrefixes ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 209 - 214

      - Parameters [1] {
        Parameter #0 [  array $classes ]
      }
    }

    /**
     * Registers a set of classes using the PEAR naming convention.
     *
     * @param string       $prefix The classes prefix
     * @param array|string $paths  The location(s) of the classes
     *
     * @api
     */
    Method [  public method registerPrefix ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 224 - 227

      - Parameters [2] {
        Parameter #0 [  $prefix ]
        Parameter #1 [  $paths ]
      }
    }

    /**
     * Registers this instance as an autoloader.
     *
     * @param Boolean $prepend Whether to prepend the autoloader or not
     *
     * @api
     */
    Method [  public method register ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 236 - 239

      - Parameters [1] {
        Parameter #0 [  $prepend = false ]
      }
    }

    /**
     * Loads the given class or interface.
     *
     * @param string $class The name of the class
     */
    Method [  public method loadClass ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 246 - 251

      - Parameters [1] {
        Parameter #0 [  $class ]
      }
    }

    /**
     * Finds the path to the file where the class is defined.
     *
     * @param string $class The name of the class
     *
     * @return string|null The path, if found
     */
    Method [  public method findFile ] {
      @@ /path/to/src/ClassLoader/UniversalClassLoader.php 260 - 318

      - Parameters [1] {
        Parameter #0 [  $class ]
      }
    }
  }
}

So how do you like them apples? With access to the autoloader there's no limit to the evil that can be done from here.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions