VYPR
Critical severity9.1NVD Advisory· Published May 22, 2024· Updated Apr 15, 2026

CVE-2024-25738

CVE-2024-25738

Description

A Server-Side Request Forgery (SSRF) vulnerability in the /Upgrade/FixConfig route in Open Library Foundation VuFind 2.0 through 9.1 before 9.1.1 allows a remote attacker to overwrite local configuration files to gain access to the administrator panel and achieve Remote Code Execution. A mitigating factor is that it requires the allow_url_include PHP runtime setting to be on, which is off in default installations. It also requires the /Upgrade route to be exposed, which is exposed by default after installing VuFind, and is recommended to be disabled by setting autoConfigure to false in config.ini.

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
vufind/vufindPackagist
>= 2.0, < 9.1.19.1.1

Patches

1
a19577d3d87d

Improve security of UpgradeController and related functionality. (#3387)

https://github.com/vufind-org/vufindDemian KatzFeb 7, 2024via ghsa
2 files changed · +52 11
  • module/VuFind/src/VuFind/Config/Upgrade.php+2 0 modified
    @@ -1358,6 +1358,8 @@ protected function upgradeILS()
                 $this->addWarning('WARNING: Could not find ILS driver setting.');
             } elseif ('Sample' == $driver) {
                 // No configuration file for Sample driver
    +        } elseif ('AdminScripts' == $driver) {
    +            // Prevent abuse if upgrade process is hijacked
             } elseif (!file_exists($this->oldDir . '/' . $driver . '.ini')) {
                 $this->addWarning(
                     "WARNING: Could not find {$driver}.ini file; "
    
  • module/VuFind/src/VuFind/Controller/UpgradeController.php+50 11 modified
    @@ -197,9 +197,7 @@ public function errorAction()
         public function establishversionsAction()
         {
             $this->cookie->newVersion = Version::getBuildVersion();
    -        $this->cookie->oldVersion = Version::getBuildVersion(
    -            $this->cookie->sourceDir
    -        );
    +        $this->cookie->oldVersion = Version::getBuildVersion($this->getSourceDir());
     
             // Block upgrade when encountering common errors:
             if (empty($this->cookie->oldVersion)) {
    @@ -234,7 +232,7 @@ public function fixconfigAction()
         {
             $localConfig = dirname($this->getForcedLocalConfigPath('config.ini'));
             $confDir = $this->cookie->oldVersion < 2
    -            ? $this->cookie->sourceDir . '/web/conf'
    +            ? $this->getSourceDir() . '/web/conf'
                 : $localConfig;
             $upgrader = new Upgrade(
                 $this->cookie->oldVersion,
    @@ -809,7 +807,7 @@ public function getsourcedirAction()
             // Process form submission:
             $dir = $this->params()->fromPost('sourcedir');
             if (!empty($dir)) {
    -            if (!is_dir($dir)) {
    +            if (!$this->isSourceDirValid($dir)) {
                     $this->flashMessenger()
                         ->addMessage($dir . ' does not exist.', 'error');
                 } elseif (!file_exists($dir . '/build.xml')) {
    @@ -819,7 +817,7 @@ public function getsourcedirAction()
                         'error'
                     );
                 } else {
    -                $this->cookie->sourceDir = rtrim($dir, '\/');
    +                $this->setSourceDir(rtrim($dir, '\/'));
                     // Clear out request to avoid infinite loop:
                     $this->getRequest()->getPost()->set('sourcedir', '');
                     return $this->forwardTo('Upgrade', 'Home');
    @@ -864,7 +862,7 @@ public function getsourceversionAction()
                     );
                 } else {
                     $this->cookie->oldVersion = $version;
    -                $this->cookie->sourceDir = realpath(APPLICATION_PATH);
    +                $this->setSourceDir(realpath(APPLICATION_PATH));
                     // Clear out request to avoid infinite loop:
                     $this->getRequest()->getPost()->set('sourceversion', '');
                     $this->processSkipParam();
    @@ -889,6 +887,50 @@ protected function performCriticalChecks()
                 ?? null;
         }
     
    +    /**
    +     * Validate a source directory string.
    +     *
    +     * @param string $dir Directory string to check
    +     *
    +     * @return bool
    +     */
    +    protected function isSourceDirValid(string $dir): bool
    +    {
    +        // Prevent abuse of stream wrappers:
    +        if (empty($dir) || str_contains($dir, '://')) {
    +            return false;
    +        }
    +        return is_dir($dir);
    +    }
    +
    +    /**
    +     * Set the source directory for the upgrade
    +     *
    +     * @param string $dir Directory to set
    +     *
    +     * @return void
    +     */
    +    protected function setSourceDir(string $dir): void
    +    {
    +        $this->cookie->sourceDir = $dir;
    +    }
    +
    +    /**
    +     * Get the source directory for the upgrade
    +     *
    +     * @param bool $validate Should we validate the directory?
    +     *
    +     * @return string
    +     */
    +    protected function getSourceDir($validate = true): string
    +    {
    +        $sourceDir = $this->cookie->sourceDir ?? '';
    +        if ($validate && !$this->isSourceDirValid($sourceDir)) {
    +            throw new \Exception('Unexpected source directory value!');
    +        }
    +        return $sourceDir;
    +    }
    +
         /**
          * Display summary of installation status
          *
    @@ -904,10 +946,7 @@ public function homeAction()
             }
     
             // First find out which version we are upgrading:
    -        if (
    -            !isset($this->cookie->sourceDir)
    -            || !is_dir($this->cookie->sourceDir)
    -        ) {
    +        if (!$this->isSourceDirValid($this->getSourceDir(false))) {
                 return $this->forwardTo('Upgrade', 'GetSourceDir');
             }
     
    

Vulnerability mechanics

Generated by null/stub on May 9, 2026. Inputs: CWE entries + fix-commit diffs from this CVE's patches. Citations validated against bundle.

References

4

News mentions

0

No linked articles in our index yet.