Issues (4967)

Security Analysis    not enabled

This project does not seem to handle request data directly as such no vulnerable execution paths were found.

  Cross-Site Scripting
Cross-Site Scripting enables an attacker to inject code into the response of a web-request that is viewed by other users. It can for example be used to bypass access controls, or even to take over other users' accounts.
  File Exposure
File Exposure allows an attacker to gain access to local files that he should not be able to access. These files can for example include database credentials, or other configuration files.
  File Manipulation
File Manipulation enables an attacker to write custom data to files. This potentially leads to injection of arbitrary code on the server.
  Object Injection
Object Injection enables an attacker to inject an object into PHP code, and can lead to arbitrary code execution, file exposure, or file manipulation attacks.
  Code Injection
Code Injection enables an attacker to execute arbitrary code on the server.
  Response Splitting
Response Splitting can be used to send arbitrary responses.
  File Inclusion
File Inclusion enables an attacker to inject custom files into PHP's file loading mechanism, either explicitly passed to include, or for example via PHP's auto-loading mechanism.
  Command Injection
Command Injection enables an attacker to inject a shell command that is execute with the privileges of the web-server. This can be used to expose sensitive data, or gain access of your server.
  SQL Injection
SQL Injection enables an attacker to execute arbitrary SQL code on your database server gaining access to user data, or manipulating user data.
  XPath Injection
XPath Injection enables an attacker to modify the parts of XML document that are read. If that XML document is for example used for authentication, this can lead to further vulnerabilities similar to SQL Injection.
  LDAP Injection
LDAP Injection enables an attacker to inject LDAP statements potentially granting permission to run unauthorized queries, or modify content inside the LDAP tree.
  Header Injection
  Other Vulnerability
This category comprises other attack vectors such as manipulating the PHP runtime, loading custom extensions, freezing the runtime, or similar.
  Regex Injection
Regex Injection enables an attacker to execute arbitrary code in your PHP process.
  XML Injection
XML Injection enables an attacker to read files on your local filesystem including configuration files, or can be abused to freeze your web-server process.
  Variable Injection
Variable Injection enables an attacker to overwrite program variables with custom data, and can lead to further vulnerabilities.
Unfortunately, the security analysis is currently not available for your project. If you are a non-commercial open-source project, please contact support to gain access.

src/wp-admin/setup-config.php (1 issue)

Labels
Severity

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
/**
3
 * Retrieves and creates the wp-config.php file.
4
 *
5
 * The permissions for the base directory must allow for writing files in order
6
 * for the wp-config.php to be created using this page.
7
 *
8
 * @package WordPress
9
 * @subpackage Administration
10
 */
11
12
/**
13
 * We are installing.
14
 */
15
define('WP_INSTALLING', true);
16
17
/**
18
 * We are blissfully unaware of anything.
19
 */
20
define('WP_SETUP_CONFIG', true);
21
22
/**
23
 * Disable error reporting
24
 *
25
 * Set this to error_reporting( -1 ) for debugging
26
 */
27
error_reporting(0);
28
29
if ( ! defined( 'ABSPATH' ) ) {
30
	define( 'ABSPATH', dirname( dirname( __FILE__ ) ) . '/' );
31
}
32
33
require( ABSPATH . 'wp-settings.php' );
34
35
/** Load WordPress Administration Upgrade API */
36
require_once( ABSPATH . 'wp-admin/includes/upgrade.php' );
37
38
/** Load WordPress Translation Install API */
39
require_once( ABSPATH . 'wp-admin/includes/translation-install.php' );
40
41
nocache_headers();
42
43
// Support wp-config-sample.php one level up, for the develop repo.
44
if ( file_exists( ABSPATH . 'wp-config-sample.php' ) )
45
	$config_file = file( ABSPATH . 'wp-config-sample.php' );
46
elseif ( file_exists( dirname( ABSPATH ) . '/wp-config-sample.php' ) )
47
	$config_file = file( dirname( ABSPATH ) . '/wp-config-sample.php' );
48
else
49
	wp_die( __( 'Sorry, I need a wp-config-sample.php file to work from. Please re-upload this file to your WordPress installation.' ) );
50
51
// Check if wp-config.php has been created
52
if ( file_exists( ABSPATH . 'wp-config.php' ) )
53
	wp_die( '<p>' . sprintf(
54
			/* translators: %s: install.php */
55
			__( "The file 'wp-config.php' already exists. If you need to reset any of the configuration items in this file, please delete it first. You may try <a href='%s'>installing now</a>." ),
56
			'install.php'
57
		) . '</p>'
58
	);
59
60
// Check if wp-config.php exists above the root directory but is not part of another install
61
if ( @file_exists( ABSPATH . '../wp-config.php' ) && ! @file_exists( ABSPATH . '../wp-settings.php' ) ) {
62
	wp_die( '<p>' . sprintf(
63
			/* translators: %s: install.php */
64
			__( "The file 'wp-config.php' already exists one level above your WordPress installation. If you need to reset any of the configuration items in this file, please delete it first. You may try <a href='%s'>installing now</a>." ),
65
			'install.php'
66
		) . '</p>'
67
	);
68
}
69
70
$step = isset( $_GET['step'] ) ? (int) $_GET['step'] : -1;
71
72
/**
73
 * Display setup wp-config.php file header.
74
 *
75
 * @ignore
76
 * @since 2.3.0
77
 *
78
 * @global string    $wp_local_package
79
 * @global WP_Locale $wp_locale
80
 *
81
 * @param string|array $body_classes
82
 */
83
function setup_config_display_header( $body_classes = array() ) {
84
	$body_classes = (array) $body_classes;
85
	$body_classes[] = 'wp-core-ui';
86
	if ( is_rtl() ) {
87
		$body_classes[] = 'rtl';
88
	}
89
90
	header( 'Content-Type: text/html; charset=utf-8' );
91
?>
92
<!DOCTYPE html>
93
<html xmlns="http://www.w3.org/1999/xhtml"<?php if ( is_rtl() ) echo ' dir="rtl"'; ?>>
94
<head>
95
	<meta name="viewport" content="width=device-width" />
96
	<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
97
	<meta name="robots" content="noindex,nofollow" />
98
	<title><?php _e( 'WordPress &rsaquo; Setup Configuration File' ); ?></title>
99
	<?php wp_admin_css( 'install', true ); ?>
100
</head>
101
<body class="<?php echo implode( ' ', $body_classes ); ?>">
102
<p id="logo"><a href="<?php echo esc_url( __( 'https://wordpress.org/' ) ); ?>" tabindex="-1"><?php _e( 'WordPress' ); ?></a></p>
103
<?php
104
} // end function setup_config_display_header();
105
106
$language = '';
107 View Code Duplication
if ( ! empty( $_REQUEST['language'] ) ) {
108
	$language = preg_replace( '/[^a-zA-Z_]/', '', $_REQUEST['language'] );
109
} elseif ( isset( $GLOBALS['wp_local_package'] ) ) {
110
	$language = $GLOBALS['wp_local_package'];
111
}
112
113
switch($step) {
114 View Code Duplication
	case -1:
115
		if ( wp_can_install_language_pack() && empty( $language ) && ( $languages = wp_get_available_translations() ) ) {
116
			setup_config_display_header( 'language-chooser' );
117
			echo '<h1 class="screen-reader-text">Select a default language</h1>';
118
			echo '<form id="setup" method="post" action="?step=0">';
119
			wp_install_language_form( $languages );
120
			echo '</form>';
121
			break;
122
		}
123
124
		// Deliberately fall through if we can't reach the translations API.
125
126
	case 0:
127 View Code Duplication
		if ( ! empty( $language ) ) {
128
			$loaded_language = wp_download_language_pack( $language );
129
			if ( $loaded_language ) {
130
				load_default_textdomain( $loaded_language );
131
				$GLOBALS['wp_locale'] = new WP_Locale();
132
			}
133
		}
134
135
		setup_config_display_header();
136
		$step_1 = 'setup-config.php?step=1';
137
		if ( isset( $_REQUEST['noapi'] ) ) {
138
			$step_1 .= '&amp;noapi';
139
		}
140
		if ( ! empty( $loaded_language ) ) {
141
			$step_1 .= '&amp;language=' . $loaded_language;
142
		}
143
?>
144
<h1 class="screen-reader-text"><?php _e( 'Before getting started' ) ?></h1>
145
<p><?php _e( 'Welcome to WordPress. Before getting started, we need some information on the database. You will need to know the following items before proceeding.' ) ?></p>
146
<ol>
147
	<li><?php _e( 'Database name' ); ?></li>
148
	<li><?php _e( 'Database username' ); ?></li>
149
	<li><?php _e( 'Database password' ); ?></li>
150
	<li><?php _e( 'Database host' ); ?></li>
151
	<li><?php _e( 'Table prefix (if you want to run more than one WordPress in a single database)' ); ?></li>
152
</ol>
153
<p><?php
154
	/* translators: %s: wp-config.php */
155
	printf( __( 'We&#8217;re going to use this information to create a %s file.' ),
156
		'<code>wp-config.php</code>'
157
	);
158
	?>
159
	<strong><?php
160
		/* translators: 1: wp-config-sample.php, 2: wp-config.php */
161
		printf( __( 'If for any reason this automatic file creation doesn&#8217;t work, don&#8217;t worry. All this does is fill in the database information to a configuration file. You may also simply open %1$s in a text editor, fill in your information, and save it as %2$s.' ),
162
			'<code>wp-config-sample.php</code>',
163
			'<code>wp-config.php</code>'
164
		);
165
	?></strong>
166
	<?php
167
	/* translators: %s: Codex URL */
168
	printf( __( 'Need more help? <a href="%s">We got it</a>.' ),
169
		__( 'https://codex.wordpress.org/Editing_wp-config.php' )
170
	);
171
?></p>
172
<p><?php _e( 'In all likelihood, these items were supplied to you by your Web Host. If you don&#8217;t have this information, then you will need to contact them before you can continue. If you&#8217;re all ready&hellip;' ); ?></p>
173
174
<p class="step"><a href="<?php echo $step_1; ?>" class="button button-large"><?php _e( 'Let&#8217;s go!' ); ?></a></p>
175
<?php
176
	break;
177
178
	case 1:
179
		load_default_textdomain( $language );
180
		$GLOBALS['wp_locale'] = new WP_Locale();
181
182
		setup_config_display_header();
183
	?>
184
<h1 class="screen-reader-text"><?php _e( 'Set up your database connection' ) ?></h1>
185
<form method="post" action="setup-config.php?step=2">
186
	<p><?php _e( 'Below you should enter your database connection details. If you&#8217;re not sure about these, contact your host.' ); ?></p>
187
	<table class="form-table">
188
		<tr>
189
			<th scope="row"><label for="dbname"><?php _e( 'Database Name' ); ?></label></th>
190
			<td><input name="dbname" id="dbname" type="text" size="25" value="wordpress" /></td>
191
			<td><?php _e( 'The name of the database you want to use with WordPress.' ); ?></td>
192
		</tr>
193
		<tr>
194
			<th scope="row"><label for="uname"><?php _e( 'Username' ); ?></label></th>
195
			<td><input name="uname" id="uname" type="text" size="25" value="<?php echo htmlspecialchars( _x( 'username', 'example username' ), ENT_QUOTES ); ?>" /></td>
196
			<td><?php _e( 'Your database username.' ); ?></td>
197
		</tr>
198
		<tr>
199
			<th scope="row"><label for="pwd"><?php _e( 'Password' ); ?></label></th>
200
			<td><input name="pwd" id="pwd" type="text" size="25" value="<?php echo htmlspecialchars( _x( 'password', 'example password' ), ENT_QUOTES ); ?>" autocomplete="off" /></td>
201
			<td><?php _e( 'Your database password.' ); ?></td>
202
		</tr>
203
		<tr>
204
			<th scope="row"><label for="dbhost"><?php _e( 'Database Host' ); ?></label></th>
205
			<td><input name="dbhost" id="dbhost" type="text" size="25" value="localhost" /></td>
206
			<td><?php
207
				/* translators: %s: localhost */
208
				printf( __( 'You should be able to get this info from your web host, if %s doesn&#8217;t work.' ),'<code>localhost</code>' );
209
			?></td>
210
		</tr>
211
		<tr>
212
			<th scope="row"><label for="prefix"><?php _e( 'Table Prefix' ); ?></label></th>
213
			<td><input name="prefix" id="prefix" type="text" value="wp_" size="25" /></td>
214
			<td><?php _e( 'If you want to run multiple WordPress installations in a single database, change this.' ); ?></td>
215
		</tr>
216
	</table>
217
	<?php if ( isset( $_GET['noapi'] ) ) { ?><input name="noapi" type="hidden" value="1" /><?php } ?>
218
	<input type="hidden" name="language" value="<?php echo esc_attr( $language ); ?>" />
219
	<p class="step"><input name="submit" type="submit" value="<?php echo htmlspecialchars( __( 'Submit' ), ENT_QUOTES ); ?>" class="button button-large" /></p>
220
</form>
221
<?php
222
	break;
223
224
	case 2:
225
	load_default_textdomain( $language );
226
	$GLOBALS['wp_locale'] = new WP_Locale();
227
228
	$dbname = trim( wp_unslash( $_POST[ 'dbname' ] ) );
229
	$uname = trim( wp_unslash( $_POST[ 'uname' ] ) );
230
	$pwd = trim( wp_unslash( $_POST[ 'pwd' ] ) );
231
	$dbhost = trim( wp_unslash( $_POST[ 'dbhost' ] ) );
232
	$prefix = trim( wp_unslash( $_POST[ 'prefix' ] ) );
233
234
	$step_1 = 'setup-config.php?step=1';
235
	$install = 'install.php';
236
	if ( isset( $_REQUEST['noapi'] ) ) {
237
		$step_1 .= '&amp;noapi';
238
	}
239
240
	if ( ! empty( $language ) ) {
241
		$step_1 .= '&amp;language=' . $language;
242
		$install .= '?language=' . $language;
243
	} else {
244
		$install .= '?language=en_US';
245
	}
246
247
	$tryagain_link = '</p><p class="step"><a href="' . $step_1 . '" onclick="javascript:history.go(-1);return false;" class="button button-large">' . __( 'Try again' ) . '</a>';
248
249
	if ( empty( $prefix ) )
250
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" must not be empty.' . $tryagain_link ) );
251
252
	// Validate $prefix: it can only contain letters, numbers and underscores.
253
	if ( preg_match( '|[^a-z0-9_]|i', $prefix ) )
254
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" can only contain numbers, letters, and underscores.' . $tryagain_link ) );
255
256
	// Test the db connection.
257
	/**#@+
258
	 * @ignore
259
	 */
260
	define('DB_NAME', $dbname);
261
	define('DB_USER', $uname);
262
	define('DB_PASSWORD', $pwd);
263
	define('DB_HOST', $dbhost);
264
	/**#@-*/
265
266
	// Re-construct $wpdb with these new values.
267
	unset( $wpdb );
268
	require_wp_db();
269
270
	/*
271
	 * The wpdb constructor bails when WP_SETUP_CONFIG is set, so we must
272
	 * fire this manually. We'll fail here if the values are no good.
273
	 */
274
	$wpdb->db_connect();
275
276
	if ( ! empty( $wpdb->error ) )
277
		wp_die( $wpdb->error->get_error_message() . $tryagain_link );
278
279
	$wpdb->query( "SELECT $prefix" );
280
	if ( ! $wpdb->last_error ) {
281
		// MySQL was able to parse the prefix as a value, which we don't want. Bail.
282
		wp_die( __( '<strong>ERROR</strong>: "Table Prefix" is invalid.' ) );
283
	}
284
285
	// Generate keys and salts using secure CSPRNG; fallback to API if enabled; further fallback to original wp_generate_password().
286
	try {
287
		$chars = 'abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789!@#$%^&*()-_ []{}<>~`+=,.;:/?|';
288
		$max = strlen($chars) - 1;
289
		for ( $i = 0; $i < 8; $i++ ) {
290
			$key = '';
291
			for ( $j = 0; $j < 64; $j++ ) {
292
				$key .= substr( $chars, random_int( 0, $max ), 1 );
293
			}
294
			$secret_keys[] = $key;
295
		}
296
	} catch ( Exception $ex ) {
297
		$no_api = isset( $_POST['noapi'] );
298
299
		if ( ! $no_api ) {
300
			$secret_keys = wp_remote_get( 'https://api.wordpress.org/secret-key/1.1/salt/' );
301
		}
302
303
		if ( $no_api || is_wp_error( $secret_keys ) ) {
304
			$secret_keys = array();
305
			for ( $i = 0; $i < 8; $i++ ) {
306
				$secret_keys[] = wp_generate_password( 64, true, true );
307
			}
308
		} else {
309
			$secret_keys = explode( "\n", wp_remote_retrieve_body( $secret_keys ) );
0 ignored issues
show
It seems like $secret_keys can also be of type object<WP_Error>; however, wp_remote_retrieve_body() does only seem to accept array, maybe add an additional type check?

If a method or function can return multiple different values and unless you are sure that you only can receive a single value in this context, we recommend to add an additional type check:

/**
 * @return array|string
 */
function returnsDifferentValues($x) {
    if ($x) {
        return 'foo';
    }

    return array();
}

$x = returnsDifferentValues($y);
if (is_array($x)) {
    // $x is an array.
}

If this a common case that PHP Analyzer should handle natively, please let us know by opening an issue.

Loading history...
310
			foreach ( $secret_keys as $k => $v ) {
311
				$secret_keys[$k] = substr( $v, 28, 64 );
312
			}
313
		}
314
	}
315
316
	$key = 0;
317
	foreach ( $config_file as $line_num => $line ) {
318
		if ( '$table_prefix  =' == substr( $line, 0, 16 ) ) {
319
			$config_file[ $line_num ] = '$table_prefix  = \'' . addcslashes( $prefix, "\\'" ) . "';\r\n";
320
			continue;
321
		}
322
323
		if ( ! preg_match( '/^define\(\'([A-Z_]+)\',([ ]+)/', $line, $match ) )
324
			continue;
325
326
		$constant = $match[1];
327
		$padding  = $match[2];
328
329
		switch ( $constant ) {
330
			case 'DB_NAME'     :
331
			case 'DB_USER'     :
332
			case 'DB_PASSWORD' :
333
			case 'DB_HOST'     :
334
				$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . addcslashes( constant( $constant ), "\\'" ) . "');\r\n";
335
				break;
336
			case 'DB_CHARSET'  :
337
				if ( 'utf8mb4' === $wpdb->charset || ( ! $wpdb->charset && $wpdb->has_cap( 'utf8mb4' ) ) ) {
338
					$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'utf8mb4');\r\n";
339
				}
340
				break;
341
			case 'AUTH_KEY'         :
342
			case 'SECURE_AUTH_KEY'  :
343
			case 'LOGGED_IN_KEY'    :
344
			case 'NONCE_KEY'        :
345
			case 'AUTH_SALT'        :
346
			case 'SECURE_AUTH_SALT' :
347
			case 'LOGGED_IN_SALT'   :
348
			case 'NONCE_SALT'       :
349
				$config_file[ $line_num ] = "define('" . $constant . "'," . $padding . "'" . $secret_keys[$key++] . "');\r\n";
350
				break;
351
		}
352
	}
353
	unset( $line );
354
355
	if ( ! is_writable(ABSPATH) ) :
356
		setup_config_display_header();
357
?>
358
<p><?php
359
	/* translators: %s: wp-config.php */
360
	printf( __( 'Sorry, but I can&#8217;t write the %s file.' ), '<code>wp-config.php</code>' );
361
?></p>
362
<p><?php
363
	/* translators: %s: wp-config.php */
364
	printf( __( 'You can create the %s manually and paste the following text into it.' ), '<code>wp-config.php</code>' );
365
?></p>
366
<textarea id="wp-config" cols="98" rows="15" class="code" readonly="readonly"><?php
367
		foreach ( $config_file as $line ) {
368
			echo htmlentities($line, ENT_COMPAT, 'UTF-8');
369
		}
370
?></textarea>
371
<p><?php _e( 'After you&#8217;ve done that, click &#8220;Run the install.&#8221;' ); ?></p>
372
<p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the install' ); ?></a></p>
373
<script>
374
(function(){
375
if ( ! /iPad|iPod|iPhone/.test( navigator.userAgent ) ) {
376
	var el = document.getElementById('wp-config');
377
	el.focus();
378
	el.select();
379
}
380
})();
381
</script>
382
<?php
383
	else :
384
		/*
385
		 * If this file doesn't exist, then we are using the wp-config-sample.php
386
		 * file one level up, which is for the develop repo.
387
		 */
388
		if ( file_exists( ABSPATH . 'wp-config-sample.php' ) )
389
			$path_to_wp_config = ABSPATH . 'wp-config.php';
390
		else
391
			$path_to_wp_config = dirname( ABSPATH ) . '/wp-config.php';
392
393
		$handle = fopen( $path_to_wp_config, 'w' );
394
		foreach ( $config_file as $line ) {
395
			fwrite( $handle, $line );
396
		}
397
		fclose( $handle );
398
		chmod( $path_to_wp_config, 0666 );
399
		setup_config_display_header();
400
?>
401
<h1 class="screen-reader-text"><?php _e( 'Successful database connection' ) ?></h1>
402
<p><?php _e( 'All right, sparky! You&#8217;ve made it through this part of the installation. WordPress can now communicate with your database. If you are ready, time now to&hellip;' ); ?></p>
403
404
<p class="step"><a href="<?php echo $install; ?>" class="button button-large"><?php _e( 'Run the install' ); ?></a></p>
405
<?php
406
	endif;
407
	break;
408
}
409
?>
410
<?php wp_print_scripts( 'language-chooser' ); ?>
411
</body>
412
</html>
413