CVE-2012-1617 (PHP, published 2012-09-26T00:55Z)
Description: value: Directory traversal vulnerability in combine.php in OSClass before 2.3.6 allows remote attackers to read and write arbitrary files via a .. (dot dot) in the type parameter.  NOTE: this vulnerability can be leveraged to upload arbitrary files.
Severity: MEDIUM (CVSS v3 base score: )
Weakness: CWE-22 \u2014 Improper Limitation of a Pathname to a Restricted Directory ('Path Traversal')
The product uses external input to construct a pathname that is intended to identify a file or directory that is located underneath a restricted parent directory, but the product does not properly neutralize special elements within the pathname that can cause the pathname to resolve to a location that is outside of the restricted directory.
Repository: https://github.com/osclass/OSClass
Files changed:
oc-content/themes/modern/combine.php
oc-includes/osclass/gui/combine.php
Commit message: show http 403 forbidden error if the type parameter is not js or css


Vulnerable code:

    $cache       = true;
    $base = dirname(__FILE__);
    $type = $_GET['type'];
    
    while (list(,$element) = each($elements)) {
        $path = realpath($base . '/' . $element);
    
        if (($type == 'js' && substr($path, -3) != '.js') || 
            ($type == 'css' && substr($path, -4) != '.css')) {
            header ("HTTP/1.0 403 Forbidden");
            exit;    
    
        
    
    if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && 
        stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == '"' . $hash . '"') 
    {
        header ("HTTP/1.0 304 Not Modified");
        header ('Content-Length: 0');
    } 
    else 
    {
        if ($cache) 
        {
            $gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
            $deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');
    
            $encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');
    
            if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') && 
                preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches)) {
                $version = floatval($matches[1]);
                
                if ($version < 6)
                    
                if ($version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1')) 
            
            $cachefile = 'cache-' . $hash . '.' . $type . ($encoding != 'none' ? '.' . $encoding : '');
            
            if (file_exists($cachedir . '/' . $cachefile)) {
                if ($fp = fopen($cachedir . '/' . $cachefile, 'rb')) {
                    if ($encoding != 'none') {
                        header ("Content-Encoding: " . $encoding);
                
                    header ("Content-Type: text/" . $type);
                    header ("Content-Length: " . filesize($cachedir . '/' . $cachefile));
        
                    fpassthru($fp);
                    fclose($fp);
                    exit;
    
        $contents = '';
        reset($elements);
        while (list(,$element) = each($elements)) {
            $path = realpath($base . '/' . $element);
            $contents .= "\n\n" . file_get_contents($path);
    
        header ("Content-Type: text/" . $type);
        
        if (isset($encoding) && $encoding != 'none') 
        {
            $contents = gzencode($contents, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE);
            header ("Content-Encoding: " . $encoding);
            header ('Content-Length: ' . strlen($contents));
            echo $contents;
        } 
        else 
        {
            header ('Content-Length: ' . strlen($contents));
            echo $contents;
        if ($cache) {
            if ($fp = fopen($cachedir . '/' . $cachefile, 'wb')) {
                fwrite($fp, $contents);
                fclose($fp);
    }    
    

    $cache       = true;
    $base = dirname(__FILE__);
    $type = $_GET['type'];
    
    while (list(,$element) = each($elements)) {
        $path = realpath($base . '/' . $element);
    
        if (($type == 'js' && substr($path, -3) != '.js') || 
            ($type == 'css' && substr($path, -4) != '.css')) {
            header ("HTTP/1.0 403 Forbidden");
            exit;    
    
        
    
    if (isset($_SERVER['HTTP_IF_NONE_MATCH']) && 
        stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == '"' . $hash . '"') 
    {
        header ("HTTP/1.0 304 Not Modified");
        header ('Content-Length: 0');
    } 
    else 
    {
        if ($cache) 
        {
            $gzip = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip');
            $deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate');
    
            $encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none');
    
            if (!strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') && 
                preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches)) {
                $version = floatval($matches[1]);
                
                if ($version < 6)
                    
                if ($version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1')) 
            
            $cachefile = 'cache-' . $hash . '.' . $type . ($encoding != 'none' ? '.' . $encoding : '');
            
            if (file_exists($cachedir . '/' . $cachefile)) {
                if ($fp = fopen($cachedir . '/' . $cachefile, 'rb')) {
                    if ($encoding != 'none') {
                        header ("Content-Encoding: " . $encoding);
                
                    header ("Content-Type: text/" . $type);
                    header ("Content-Length: " . filesize($cachedir . '/' . $cachefile));
        
                    fpassthru($fp);
                    fclose($fp);
                    exit;
    
        $contents = '';
        reset($elements);
        while (list(,$element) = each($elements)) {
            $path = realpath($base . '/' . $element);
            $contents .= "\n\n" . file_get_contents($path);
    
        header ("Content-Type: text/" . $type);
        
        if (isset($encoding) && $encoding != 'none') 
        {
            $contents = gzencode($contents, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE);
            header ("Content-Encoding: " . $encoding);
            header ('Content-Length: ' . strlen($contents));
            echo $contents;
        } 
        else 
        {
            header ('Content-Length: ' . strlen($contents));
            echo $contents;
        if ($cache) {
            if ($fp = fopen($cachedir . '/' . $cachefile, 'wb')) {
                fwrite($fp, $contents);
                fclose($fp);
    }    
    

Fixed code:
    $cache    = true;
    $base     = dirname(__FILE__);
    $type     = $_GET['type'];

    while( list(,$element) = each($elements) ) {
        $path = realpath($base . '/' . $element) ;

        if( ($type != 'js' && $type != 'css') || 
            ($type == 'js' && substr($path, -3) != '.js') || 
            ($type == 'css' && substr($path, -4) != '.css') ) {
            header ("HTTP/1.0 403 Forbidden") ;
            exit ;



    if( isset($_SERVER['HTTP_IF_NONE_MATCH']) && 
        stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == '"' . $hash . '"' ) {
        header ("HTTP/1.0 304 Not Modified") ;
        header ('Content-Length: 0') ;
    } else {
        if( $cache ) {
            $gzip    = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') ;
            $deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') ;

            $encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none') ;

            if( !strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') && 
                preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches) ) {
                $version = floatval($matches[1]) ;

                if( $version < 6 ) {
                }
                if( $version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1') ) {
                }

            $cachefile = 'cache-' . $hash . '.' . $type . ($encoding != 'none' ? '.' . $encoding : '') ;
            if( file_exists($cachedir . '/' . $cachefile) ) {
                if( $fp = fopen($cachedir . '/' . $cachefile, 'rb') ) {
                    if( $encoding != 'none' ) {
                        header ("Content-Encoding: " . $encoding) ;

                    header( "Content-Type: text/" . $type) ;
                    header( "Content-Length: " . filesize($cachedir . '/' . $cachefile) ) ;

                    fpassthru($fp) ;
                    fclose($fp) ;
                    exit ;

        $contents = '' ;
        reset($elements) ;
        while( list(,$element) = each($elements) ) {
            $path      = realpath($base . '/' . $element) ;
            $contents .= "\n\n" . file_get_contents($path) ;

        header ("Content-Type: text/" . $type) ;

        if (isset($encoding) && $encoding != 'none') {
            $contents = gzencode($contents, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE) ;
            header( "Content-Encoding: " . $encoding ) ;
            header( 'Content-Length: ' . strlen($contents) ) ;
            echo $contents ;
        } else {
            header( 'Content-Length: ' . strlen($contents) ) ;
            echo $contents ;
        if( $cache ) {
            if( $fp = fopen($cachedir . '/' . $cachefile, 'wb') ) {
                fwrite($fp, $contents) ;
                fclose($fp) ;
    }

?>
    $cache    = true;
    $base     = dirname(__FILE__);
    $type     = $_GET['type'];

    while( list(,$element) = each($elements) ) {
        $path = realpath($base . '/' . $element) ;

        if( ($type != 'js' && $type != 'css') || 
            ($type == 'js' && substr($path, -3) != '.js') || 
            ($type == 'css' && substr($path, -4) != '.css') ) {
            header ("HTTP/1.0 403 Forbidden") ;
            exit ;



    if( isset($_SERVER['HTTP_IF_NONE_MATCH']) && 
        stripslashes($_SERVER['HTTP_IF_NONE_MATCH']) == '"' . $hash . '"' ) {
        header ("HTTP/1.0 304 Not Modified") ;
        header ('Content-Length: 0') ;
    } else {
        if( $cache ) {
            $gzip    = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'gzip') ;
            $deflate = strstr($_SERVER['HTTP_ACCEPT_ENCODING'], 'deflate') ;

            $encoding = $gzip ? 'gzip' : ($deflate ? 'deflate' : 'none') ;

            if( !strstr($_SERVER['HTTP_USER_AGENT'], 'Opera') && 
                preg_match('/^Mozilla\/4\.0 \(compatible; MSIE ([0-9]\.[0-9])/i', $_SERVER['HTTP_USER_AGENT'], $matches) ) {
                $version = floatval($matches[1]) ;

                if( $version < 6 ) {
                }
                if( $version == 6 && !strstr($_SERVER['HTTP_USER_AGENT'], 'EV1') ) {
                }

            $cachefile = 'cache-' . $hash . '.' . $type . ($encoding != 'none' ? '.' . $encoding : '') ;
            if( file_exists($cachedir . '/' . $cachefile) ) {
                if( $fp = fopen($cachedir . '/' . $cachefile, 'rb') ) {
                    if( $encoding != 'none' ) {
                        header ("Content-Encoding: " . $encoding) ;

                    header( "Content-Type: text/" . $type) ;
                    header( "Content-Length: " . filesize($cachedir . '/' . $cachefile) ) ;

                    fpassthru($fp) ;
                    fclose($fp) ;
                    exit ;

        $contents = '' ;
        reset($elements) ;
        while( list(,$element) = each($elements) ) {
            $path      = realpath($base . '/' . $element) ;
            $contents .= "\n\n" . file_get_contents($path) ;

        header ("Content-Type: text/" . $type) ;

        if (isset($encoding) && $encoding != 'none') {
            $contents = gzencode($contents, 9, $gzip ? FORCE_GZIP : FORCE_DEFLATE) ;
            header( "Content-Encoding: " . $encoding ) ;
            header( 'Content-Length: ' . strlen($contents) ) ;
            echo $contents ;
        } else {
            header( 'Content-Length: ' . strlen($contents) ) ;
            echo $contents ;
        if( $cache ) {
            if( $fp = fopen($cachedir . '/' . $cachefile, 'wb') ) {
                fwrite($fp, $contents) ;
                fclose($fp) ;
    }

?>