WordPress.org

Make WordPress Core

Ticket #42016: 42016.diff

File 42016.diff, 5.7 KB (added by johnbillion, 2 years ago)
  • src/wp-admin/includes/file.php

    diff --git src/wp-admin/includes/file.php src/wp-admin/includes/file.php
    index 858f828185..a834e5e161 100644
    function wp_tempnam( $filename = '', $dir = '' ) { 
    663663 * @param array  $allowed_files Optional. Array of allowed files to edit, $file must match an entry exactly.
    664664 * @return string|null
    665665 */
    666 function validate_file_to_edit( $file, $allowed_files = '' ) {
     666function validate_file_to_edit( $file, $allowed_files = array() ) {
    667667        $code = validate_file( $file, $allowed_files );
    668668
    669669        if (!$code )
    function _unzip_file_ziparchive($file, $to, $needed_dirs = array() ) { 
    11191119                if ( '__MACOSX/' === substr($info['name'], 0, 9) ) // Skip the OS X-created __MACOSX directory
    11201120                        continue;
    11211121
     1122                // Don't extract invalid files:
    11221123                if ( 0 !== validate_file( $info['name'] ) ) {
    1123                         return new WP_Error( 'invalid_file_ziparchive', __( 'Could not extract file from archive.' ), $info['name'] );
     1124                        continue;
    11241125                }
    11251126
    11261127                $uncompressed_size += $info['size'];
    function _unzip_file_ziparchive($file, $to, $needed_dirs = array() ) { 
    11801181                if ( '__MACOSX/' === substr($info['name'], 0, 9) ) // Don't extract the OS X-created __MACOSX directory files
    11811182                        continue;
    11821183
     1184                // Don't extract invalid files:
     1185                if ( 0 !== validate_file( $info['name'] ) ) {
     1186                        continue;
     1187                }
     1188
    11831189                $contents = $z->getFromIndex($i);
    11841190                if ( false === $contents )
    11851191                        return new WP_Error( 'extract_failed_ziparchive', __( 'Could not extract file from archive.' ), $info['name'] );
    function _unzip_file_pclzip($file, $to, $needed_dirs = array()) { 
    12831289                if ( '__MACOSX/' === substr($file['filename'], 0, 9) ) // Don't extract the OS X-created __MACOSX directory files
    12841290                        continue;
    12851291
     1292                // Don't extract invalid files:
    12861293                if ( 0 !== validate_file( $file['filename'] ) ) {
    1287                         return new WP_Error( 'invalid_file_pclzip', __( 'Could not extract file from archive.' ), $file['filename'] );
     1294                        continue;
    12881295                }
    12891296
    12901297                if ( ! $wp_filesystem->put_contents( $to . $file['filename'], $file['content'], FS_CHMOD_FILE) )
  • src/wp-includes/functions.php

    diff --git src/wp-includes/functions.php src/wp-includes/functions.php
    index a9c53d31e4..b5d21285b6 100644
    function iis7_supports_permalinks() { 
    42524252 * @param array  $allowed_files Optional. List of allowed files.
    42534253 * @return int 0 means nothing is wrong, greater than 0 means something was wrong.
    42544254 */
    4255 function validate_file( $file, $allowed_files = '' ) {
    4256         if ( false !== strpos( $file, '..' ) )
     4255function validate_file( $file, $allowed_files = array() ) {
     4256        // `../` on its own is not allowed:
     4257        if ( '../' === $file ) {
    42574258                return 1;
     4259        }
    42584260
    4259         if ( false !== strpos( $file, './' ) )
     4261        // More than one occurence of `../` is not allowed:
     4262        if ( preg_match_all( '#\.\./#', $file, $matches, PREG_SET_ORDER ) && ( count( $matches ) > 1 ) ) {
    42604263                return 1;
     4264        }
     4265
     4266        // `../` which does not occur at the end of the path is not allowed:
     4267        if ( false !== strpos( $file, '../' ) && '../' !== mb_substr( $file, -3, 3 ) ) {
     4268                return 1;
     4269        }
    42614270
     4271        // Files not in the allowed file list are not allowed:
    42624272        if ( ! empty( $allowed_files ) && ! in_array( $file, $allowed_files ) )
    42634273                return 3;
    42644274
     4275        // Absolute Windows drive paths are not allowed:
    42654276        if (':' == substr( $file, 1, 1 ) )
    42664277                return 2;
    42674278
  • tests/phpunit/tests/functions.php

    diff --git tests/phpunit/tests/functions.php tests/phpunit/tests/functions.php
    index 7c8736ab67..6a2477ef0b 100644
    class Tests_Functions extends WP_UnitTestCase { 
    11611161                return $data;
    11621162        }
    11631163
     1164        /**
     1165         * Test file path validation
     1166         *
     1167         * @ticket 42016
     1168         * @dataProvider data_test_validate_file()
     1169         *
     1170         * @param string $file          File path.
     1171         * @param array  $allowed_files List of allowed files.
     1172         * @param int    $expected      Expected result.
     1173         */
     1174        public function test_validate_file( $file, $allowed_files, $expected ) {
     1175                $this->assertSame( $expected, validate_file( $file, $allowed_files ) );
     1176        }
     1177
     1178        /**
     1179         * Data provider for file validation.
     1180         *
     1181         * @return array {
     1182         *     @type array $0... {
     1183         *         @type string $0 File path.
     1184         *         @type array  $1 List of allowed files.
     1185         *         @type int    $2 Expected result.
     1186         *     }
     1187         * }
     1188         */
     1189        public function data_test_validate_file() {
     1190                return array(
     1191
     1192                        // Allowed files:
     1193                        array(
     1194                                null,
     1195                                array(),
     1196                                0,
     1197                        ),
     1198                        array(
     1199                                '',
     1200                                array(),
     1201                                0,
     1202                        ),
     1203                        array(
     1204                                ' ',
     1205                                array(),
     1206                                0,
     1207                        ),
     1208                        array(
     1209                                '.',
     1210                                array(),
     1211                                0,
     1212                        ),
     1213                        array(
     1214                                '..',
     1215                                array(),
     1216                                0,
     1217                        ),
     1218                        array(
     1219                                './',
     1220                                array(),
     1221                                0,
     1222                        ),
     1223                        array(
     1224                                'foo.ext',
     1225                                array( 'foo.ext' ),
     1226                                0,
     1227                        ),
     1228                        array(
     1229                                'dir/foo.ext',
     1230                                array(),
     1231                                0,
     1232                        ),
     1233                        array(
     1234                                'foo..ext',
     1235                                array(),
     1236                                0,
     1237                        ),
     1238                        array(
     1239                                'dir/dir/../',
     1240                                array(),
     1241                                0,
     1242                        ),
     1243
     1244                        // Directory traversal:
     1245                        array(
     1246                                '../',
     1247                                array(),
     1248                                1,
     1249                        ),
     1250                        array(
     1251                                '../../',
     1252                                array(),
     1253                                1,
     1254                        ),
     1255                        array(
     1256                                '../file.ext',
     1257                                array(),
     1258                                1,
     1259                        ),
     1260                        array(
     1261                                '../dir/../',
     1262                                array(),
     1263                                1,
     1264                        ),
     1265                        array(
     1266                                '/dir/dir/../../',
     1267                                array(),
     1268                                1,
     1269                        ),
     1270                        array(
     1271                                '/dir/dir/../../',
     1272                                array( '/dir/dir/../../' ),
     1273                                1,
     1274                        ),
     1275
     1276                        // Windows drives:
     1277                        array(
     1278                                'c:',
     1279                                array(),
     1280                                2,
     1281                        ),
     1282                        array(
     1283                                'C:/WINDOWS/system32',
     1284                                array( 'C:/WINDOWS/system32' ),
     1285                                2,
     1286                        ),
     1287
     1288                        // Disallowed files:
     1289                        array(
     1290                                'foo.ext',
     1291                                array( 'bar.ext' ),
     1292                                3,
     1293                        ),
     1294                        array(
     1295                                'foo.ext',
     1296                                array( '.ext' ),
     1297                                3,
     1298                        ),
     1299                        array(
     1300                                'path/foo.ext',
     1301                                array( 'foo.ext' ),
     1302                                3,
     1303                        ),
     1304
     1305                );
     1306        }
    11641307}