VYPR
High severityNVD Advisory· Published Aug 10, 2021· Updated Aug 3, 2024

Use of Predictable Algorithm in Random Number Generator in yiisoft/yii2

CVE-2021-3689

Description

yii2 is vulnerable to Use of Predictable Algorithm in Random Number Generator

Affected packages

Versions sourced from the GitHub Security Advisory.

PackageAffected versionsPatched versions
yiisoft/yii2-devPackagist
< 2.0.432.0.43

Affected products

1

Patches

1
13f27e4d920a

Fix #18817: Use `paragonie/random_compat` for random bytes and int generation

https://github.com/yiisoft/yii2Alexander MakarovAug 9, 2021via ghsa
12 files changed · +85 353
  • composer.json+2 1 modified
    @@ -78,7 +78,8 @@
             "bower-asset/jquery": "3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
             "bower-asset/inputmask": "~3.2.2 | ~3.3.5",
             "bower-asset/punycode": "1.3.*",
    -        "bower-asset/yii2-pjax": "~2.0.1"
    +        "bower-asset/yii2-pjax": "~2.0.1",
    +        "paragonie/random_compat": ">=1"
         },
         "require-dev": {
             "cweagans/composer-patches": "^1.7",
    
  • composer.lock+56 56 modified
    @@ -4,7 +4,7 @@
             "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
             "This file is @generated automatically"
         ],
    -    "content-hash": "7e41c6fc0175fd049e0e52c4e8b25e5c",
    +    "content-hash": "8f9a4d7e645592f806605d32d676f54e",
         "packages": [
             {
                 "name": "bower-asset/inputmask",
    @@ -199,6 +199,60 @@
                 },
                 "time": "2020-06-29T00:56:53+00:00"
             },
    +        {
    +            "name": "paragonie/random_compat",
    +            "version": "v2.0.20",
    +            "source": {
    +                "type": "git",
    +                "url": "https://github.com/paragonie/random_compat.git",
    +                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a"
    +            },
    +            "dist": {
    +                "type": "zip",
    +                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
    +                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
    +                "shasum": ""
    +            },
    +            "require": {
    +                "php": ">=5.2.0"
    +            },
    +            "require-dev": {
    +                "phpunit/phpunit": "4.*|5.*"
    +            },
    +            "suggest": {
    +                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
    +            },
    +            "type": "library",
    +            "autoload": {
    +                "files": [
    +                    "lib/random.php"
    +                ]
    +            },
    +            "notification-url": "https://packagist.org/downloads/",
    +            "license": [
    +                "MIT"
    +            ],
    +            "authors": [
    +                {
    +                    "name": "Paragon Initiative Enterprises",
    +                    "email": "security@paragonie.com",
    +                    "homepage": "https://paragonie.com"
    +                }
    +            ],
    +            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
    +            "keywords": [
    +                "csprng",
    +                "polyfill",
    +                "pseudorandom",
    +                "random"
    +            ],
    +            "support": {
    +                "email": "info@paragonie.com",
    +                "issues": "https://github.com/paragonie/random_compat/issues",
    +                "source": "https://github.com/paragonie/random_compat"
    +            },
    +            "time": "2021-04-17T09:33:01+00:00"
    +        },
             {
                 "name": "yiisoft/yii2-composer",
                 "version": "2.0.10",
    @@ -891,60 +945,6 @@
                 },
                 "time": "2015-09-13T19:01:00+00:00"
             },
    -        {
    -            "name": "paragonie/random_compat",
    -            "version": "v2.0.20",
    -            "source": {
    -                "type": "git",
    -                "url": "https://github.com/paragonie/random_compat.git",
    -                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a"
    -            },
    -            "dist": {
    -                "type": "zip",
    -                "url": "https://api.github.com/repos/paragonie/random_compat/zipball/0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
    -                "reference": "0f1f60250fccffeaf5dda91eea1c018aed1adc2a",
    -                "shasum": ""
    -            },
    -            "require": {
    -                "php": ">=5.2.0"
    -            },
    -            "require-dev": {
    -                "phpunit/phpunit": "4.*|5.*"
    -            },
    -            "suggest": {
    -                "ext-libsodium": "Provides a modern crypto API that can be used to generate random bytes."
    -            },
    -            "type": "library",
    -            "autoload": {
    -                "files": [
    -                    "lib/random.php"
    -                ]
    -            },
    -            "notification-url": "https://packagist.org/downloads/",
    -            "license": [
    -                "MIT"
    -            ],
    -            "authors": [
    -                {
    -                    "name": "Paragon Initiative Enterprises",
    -                    "email": "security@paragonie.com",
    -                    "homepage": "https://paragonie.com"
    -                }
    -            ],
    -            "description": "PHP 5.x polyfill for random_bytes() and random_int() from PHP 7",
    -            "keywords": [
    -                "csprng",
    -                "polyfill",
    -                "pseudorandom",
    -                "random"
    -            ],
    -            "support": {
    -                "email": "info@paragonie.com",
    -                "issues": "https://github.com/paragonie/random_compat/issues",
    -                "source": "https://github.com/paragonie/random_compat"
    -            },
    -            "time": "2021-04-17T09:33:01+00:00"
    -        },
             {
                 "name": "phpdocumentor/reflection-docblock",
                 "version": "2.0.5",
    @@ -2919,5 +2919,5 @@
         "platform-overrides": {
             "php": "5.4"
         },
    -    "plugin-api-version": "2.0.0"
    +    "plugin-api-version": "2.1.0"
     }
    
  • framework/base/Security.php+1 88 modified
    @@ -116,14 +116,6 @@ protected function shouldUseLibreSSL()
             return $this->_useLibreSSL;
         }
     
    -    /**
    -     * @return bool if operating system is Windows
    -     */
    -    private function isWindows()
    -    {
    -        return DIRECTORY_SEPARATOR !== '/';
    -    }
    -
         /**
          * Encrypts data using a password.
          * Derives keys for encryption and authentication from the password using PBKDF2 and a random salt,
    @@ -471,8 +463,6 @@ public function validateData($data, $key, $rawHash = false)
             return false;
         }
     
    -    private $_randomFile;
    -
         /**
          * Generates specified number of random bytes.
          * Note that output may not be ASCII.
    @@ -493,84 +483,7 @@ public function generateRandomKey($length = 32)
                 throw new InvalidArgumentException('First parameter ($length) must be greater than 0');
             }
     
    -        // always use random_bytes() if it is available
    -        if (function_exists('random_bytes')) {
    -            return random_bytes($length);
    -        }
    -
    -        // The recent LibreSSL RNGs are faster and likely better than /dev/urandom.
    -        // Since 5.4.0, openssl_random_pseudo_bytes() reads from CryptGenRandom on Windows instead
    -        // of using OpenSSL library. LibreSSL is OK everywhere but don't use OpenSSL on non-Windows.
    -        if (function_exists('openssl_random_pseudo_bytes')
    -            && ($this->shouldUseLibreSSL() || $this->isWindows())
    -        ) {
    -            $key = openssl_random_pseudo_bytes($length, $cryptoStrong);
    -            if ($cryptoStrong === false) {
    -                throw new Exception(
    -                    'openssl_random_pseudo_bytes() set $crypto_strong false. Your PHP setup is insecure.'
    -                );
    -            }
    -            if ($key !== false && StringHelper::byteLength($key) === $length) {
    -                return $key;
    -            }
    -        }
    -
    -        // mcrypt_create_iv() does not use libmcrypt. Since PHP 5.3.7 it directly reads
    -        // CryptGenRandom on Windows. Elsewhere it directly reads /dev/urandom.
    -        if (function_exists('mcrypt_create_iv')) {
    -            $key = mcrypt_create_iv($length, MCRYPT_DEV_URANDOM);
    -            if (StringHelper::byteLength($key) === $length) {
    -                return $key;
    -            }
    -        }
    -
    -        // If not on Windows, try to open a random device.
    -        if ($this->_randomFile === null && !$this->isWindows()) {
    -            // urandom is a symlink to random on FreeBSD.
    -            $device = PHP_OS === 'FreeBSD' ? '/dev/random' : '/dev/urandom';
    -            // Check random device for special character device protection mode. Use lstat()
    -            // instead of stat() in case an attacker arranges a symlink to a fake device.
    -            $lstat = @lstat($device);
    -            if ($lstat !== false && ($lstat['mode'] & 0170000) === 020000) {
    -                $this->_randomFile = fopen($device, 'rb') ?: null;
    -
    -                if (is_resource($this->_randomFile)) {
    -                    // Reduce PHP stream buffer from default 8192 bytes to optimize data
    -                    // transfer from the random device for smaller values of $length.
    -                    // This also helps to keep future randoms out of user memory space.
    -                    $bufferSize = 8;
    -
    -                    if (function_exists('stream_set_read_buffer')) {
    -                        stream_set_read_buffer($this->_randomFile, $bufferSize);
    -                    }
    -                    // stream_set_read_buffer() isn't implemented on HHVM
    -                    if (function_exists('stream_set_chunk_size')) {
    -                        stream_set_chunk_size($this->_randomFile, $bufferSize);
    -                    }
    -                }
    -            }
    -        }
    -
    -        if (is_resource($this->_randomFile)) {
    -            $buffer = '';
    -            $stillNeed = $length;
    -            while ($stillNeed > 0) {
    -                $someBytes = fread($this->_randomFile, $stillNeed);
    -                if ($someBytes === false) {
    -                    break;
    -                }
    -                $buffer .= $someBytes;
    -                $stillNeed -= StringHelper::byteLength($someBytes);
    -                if ($stillNeed === 0) {
    -                    // Leaving file pointer open in order to make next generation faster by reusing it.
    -                    return $buffer;
    -                }
    -            }
    -            fclose($this->_randomFile);
    -            $this->_randomFile = null;
    -        }
    -
    -        throw new Exception('Unable to generate a random key');
    +        return random_bytes($length);
         }
     
         /**
    
  • framework/caching/DbCache.php+2 1 modified
    @@ -276,7 +276,8 @@ protected function deleteValue($key)
          */
         public function gc($force = false)
         {
    -        if ($force || mt_rand(0, 1000000) < $this->gcProbability) {
    +
    +        if ($force || random_int(0, 1000000) < $this->gcProbability) {
                 $this->db->createCommand()
                     ->delete($this->cacheTable, '[[expire]] > 0 AND [[expire]] < ' . time())
                     ->execute();
    
  • framework/caching/FileCache.php+1 1 modified
    @@ -245,7 +245,7 @@ protected function flushValues()
          */
         public function gc($force = false, $expiredOnly = true)
         {
    -        if ($force || mt_rand(0, 1000000) < $this->gcProbability) {
    +        if ($force || random_int(0, 1000000) < $this->gcProbability) {
                 $this->gcRecursive($this->cachePath, $expiredOnly);
             }
         }
    
  • framework/captcha/CaptchaAction.php+9 8 modified
    @@ -214,16 +214,17 @@ protected function generateVerifyCode()
             if ($this->maxLength > 20) {
                 $this->maxLength = 20;
             }
    -        $length = mt_rand($this->minLength, $this->maxLength);
    +
    +        $length = random_int($this->minLength, $this->maxLength);
     
             $letters = 'bcdfghjklmnpqrstvwxyz';
             $vowels = 'aeiou';
             $code = '';
             for ($i = 0; $i < $length; ++$i) {
    -            if ($i % 2 && mt_rand(0, 10) > 2 || !($i % 2) && mt_rand(0, 10) > 9) {
    -                $code .= $vowels[mt_rand(0, 4)];
    +            if ($i % 2 && random_int(0, 10) > 2 || !($i % 2) && random_int(0, 10) > 9) {
    +                $code .= $vowels[random_int(0, 4)];
                 } else {
    -                $code .= $letters[mt_rand(0, 20)];
    +                $code .= $letters[random_int(0, 20)];
                 }
             }
     
    @@ -298,8 +299,8 @@ protected function renderImageByGD($code)
             $x = 10;
             $y = round($this->height * 27 / 40);
             for ($i = 0; $i < $length; ++$i) {
    -            $fontSize = (int) (mt_rand(26, 32) * $scale * 0.8);
    -            $angle = mt_rand(-10, 10);
    +            $fontSize = (int) (random_int(26, 32) * $scale * 0.8);
    +            $angle = random_int(-10, 10);
                 $letter = $code[$i];
                 $box = imagettftext($image, $fontSize, $angle, $x, $y, $foreColor, $this->fontFile, $letter);
                 $x = $box[2] + $this->offset;
    @@ -341,9 +342,9 @@ protected function renderImageByImagick($code)
             for ($i = 0; $i < $length; ++$i) {
                 $draw = new \ImagickDraw();
                 $draw->setFont($this->fontFile);
    -            $draw->setFontSize((int) (mt_rand(26, 32) * $scale * 0.8));
    +            $draw->setFontSize((int) (random_int(26, 32) * $scale * 0.8));
                 $draw->setFillColor($foreColor);
    -            $image->annotateImage($draw, $x, $y, mt_rand(-10, 10), $code[$i]);
    +            $image->annotateImage($draw, $x, $y, random_int(-10, 10), $code[$i]);
                 $fontMetrics = $image->queryFontMetrics($draw, $code[$i]);
                 $x += (int) $fontMetrics['textWidth'] + $this->offset;
             }
    
  • framework/CHANGELOG.md+1 0 modified
    @@ -4,6 +4,7 @@ Yii Framework 2 Change Log
     2.0.43 under development
     ------------------------
     
    +- Enh #18817: Use `paragonie/random_compat` for random bytes and int generation (samdark)
     - Bug #14663: Do not convert int to string if database type of a column is numeric (egorrishe)
     - Bug #18650: Refactor `framework/assets/yii.activeForm.js` arrow function into traditional function for IE11 compatibility (marcovtwout)
     - Bug #18749: Fix `yii\web\ErrorHandler::encodeHtml()` to support strings with invalid UTF symbols (vjik)
    
  • framework/composer.json+2 1 modified
    @@ -73,7 +73,8 @@
             "bower-asset/jquery": "3.6.*@stable | 3.5.*@stable | 3.4.*@stable | 3.3.*@stable | 3.2.*@stable | 3.1.*@stable | 2.2.*@stable | 2.1.*@stable | 1.11.*@stable | 1.12.*@stable",
             "bower-asset/inputmask": "~3.2.2 | ~3.3.5",
             "bower-asset/punycode": "1.3.*",
    -        "bower-asset/yii2-pjax": "~2.0.1"
    +        "bower-asset/yii2-pjax": "~2.0.1",
    +        "paragonie/random_compat": ">=1"
         },
         "autoload": {
             "psr-4": {"yii\\": ""}
    
  • framework/mail/BaseMailer.php+1 1 modified
    @@ -343,7 +343,7 @@ public function generateMessageFileName()
         {
             $time = microtime(true);
     
    -        return date('Ymd-His-', $time) . sprintf('%04d', (int) (($time - (int) $time) * 10000)) . '-' . sprintf('%04d', mt_rand(0, 10000)) . '.eml';
    +        return date('Ymd-His-', $time) . sprintf('%04d', (int) (($time - (int) $time) * 10000)) . '-' . sprintf('%04d', random_int(0, 10000)) . '.eml';
         }
     
         /**
    
  • tests/framework/base/SecurityTest.php+2 189 modified
    @@ -5,53 +5,7 @@
      * @license http://www.yiiframework.com/license/
      */
     
    -namespace yii\base {
    -
    -    /**
    -     * emulate availability of functions, to test different branches of Security class
    -     * where different execution paths are chosen based on calling function_exists.
    -     *
    -     * This function overrides function_exists from the root namespace in yii\base.
    -     * @param string $name
    -     */
    -    function function_exists($name)
    -    {
    -        if (isset(\yiiunit\framework\base\SecurityTest::$functions[$name])) {
    -            return \yiiunit\framework\base\SecurityTest::$functions[$name];
    -        }
    -
    -        return \function_exists($name);
    -    }
    -    /**
    -     * Emulate chunked reading of fread(), to test different branches of Security class
    -     * where different execution paths are chosen based on the return value of fopen/fread.
    -     *
    -     * This function overrides fopen and fread from the root namespace in yii\base.
    -     * @param string $filename
    -     * @param mixed $mode
    -     */
    -    function fopen($filename, $mode)
    -    {
    -        if (\yiiunit\framework\base\SecurityTest::$fopen !== null) {
    -            return \yiiunit\framework\base\SecurityTest::$fopen;
    -        }
    -
    -        return \fopen($filename, $mode);
    -    }
    -    function fread($handle, $length)
    -    {
    -        if (\yiiunit\framework\base\SecurityTest::$fread !== null) {
    -            return \yiiunit\framework\base\SecurityTest::$fread;
    -        }
    -        if (\yiiunit\framework\base\SecurityTest::$fopen !== null) {
    -            return $length < 8 ? \str_repeat('s', $length) : 'test1234';
    -        }
    -
    -        return \fread($handle, $length);
    -    }
    -} // closing namespace yii\base;
    -
    -namespace yiiunit\framework\base {
    +namespace yiiunit\framework\base;
     
     use yii\base\Security;
     use yiiunit\TestCase;
    @@ -63,44 +17,18 @@ class SecurityTest extends TestCase
     {
         const CRYPT_VECTORS = 'old';
     
    -    /**
    -     * @var array set of functions for which a fake return value for `function_exists()` is provided.
    -     */
    -    public static $functions = [];
    -    /**
    -     * @var resource|false|null fake return value for fopen() in \yii\base namespace. Normal behavior if this is null.
    -     */
    -    public static $fopen;
    -    public static $fread;
    -
         /**
          * @var ExposedSecurity
          */
         protected $security;
     
         protected function setUp()
         {
    -        static::$functions = [];
    -        static::$fopen = null;
    -        static::$fread = null;
             parent::setUp();
             $this->security = new ExposedSecurity();
             $this->security->derivationIterations = 1000; // speed up test running
         }
     
    -    protected function tearDown()
    -    {
    -        static::$functions = [];
    -        static::$fopen = null;
    -        static::$fread = null;
    -        parent::tearDown();
    -    }
    -
    -    private function isWindows()
    -    {
    -        return DIRECTORY_SEPARATOR !== '/';
    -    }
    -
         // Tests :
     
         public function testHashData()
    @@ -893,76 +821,8 @@ public function testRandomKeyInvalidInput($input)
             $key1 = $this->security->generateRandomKey($input);
         }
     
    -    /**
    -     * Test the case where opening /dev/urandom fails.
    -     */
    -    public function testRandomKeyNoOptions()
    -    {
    -        static::$functions = ['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false];
    -        static::$fopen = false;
    -        $this->expectException('yii\base\Exception');
    -        $this->expectExceptionMessage('Unable to generate a random key');
    -
    -        $this->security->generateRandomKey(42);
    -    }
    -
    -    /**
    -     * Test the case where reading from /dev/urandom fails.
    -     */
    -    public function testRandomKeyFreadFailure()
    -    {
    -        static::$functions = ['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false];
    -        static::$fread = false;
    -        $this->expectException('yii\base\Exception');
    -        $this->expectExceptionMessage('Unable to generate a random key');
    -
    -        $this->security->generateRandomKey(42);
    -    }
    -
    -    /**
    -     * returns a set of different combinations of functions available.
    -     */
    -    public function randomKeyVariants()
    +    public function testGenerateRandomKey()
         {
    -        return [
    -            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => true]],
    -            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => false]],
    -            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => true]],
    -            [['random_bytes' => true,  'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false]],
    -            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => true]],
    -            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => true,  'mcrypt_create_iv' => false]],
    -            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => true]],
    -            [['random_bytes' => false, 'openssl_random_pseudo_bytes' => false, 'mcrypt_create_iv' => false]],
    -        ];
    -    }
    -
    -    /**
    -     * @dataProvider randomKeyVariants
    -     * @param array $functions
    -     */
    -    public function testGenerateRandomKey($functions)
    -    {
    -        foreach ($functions as $fun => $available) {
    -            if ($available && !\function_exists($fun)) {
    -                $this->markTestSkipped("Can not test generateRandomKey() branch that includes $fun, because it is not available on your system.");
    -            }
    -        }
    -        // there is no /dev/urandom on windows so we expect this to fail
    -        if ($this->isWindows() && $functions['random_bytes'] === false && $functions['openssl_random_pseudo_bytes'] === false && $functions['mcrypt_create_iv'] === false) {
    -            $this->expectException('yii\base\Exception');
    -            $this->expectExceptionMessage('Unable to generate a random key');
    -        }
    -        // Function mcrypt_create_iv() is deprecated since PHP 7.1
    -        if (version_compare(PHP_VERSION, '7.1.0alpha', '>=') && $functions['random_bytes'] === false && $functions['mcrypt_create_iv'] === true) {
    -            if ($functions['openssl_random_pseudo_bytes'] === false) {
    -                $this->markTestSkipped('Function mcrypt_create_iv() is deprecated as of PHP 7.1');
    -            } elseif (!$this->security->shouldUseLibreSSL() && !$this->isWindows()) {
    -                $this->markTestSkipped('Function openssl_random_pseudo_bytes need LibreSSL version >=2.1.5 or Windows system on server');
    -            }
    -        }
    -
    -        static::$functions = $functions;
    -
             // test various string lengths
             for ($length = 1; $length < 64; $length++) {
                 $key1 = $this->security->generateRandomKey($length);
    @@ -985,16 +845,6 @@ public function testGenerateRandomKey($functions)
             $this->assertInternalType('string', $key2);
             $this->assertEquals($length, strlen($key2));
             $this->assertNotEquals($key1, $key2);
    -
    -        // force /dev/urandom reading loop to deal with chunked data
    -        // the above test may have read everything in one run.
    -        // not sure if this can happen in real life but if it does
    -        // we should be prepared
    -        static::$fopen = fopen('php://memory', 'rwb');
    -        $length = 1024 * 1024;
    -        $key1 = $this->security->generateRandomKey($length);
    -        $this->assertInternalType('string', $key1);
    -        $this->assertEquals($length, strlen($key1));
         }
     
         protected function randTime(Security $security, $count, $length, $message)
    @@ -1010,42 +860,6 @@ protected function randTime(Security $security, $count, $length, $message)
             fwrite(STDERR, "$message: $count x $length B = $nbytes B in $milisec ms => $rate MB/s\n");
         }
     
    -    public function testGenerateRandomKeySpeed()
    -    {
    -        self::markTestSkipped('Comment markTestSkipped in testGenerateRandomKeySpeed() in order to get RNG benchmark.');
    -        $tests = [
    -            "function_exists('random_bytes')",
    -            "defined('OPENSSL_VERSION_TEXT') ? OPENSSL_VERSION_TEXT : null",
    -            'PHP_VERSION_ID',
    -            'PHP_OS',
    -            "function_exists('mcrypt_create_iv') ? bin2hex(mcrypt_create_iv(4, MCRYPT_DEV_URANDOM)) : null",
    -            'DIRECTORY_SEPARATOR',
    -            "ini_get('open_basedir')",
    -        ];
    -        if ($this->isWindows()) {
    -            $tests[] = "sprintf('%o', lstat(PHP_OS === 'FreeBSD' ? '/dev/random' : '/dev/urandom')['mode'] & 0170000)";
    -            $tests[] = "bin2hex(file_get_contents(PHP_OS === 'FreeBSD' ? '/dev/random' : '/dev/urandom', false, null, 0, 8))";
    -        }
    -        foreach ($tests as $i => $test) {
    -            $result = eval('return ' . $test . ';');
    -            fwrite(STDERR, sprintf("%2d %s ==> %s\n", $i + 1, $test, var_export($result, true)));
    -        }
    -
    -        foreach ([16, 2000, 262144] as $block) {
    -            $security = new Security();
    -            foreach (range(1, 10) as $nth) {
    -                $this->randTime($security, 1, $block, "Call $nth");
    -            }
    -            unset($security);
    -        }
    -
    -        $security = new Security();
    -        $this->randTime($security, 10000, 16, 'Rate test');
    -
    -        $security = new Security();
    -        $this->randTime($security, 10000, 5000, 'Rate test');
    -    }
    -
         public function testGenerateRandomString()
         {
             $length = 21;
    @@ -1305,4 +1119,3 @@ public function maskProvider()
             ];
         }
     }
    -} // closing namespace yiiunit\framework\base;
    
  • tests/framework/validators/FileValidatorTest.php+2 2 modified
    @@ -324,7 +324,7 @@ protected function createTestFiles($params = [])
                 $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
                 $randomString = '';
                 for ($i = 0; $i < $len; $i++) {
    -                $randomString .= $characters[rand(0, strlen($characters) - 1)];
    +                $randomString .= $characters[random_int(0, strlen($characters) - 1)];
                 }
     
                 return $randomString;
    @@ -340,7 +340,7 @@ protected function createTestFiles($params = [])
                 if (is_readable($tempName)) {
                     $size = filesize($tempName);
                 } else {
    -                $size = isset($param['size']) ? $param['size'] : rand(
    +                $size = isset($param['size']) ? $param['size'] : random_int(
                         1,
                         $this->sizeToBytes(ini_get('upload_max_filesize'))
                     );
    
  • tests/framework/web/UploadedFileTest.php+6 5 modified
    @@ -7,6 +7,7 @@
     
     namespace yiiunit\framework\web;
     
    +use Yii;
     use yii\web\UploadedFile;
     use yiiunit\framework\web\mocks\UploadedFileMock;
     use yiiunit\framework\web\stubs\ModelStub;
    @@ -28,21 +29,21 @@ protected function setUp()
         private function generateFakeFileData()
         {
             return [
    -            'name' => md5(mt_rand()),
    -            'tmp_name' => md5(mt_rand()),
    +            'name' => md5(random_int(0, PHP_INT_MAX)),
    +            'tmp_name' => md5(random_int(0, PHP_INT_MAX)),
                 'type' => 'image/jpeg',
    -            'size' => mt_rand(1000, 10000),
    +            'size' => random_int(1000, 10000),
                 'error' => '0',
             ];
         }
     
         private function generateTempFileData()
         {
             return [
    -            'name' => md5(mt_rand()),
    +            'name' => md5(random_int(0, PHP_INT_MAX)),
                 'tmp_name' => tempnam(sys_get_temp_dir(), ''),
                 'type' => 'image/jpeg',
    -            'size' => mt_rand(1000, 10000),
    +            'size' => random_int(1000, 10000),
                 'error' => '0',
             ];
         }
    

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.