Invision Power Services, Inc. * @copyright (c) Invision Power Services, Inc. * @license https://www.invisioncommunity.com/legal/standards/ * @package Invision Community * @since 31 Jul 2017 */ // This file deliberately exists outside of the framework // and MUST NOT call init.php @ini_set('display_errors', 'off'); if ( file_exists( "../../constants.php" ) ) { require "../../constants.php"; } if ( !defined( 'ROOT_PATH' ) ) { define( 'ROOT_PATH', str_replace( 'admin/upgrade', '', __DIR__ ) ); } require "../../conf_global.php"; /** * Compare hashes in fixed length, time constant manner. * * @param string $expected The expected hash * @param string $provided The provided input * @return boolean */ function compareHashes( $expected, $provided ) { if ( !is_string( $expected ) || !is_string( $provided ) || $expected === '*0' || $expected === '*1' || $provided === '*0' || $provided === '*1' ) // *0 and *1 are failures from crypt() - if we have ended up with an invalid hash anywhere, we will reject it to prevent a possible vulnerability from deliberately generating invalid hashes { return FALSE; } $len = strlen( $expected ); if ( $len !== strlen( $provided ) ) { return FALSE; } $status = 0; for ( $i = 0; $i < $len; $i++ ) { $status |= ord( $expected[ $i ] ) ^ ord( $provided[ $i ] ); } return $status === 0; } /** * Get CiCloud User * * @return string|NULL */ function getCicUsername(): ?string { if ( preg_match( '/^\/var\/www\/html\/(.+?)(?:\/|$)/i', ROOT_PATH, $matches ) ) { return $matches[1]; } return NULL; } /** * Function to write a log file to disk * * @param mixed $message Exception or message to log * @return void */ function writeLogFile( $message ) { /* What are we writing? */ $date = date('r'); if ( $message instanceof Exception) { $messageToLog = $date . "\n" . get_class( $message ) . '::' . $message->getCode() . "\n" . $message->getMessage() . "\n" . $message->getTraceAsString(); } else { if ( is_array( $message ) ) { $message = var_export( $message, TRUE ); } $messageToLog = $date . "\n" . $message . "\n" . ( new Exception)->getTraceAsString(); } /* Where are we writing it? */ $dir = rtrim( __DIR__, '/' ) . '/../../uploads/logs'; /* Write it */ $header = "\n\n"; $file = $dir . '/' . date( 'Y' ) . '_' . date( 'm' ) . '_' . date('d') . '_' . ( 'extractfailure' ) . '.php'; if ( file_exists( $file ) ) { @file_put_contents( $file, "\n\n-------------\n\n" . $messageToLog, FILE_APPEND ); } else { @file_put_contents( $file, $header . $messageToLog ); } @chmod( $file, IPS_FILE_PERMISSION ); } /* ! Controller */ try { /* Check this request came from the ACP */ if ( !getCicUsername() OR compareHashes( md5( getCicUsername() . $INFO['sql_pass'] ), $_GET['key'] ) === FALSE ) { throw new Exception( "Security check failed" ); } /* We are done if last_auto_upgrade exists and is both older than the current time but updated less than ten minutes ago. */ $done = ( isset( $INFO['last_auto_upgrade'] ) AND $INFO['last_auto_upgrade'] < time() AND ( $INFO['last_auto_upgrade'] > time() - ( 10 * 60 ) ) ); $adsess = $_GET['adsess'] ?? ''; if ( $done ) { if ( function_exists( 'opcache_reset' ) ) { @opcache_reset(); } $siteurl = $INFO['base_url'] ?? $INFO['board_url']; $upgradeUrl = rtrim( $siteurl, '/' ) . "/admin/upgrade/"; echo <<

  

HTML; } /* Nope, redirect to the next batch */ else { if ( !isset( $_GET['counter'] ) ) { $_GET['counter'] = 0; } $i = 1 + $_GET['counter']; $url = "extractCic.php?counter={$i}&key={$_GET['key']}&adsess={$adsess}"; echo <<

  

HTML; } } catch ( Throwable $e ) { writeLogFile( $e ); echo ""; exit; } ?>