Wordpress Redux Framework Class Redux Helpers Php Sensitive Information Leakage Vulnerability Cve 2021 38314
WordPress Redux Framework class-redux-helpers.php Sensitive information leakage vulnerability CVE-2021-38314
Vulnerability Description
In August 2021, there was an unauthorized sensitive information leakage vulnerability in Redux Framework. The CVE number is CVE-2021-38314, affecting v4.2.11 and below. Sending a specific request packet can obtain server sensitive information without authorization.
Vulnerability Impact
Redux Framework <= v4.2.11
Plugin Name
Redux Framework
https://github.com/reduxframework/redux-framework
Vulnerability reappears
The impact range is below v4.211. Let’s take a look at the update differences between versions.
Here all the functions registered with add_action are deleted. Please check the function related code for local installation.
1
2
3
4
5
6
7
8
9
10
$support_hash = md5( md5( Redux_Functions_Ex::hash_key() . '-redux' ) . '-support' );
add_action( 'wp_ajax_nopriv_' . $support_hash, array( 'Redux_Helpers', 'support_args' ) );
add_action( 'wp_ajax_' . $support_hash, array( 'Redux_Helpers', 'support_args' ) );
$hash_arg = md5( trailingslashit( network_site_url() ) . '-redux' );
add_action( 'wp_ajax_nopriv_' . $hash_arg, array( 'Redux_Helpers', 'hash_arg' ) );
add_action( 'wp_ajax_' . $hash_arg, array( 'Redux_Helpers', 'hash_arg' ) );
add_action( 'wp_ajax_redux_support_hash', array( 'Redux_Functions', 'support_hash' ) );
add_filter( 'redux/tracking/options', array( 'Redux_Helpers', 'redux_stats_additions' ) );
View the add_action registered functions hash_arg() and support_args()
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
public static function hash_arg() {
echo esc_html( md5( Redux_Functions_Ex::hash_key() . '-redux' ) );
die();
}
public static function support_args() {
header( 'Expires: Mon, 26 Jul 1997 05:00:00 GMT' );
header( 'Last-Modified: ' . gmdate( 'D, d M Y H:i:s' ) . 'GMT' );
header( 'Expires: Sat, 26 Jul 1997 05:00:00 GMT' );
header( 'Cache-Control: no-store, no-cache, must-revalidate' );
header( 'Cache-Control: post-check=0, pre-check=0', false );
header( 'Pragma: no-cache' );
$instances = Redux::all_instances();
if ( isset( $_REQUEST['i'] ) && ! empty( $_REQUEST['i'] ) ) { // phpcs:ignore WordPress.Security.NonceVerification
if ( is_array( $instances ) && ! empty( $instances ) ) {
foreach ( $instances as $opt_name => $data ) {
if ( md5( $opt_name . '-debug' ) === $_REQUEST['i'] ) { // phpcs:ignore WordPress.Security.NonceVerification
$array = $data;
}
}
}
if ( isset( $array ) ) {
// We only want the extension names and versions.
$array->extensions = self::get_extensions( $opt_name );
$to_return = array();
// Filter out all the unwanted data.
foreach ( $array as $key => $value ) {
if ( in_array(
$key,
array(
// 'fields',
'extensions',
'sections',
'args',
// 'field_types'
),
true
) ) {
$to_return[ $key ] = $value;
} else { // phpcs:ignore Generic.CodeAnalysis.EmptyStatement
// phpcs:ignore Squiz.PHP.CommentedOutCode
/* echo $key.PHP_EOL; */
}
}
$array = $to_return;
} else {
die();
}
} else {
$array = self::get_statistics_object();
if ( is_array( $instances ) && ! empty( $instances ) ) {
$array['instances'] = array();
foreach ( $instances as $opt_name => $data ) {
$array['instances'][] = $opt_name;
}
}
$array['key'] = md5( Redux_Functions_Ex::hash_key() );
}
ksort( $array ); // Let's make that pretty.
// phpcs:ignored WordPress.PHP.NoSilencedErrors, WordPress.Security.EscapeOutput
echo @htmlspecialchars( @wp_json_encode( $array, true ), ENT_QUOTES );
die();
}
support_args() function $_REQUEST[‘i’] is empty, and comes to another branch
1
2
3
4
5
6
7
8
9
10
} else {
$array = self::get_statistics_object();
if ( is_array( $instances ) && ! empty( $instances ) ) {
$array['instances'] = array();
foreach ( $instances as $opt_name => $data ) {
$array['instances'][] = $opt_name;
}
}
$array['key'] = md5( Redux_Functions_Ex::hash_key() );
}
Track the get_statistics_object() function, which can obtain information about environment variables such as plugins
Go back and see that the function is wp_ajax_nopriv_* and can be called unauthorized
The variable $support_hash is required, and the hash_key() method is tracked.
1
$support_hash = md5( md5( Redux_Functions_Ex::hash_key() . '-redux' ) . '-support' );
The AUTH_KEY parameter exists in wp-config.php, which is a random value
Here comes the hash_arg() function
1
2
3
4
public static function hash_arg() {
echo esc_html( md5( Redux_Functions_Ex::hash_key() . '-redux' ) );
die();
}
Here the function in Redux_Functions_Ex::hash_key() is called, and the md5 value is returned.
Going back to the code just now, we can find that the result is also the parameters we need to know about $support_hash. The following is the equivalent replacement.
1
$support_hash = md5(hash_arg(). '-support' );
In this way we get a utilization chain
1
2
3
4
5
6
7
8
9
$hash_arg = md5( trailingslashit( network_site_url() ) . '-redux' );
add_action( 'wp_ajax_nopriv_' . $hash_arg, array( 'Redux_Helpers', 'hash_arg' ) );
|
获取 md5( Redux_Functions_Ex::hash_key() . '-redux') 值
|
$support_hash = md5( md5( Redux_Functions_Ex::hash_key() . '-redux' ) . '-support' );
add_action( 'wp_ajax_nopriv_' . $support_hash, array( 'Redux_Helpers', 'support_args' ) );
|
调用函数 support_args 获取系统敏感信息
Successfully obtained plug-in version and other related information