CVE-2023-25570: Missing Authentication for Critical Function (CWE-306)
value: Apollo is a configuration management system. Prior to version 2.1.0, there are potential security issues if users expose apollo-configservice to the internet, which is not recommended. This is because there is no authentication feature enabled for the built-in eureka service. Malicious hackers may access eureka directly to mock apollo-configservice and apollo-adminservice. Login authentication for eureka was added in version 2.1.0. As a workaround, avoid exposing apollo-configservice to the internet.
CWE description: The product does not perform any authentication for functionality that requires a provable user identity or consumes a significant amount of resources.
CVSS v3 base score: 7.5
Published: 2023-02-20T16:15Z
Repository: https://github.com/apolloconfig/apollo
Language: Markdown
Files changed: CHANGES.md, apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServerEurekaServerConfigure.java, apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/TestWebSecurityConfig.java, docs/en/deployment/distributed-deployment-guide.md, docs/en/usage/apollo-user-guide.md, docs/zh/deployment/distributed-deployment-guide.md, docs/zh/usage/apollo-user-guide.md
Commit date: 2022-12-14 08:47:53 +0800
Commit message: Enable login authentication for eureka

Diff: diff --git a/CHANGES.md b/CHANGES.md
index 53cc8e5f0..3e688b5c6 100644
--- a/CHANGES.md
+++ b/CHANGES.md
@@ -37,8 +37,9 @@ Apollo 2.1.0
 * [fix doc bug](https://github.com/apolloconfig/apollo/pull/4579)
 * [fix Grayscale release Item Value length limit can not be synchronized with its main version](https://github.com/apolloconfig/apollo/pull/4622)
 * [feat: use can change spring.profiles.active's value without rebuild project](https://github.com/apolloconfig/apollo/pull/4616)
 * [refactor: remove app.properties and move some config file's location](https://github.com/apolloconfig/apollo/pull/4637)
 * [Fix the problem of deleting blank items appear at the end](https://github.com/apolloconfig/apollo/pull/4662)
+* [Enable login authentication for eureka](https://github.com/apolloconfig/apollo/pull/4663)
 
 ------------------
 All issues and pull requests are [here](https://github.com/apolloconfig/apollo/milestone/11?closed=1)
diff --git a/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServerEurekaServerConfigure.java b/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServerEurekaServerConfigure.java
index 5ff1ce468..6dad7f19a 100644
--- a/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServerEurekaServerConfigure.java
+++ b/apollo-configservice/src/main/java/com/ctrip/framework/apollo/configservice/ConfigServerEurekaServerConfigure.java
@@ -14,19 +14,65 @@
  * limitations under the License.
  *
  */
 package com.ctrip.framework.apollo.configservice;
 
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.beans.factory.annotation.Value;
 import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
 import org.springframework.cloud.netflix.eureka.server.EnableEurekaServer;
 import org.springframework.context.annotation.Configuration;
+import org.springframework.core.annotation.Order;
+import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
+import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
+import org.springframework.security.config.annotation.web.builders.HttpSecurity;
+import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
 /**
  * Start Eureka Server annotations according to configuration
  *
  * @author Zhiqiang Lin(linzhiqiang0514@163.com)
  */
 @Configuration
 @EnableEurekaServer
 @ConditionalOnProperty(name = "apollo.eureka.server.enabled", havingValue = "true", matchIfMissing = true)
 public class ConfigServerEurekaServerConfigure {
+
+  @Order(99)
+  @Configuration
+  static class EurekaServerSecurityConfigurer extends WebSecurityConfigurerAdapter {
+
+    private static final String EUREKA_ROLE = "EUREKA";
+
+    @Value("${apollo.eureka.server.security.enabled:false}")
+    private boolean eurekaSecurityEnabled;
+    @Value("${apollo.eureka.server.security.username:}")
+    private String username;
+    @Value("${apollo.eureka.server.security.password:}")
+    private String password;
+
+    @Override
+    protected void configure(HttpSecurity http) throws Exception {
+      http.csrf().disable();
+      http.httpBasic();
+      if (eurekaSecurityEnabled) {
+        http.authorizeRequests()
+            .antMatchers("/eureka/apps/**", "/eureka/instances/**", "/eureka/peerreplication/**")
+            .hasRole(EUREKA_ROLE)
+            .antMatchers("/**").permitAll();
+      }
+    }
+
+    @Autowired
+    public void configureEurekaUser(AuthenticationManagerBuilder auth) throws Exception {
+      if (!eurekaSecurityEnabled) {
+        return;
+      }
+      InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> configurer = auth
+          .getConfigurer(InMemoryUserDetailsManagerConfigurer.class);
+      if (configurer == null) {
+        configurer = auth.inMemoryAuthentication();
+      }
+      configurer.withUser(username).password(password).roles(EUREKA_ROLE);
+    }
+  }
 }
diff --git a/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/TestWebSecurityConfig.java b/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/TestWebSecurityConfig.java
index db1a9c5e1..60d4fe153 100644
--- a/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/TestWebSecurityConfig.java
+++ b/apollo-configservice/src/test/java/com/ctrip/framework/apollo/configservice/controller/TestWebSecurityConfig.java
@@ -20,11 +20,11 @@ import org.springframework.context.annotation.Configuration;
 import org.springframework.core.annotation.Order;
 import org.springframework.security.config.annotation.web.builders.HttpSecurity;
 import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
 
 @Configuration
-@Order(99)
+@Order(98)
 public class TestWebSecurityConfig extends WebSecurityConfigurerAdapter {
 
   @Override
   protected void configure(HttpSecurity http) throws Exception {
     http.httpBasic();
diff --git a/docs/en/deployment/distributed-deployment-guide.md b/docs/en/deployment/distributed-deployment-guide.md
index 6ceaff33a..8175585e7 100644
--- a/docs/en/deployment/distributed-deployment-guide.md
+++ b/docs/en/deployment/distributed-deployment-guide.md
@@ -1526,5 +1526,33 @@ admin-services.access.tokens=098f6bcd4621d373cade4e832627b4f6,ad0234829205b90331
 ### 3.2.8 `apollo.access-key.auth-time-diff-tolerance` - Configure server-side AccessKey checksum tolerance for time deviation
 
 > For version 2.0.0 and above
 
 The default value is 60, in seconds. Since the key authentication needs to verify the time, there may be time deviation between the time of the client and the time of the server, if the deviation is too large, the authentication will fail, this configuration can configure the tolerated time deviation size, the default is 60 seconds.
+
+### 3.2.9 apollo.eureka.server.security.enabled - Configure whether to enable Eureka login authentication
+
+> For version 2.1.0 and above
+
+The default value is false, if you want to improve security (such as when apollo is exposed to the public network), you can enable login authentication for eureka by setting this configuration to true.
+
+Note that if eureka login authentication is enabled, the addresses in [eureka.service.url](#_321-eurekaserviceurl-eureka-service-url) needs to be configured with a user name and password, such as:
+
+```
+http://some-user-name:some-password@1.1.1.1:8080/eureka/, http://some-user-name:some-password@2.2.2.2:8080/eureka/
+```
+
+Among them, `some-user-name` and `some-password` need to be consistent with the configuration items of `apollo.eureka.server.security.username` and `apollo.eureka.server.security.password`.
+
+### 3.2.10 apollo.eureka.server.security.username - Configure the username of Eureka server
+
+> For version 2.1.0 and above
+
+Configure the login username of eureka server, which needs to be used together with [apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-configure-whether-to-enable-eureka-login-authentication).
+
+> Note that the username cannot be configured as apollo.
+
+### 3.2.11 apollo.eureka.server.security.password - Configure the password of Eureka server
+
+> For version 2.1.0 and above
+
+Configure the login password of eureka server, which needs to be used together with [apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-configure-whether-to-enable-eureka-login-authentication).
\ No newline at end of file
diff --git a/docs/en/usage/apollo-user-guide.md b/docs/en/usage/apollo-user-guide.md
index d066a4102..422ce0844 100644
--- a/docs/en/usage/apollo-user-guide.md
+++ b/docs/en/usage/apollo-user-guide.md
@@ -502,6 +502,7 @@ Apollo supports fine-grained permissions control, so please make sure to control
 
 In addition to user permissions, system access also needs to be considered in terms of.
 
 1. `apollo-configservice` and `apollo-adminservice` are designed based on the intranet trusted network, so for security reasons, `apollo-configservice` and `apollo-adminservice` are prohibited from being exposed directly to the public network
 2. For sensitive configurations, consider enabling [access secret key](en/usage/apollo-user-guide?id=_62-configuring-access-keys) so that only authenticated clients can access sensitive configurations
-3. 1.7.1 and above can consider enabling [access control](en/deployment/distributed-deployment-guide?id=_326-admin-servicesaccesscontrolenabled-configure-whether-apollo-adminservice-has-access-control-enabled) for `apollo-adminservice`, so that only [controlled](en/deployment/distributed-deployment-guide?id=_3112-admin-servicesaccesstokens-set-the-access-token-required-by-apollo-portal-to-access-the-apollo-adminservice-for-each-environment) `apollo-portal` can access the corresponding interface to enhance security
+3. version 1.7.1 and above can consider enabling [access control](en/deployment/distributed-deployment-guide?id=_326-admin-servicesaccesscontrolenabled-configure-whether-apollo-adminservice-has-access-control-enabled) for `apollo-adminservice`, so that only [controlled](en/deployment/distributed-deployment-guide?id=_3112-admin-servicesaccesstokens-set-the-access-token-required-by-apollo-portal-to-access-the-apollo-adminservice-for-each-environment) `apollo-portal` can access the corresponding interface to enhance security
+4. version 2.1.0 and above can consider enabling [access control](en/deployment/distributed-deployment-guide?id=_329-apolloeurekaserversecurityenabled-configure-whether-to-enable-eureka-login-authentication) for `eureka`, so that only controlled `apollo-configservice` and `apollo-adminservice` can be registered to `eureka` to enhance security
\ No newline at end of file
diff --git a/docs/zh/deployment/distributed-deployment-guide.md b/docs/zh/deployment/distributed-deployment-guide.md
index 1bd507bef..1e0c2a70c 100644
--- a/docs/zh/deployment/distributed-deployment-guide.md
+++ b/docs/zh/deployment/distributed-deployment-guide.md
@@ -1468,5 +1468,32 @@ admin-service.access.tokens=098f6bcd4621d373cade4e832627b4f6,ad0234829205b903319
 ### 3.2.8 apollo.access-key.auth-time-diff-tolerance - 配置服务端AccessKey校验容忍的时间偏差
 
 > 适用于2.0.0及以上版本
 
 默认值为60，单位为秒。由于密钥认证时需要校验时间，客户端与服务端的时间可能存在时间偏差，如果偏差太大会导致认证失败，此配置可以配置容忍的时间偏差大小，默认为60秒。
+
+### 3.2.9 apollo.eureka.server.security.enabled - 配置是否开启eureka server的登录认证
+
+> 适用于2.1.0及以上版本
+
+默认为false，如果希望提升安全性（比如公网可访问的场景），可以设置该配置项为true启用登录认证。
+
+需要注意的是，开启登录认证后，[eureka.service.url](#_321-eurekaserviceurl-eureka服务url)中的地址需要配置用户名和密码，如：
+
+```
+http://some-user-name:some-password@1.1.1.1:8080/eureka/,http://some-user-name:some-password@2.2.2.2:8080/eureka/
+```
+其中`some-user-name`和`some-password`需要和`apollo.eureka.server.security.username`以及`apollo.eureka.server.security.password`的配置项一致。
+
+### 3.2.10 apollo.eureka.server.security.username - 配置eureka server的登录用户名
+
+> 适用于2.1.0及以上版本
+
+配置eureka server的登录用户名，需要和[apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-配置是否开启eureka-server的登录认证)一起使用。
+
+> 注意用户名不能配置为apollo
+
+### 3.2.11 apollo.eureka.server.security.password - 配置eureka server的登录密码
+
+> 适用于2.1.0及以上版本
+
+配置eureka server的登录密码，需要和[apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-配置是否开启eureka-server的登录认证)一起使用。
\ No newline at end of file
diff --git a/docs/zh/usage/apollo-user-guide.md b/docs/zh/usage/apollo-user-guide.md
index 4f6d17617..33bd4b0a5 100644
--- a/docs/zh/usage/apollo-user-guide.md
+++ b/docs/zh/usage/apollo-user-guide.md
@@ -475,5 +475,6 @@ Apollo 支持细粒度的权限控制，请务必根据实际情况做好权限
 除了用户权限，在系统访问上也需要加以考虑：
 
 1. `apollo-configservice`和`apollo-adminservice`是基于内网可信网络设计的，所以出于安全考虑，禁止`apollo-configservice`和`apollo-adminservice`直接暴露在公网
 2. 对敏感配置可以考虑开启[访问秘钥](#_62-%e9%85%8d%e7%bd%ae%e8%ae%bf%e9%97%ae%e5%af%86%e9%92%a5)，从而只有经过身份验证的客户端才能访问敏感配置
 3. 1.7.1及以上版本可以考虑为`apollo-adminservice`开启[访问控制](zh/deployment/distributed-deployment-guide?id=_326-admin-serviceaccesscontrolenabled-配置apollo-adminservice是否开启访问控制)，从而只有[受控的](zh/deployment/distributed-deployment-guide?id=_3112-admin-serviceaccesstokens-设置apollo-portal访问各环境apollo-adminservice所需的access-token)`apollo-portal`才能访问对应接口，增强安全性
+4. 2.1.0及以上版本可以考虑为`eureka`开启[访问控制](zh/deployment/distributed-deployment-guide?id=_329-apolloeurekaserversecurityenabled-配置是否开启eureka-server的登录认证)，从而只有受控的`apollo-configservice`和`apollo-adminservice`可以注册到`eureka`，增强安全性
\ No newline at end of file

Vulnerable code: @Order(99)
3. 1.7.1 and above can consider enabling [access control](en/deployment/distributed-deployment-guide?id=_326-admin-servicesaccesscontrolenabled-configure-whether-apollo-adminservice-has-access-control-enabled) for `apollo-adminservice`, so that only [controlled](en/deployment/distributed-deployment-guide?id=_3112-admin-servicesaccesstokens-set-the-access-token-required-by-apollo-portal-to-access-the-apollo-adminservice-for-each-environment) `apollo-portal` can access the corresponding interface to enhance security
Fixed code: * [Enable login authentication for eureka](https://github.com/apolloconfig/apollo/pull/4663)
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.core.annotation.Order;
import org.springframework.security.config.annotation.authentication.builders.AuthenticationManagerBuilder;
import org.springframework.security.config.annotation.authentication.configurers.provisioning.InMemoryUserDetailsManagerConfigurer;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;

  @Order(99)
  @Configuration
  static class EurekaServerSecurityConfigurer extends WebSecurityConfigurerAdapter {

    private static final String EUREKA_ROLE = "EUREKA";

    @Value("${apollo.eureka.server.security.enabled:false}")
    private boolean eurekaSecurityEnabled;
    @Value("${apollo.eureka.server.security.username:}")
    private String username;
    @Value("${apollo.eureka.server.security.password:}")
    private String password;

    @Override
    protected void configure(HttpSecurity http) throws Exception {
      http.csrf().disable();
      http.httpBasic();
      if (eurekaSecurityEnabled) {
        http.authorizeRequests()
            .antMatchers("/eureka/apps/**", "/eureka/instances/**", "/eureka/peerreplication/**")
            .hasRole(EUREKA_ROLE)
            .antMatchers("/**").permitAll();
      }
    }

    @Autowired
    public void configureEurekaUser(AuthenticationManagerBuilder auth) throws Exception {
      if (!eurekaSecurityEnabled) {
        return;
      }
      InMemoryUserDetailsManagerConfigurer<AuthenticationManagerBuilder> configurer = auth
          .getConfigurer(InMemoryUserDetailsManagerConfigurer.class);
      if (configurer == null) {
        configurer = auth.inMemoryAuthentication();
      }
      configurer.withUser(username).password(password).roles(EUREKA_ROLE);
    }
  }
@Order(98)

### 3.2.9 apollo.eureka.server.security.enabled - Configure whether to enable Eureka login authentication

> For version 2.1.0 and above

The default value is false, if you want to improve security (such as when apollo is exposed to the public network), you can enable login authentication for eureka by setting this configuration to true.

Note that if eureka login authentication is enabled, the addresses in [eureka.service.url](#_321-eurekaserviceurl-eureka-service-url) needs to be configured with a user name and password, such as:

```
http://some-user-name:some-password@1.1.1.1:8080/eureka/, http://some-user-name:some-password@2.2.2.2:8080/eureka/
```

Among them, `some-user-name` and `some-password` need to be consistent with the configuration items of `apollo.eureka.server.security.username` and `apollo.eureka.server.security.password`.

### 3.2.10 apollo.eureka.server.security.username - Configure the username of Eureka server

> For version 2.1.0 and above

Configure the login username of eureka server, which needs to be used together with [apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-configure-whether-to-enable-eureka-login-authentication).

> Note that the username cannot be configured as apollo.

### 3.2.11 apollo.eureka.server.security.password - Configure the password of Eureka server

> For version 2.1.0 and above

Configure the login password of eureka server, which needs to be used together with [apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-configure-whether-to-enable-eureka-login-authentication).
3. version 1.7.1 and above can consider enabling [access control](en/deployment/distributed-deployment-guide?id=_326-admin-servicesaccesscontrolenabled-configure-whether-apollo-adminservice-has-access-control-enabled) for `apollo-adminservice`, so that only [controlled](en/deployment/distributed-deployment-guide?id=_3112-admin-servicesaccesstokens-set-the-access-token-required-by-apollo-portal-to-access-the-apollo-adminservice-for-each-environment) `apollo-portal` can access the corresponding interface to enhance security
4. version 2.1.0 and above can consider enabling [access control](en/deployment/distributed-deployment-guide?id=_329-apolloeurekaserversecurityenabled-configure-whether-to-enable-eureka-login-authentication) for `eureka`, so that only controlled `apollo-configservice` and `apollo-adminservice` can be registered to `eureka` to enhance security

### 3.2.9 apollo.eureka.server.security.enabled - 配置是否开启eureka server的登录认证

> 适用于2.1.0及以上版本

默认为false，如果希望提升安全性（比如公网可访问的场景），可以设置该配置项为true启用登录认证。

需要注意的是，开启登录认证后，[eureka.service.url](#_321-eurekaserviceurl-eureka服务url)中的地址需要配置用户名和密码，如：

```
http://some-user-name:some-password@1.1.1.1:8080/eureka/,http://some-user-name:some-password@2.2.2.2:8080/eureka/
```
其中`some-user-name`和`some-password`需要和`apollo.eureka.server.security.username`以及`apollo.eureka.server.security.password`的配置项一致。

### 3.2.10 apollo.eureka.server.security.username - 配置eureka server的登录用户名

> 适用于2.1.0及以上版本

配置eureka server的登录用户名，需要和[apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-配置是否开启eureka-server的登录认证)一起使用。

> 注意用户名不能配置为apollo

### 3.2.11 apollo.eureka.server.security.password - 配置eureka server的登录密码

> 适用于2.1.0及以上版本

配置eureka server的登录密码，需要和[apollo.eureka.server.security.enabled](#_329-apolloeurekaserversecurityenabled-配置是否开启eureka-server的登录认证)一起使用。
4. 2.1.0及以上版本可以考虑为`eureka`开启[访问控制](zh/deployment/distributed-deployment-guide?id=_329-apolloeurekaserversecurityenabled-配置是否开启eureka-server的登录认证)，从而只有受控的`apollo-configservice`和`apollo-adminservice`可以注册到`eureka`，增强安全性