Dear students, I believe that we have seen the information about the vulnerability of SpringCloudGateway recently. Since this is the case, don’t you hurry up to modify your own program? Even if you’re not involved in this bug, I suggest you check it out, and maybe you’ll learn something you didn’t know.

This article project code gitee address: gitee.com/wei_rong_xi…

What is SpringCloudGateway?

Before we start talking about vulnerabilities, what is SpringCloudGateway?

Let’s take a quick look at what SpringCloudGateway is used to build API gateways on top of Spring WebFlux, aiming to provide a simple and efficient way to route apis and provide crosscutting concerns to them.

The above is very official and not easy to understand. In fact, I can simply describe it in daily use for your understanding:

  • The most front-end unified API entry, I can also call itBFF (banked - for - front)!
  • As a request dynamic proxy, request forwarding, route filtering, similar to nginx capabilities
  • As a unified authentication module for services, such as JWT, user rights authentication, etc
  • Global path request whitelist
  • Rate configuration for global QPS
  • The development phase integrates Swagger as the interface development document

That’s all I have to say about the functions we use, but there’s more to them than that.

Ii. Vulnerability description

2.1 CVE-2022-22947 Code injection Vulnerability

  • Hazard level: super dangerous

  • Threat type: Remote

  • Vulnerability description:

    Applications using Spring Cloud Gateway are vulnerable to code injection attacks when Gateway Actuator endpoints are enabled, exposed, and insecure. Remote attackers can issue maliciously crafted requests that allow arbitrary remote execution on remote hosts.

  • Affected version

    • 3.1.0
    • 3.0.0 ~ 3.0.6
    • An old or unsupported version
  • Solution:

    Users of affected versions should use the following remedies.

    • 3.1.x users should upgrade to 3.1.1+.
    • 3.0.x users should upgrade to 3.0.7+.
    • If you don’t need physical endpoint, should by management. The endpoint gateway. Enabled: false to disable it.
    • If the endpoints of the Actuator are required, use Spring Security to protect them.

2.2 CVE-2022-22946 HTTP2 Insecure TrustManager

  • Hazard level: medium danger

  • Threat type: Local

  • Vulnerability description:

    Applications that use the Spring Cloud Gateway configured to enable HTTP2 and not set up key stores or trusted certificates will be configured to use the insecure TrustManager. This enables the gateway to connect to remote services using invalid or custom certificates.

  • Affected version

    • 3.1.0
  • Solution:

    Users of affected versions should use the following remedies.

    • 3.1.x users should upgrade to 3.1.1+.

Third, expand knowledge

I believe that students who are not familiar with springcloudgateway, or who have come into contact with it for the first time, are quite confused about some terms. I will make a simple arrangement for these terms to help you understand and learn.

3.1 What are Actuator endpoints?

SpringcloudGateway endpoint official documentation location: docs.spring. IO /spring-clou…

Springboot endpoint official documentation: docs.spring. IO /spring-boot…

Actuator endpoints enable you to monitor and interact with applications. Spring Boot includes a number of built-in endpoints and allows you to add your own. For example, the Health endpoint provides basic application health information.

You can enable or disable each individual endpoint and expose them (making them remotely accessible) over HTTP or JMX. When an endpoint is enabled and exposed, it is considered available. Built-in endpoints are automatically configured only when they are available. Most applications choose to expose over HTTP, where the ids of endpoints and the prefix /actuator are mapped to the URL. For example, by default, the health endpoint maps to /actuator/ Health.

In addition to SpringCloudGateway, other SpringBoot services can also open their endpoints. For example, we use springbootAdmin to monitor the health status of the service.

In order to facilitate your understanding and use, I use a set of micro services built in front of you to demonstrate, micro service source address placed at the beginning of the article, we access through http://localhost:8000/ + endpoint address.

In the previous article, we did not enable the gateway’s endpoints. The following configurations enable them:

  • Introducing dependencies:
            <! -- SpringBoot Actuator -->
            <dependency>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>
    Copy the code
  • Add the following configuration
    management:
      endpoint:
        gateway:
          enabled: true
      endpoints:
        web:
          exposure:
            include: gateway
    Copy the code

Here are a few of the endpoint API tests supported by the gateway. For more information, please see the official address provided earlier.

View all gateway routes

Path: / physical/gateway/routes

[{"predicate": "Paths: [/rob-necessities-gateway/**], match trailing slash: true"."metadata": {
            "nacos.instanceId": null."nacos.weight": "1.0"."nacos.cluster": "DEFAULT"."nacos.ephemeral": "true"."nacos.healthy": "true"."preserved.register.source": "SPRING_CLOUD"
        },
        "route_id": "ReactiveCompositeDiscoveryClient_rob-necessities-gateway"."filters": [
            "[[RewritePath /rob-necessities-gateway/(?<remaining>.*) = '/${remaining}'], order = 1]"]."uri": "lb://rob-necessities-gateway"."order": 0}]Copy the code

Obtain routing information based on the route ID

Path: / physical/gateway/routes / {id}. Such as http://localhost:8000/actuator/gateway/routes/ReactiveCompositeDiscoveryClient_rob-necessities-gateway

[{"predicate": "Paths: [/rob-necessities-gateway/**], match trailing slash: true"."metadata": {
            "nacos.instanceId": null."nacos.weight": "1.0"."nacos.cluster": "DEFAULT"."nacos.ephemeral": "true"."nacos.healthy": "true"."preserved.register.source": "SPRING_CLOUD"
        },
        "route_id": "ReactiveCompositeDiscoveryClient_rob-necessities-gateway"."filters": [
            "[[RewritePath /rob-necessities-gateway/(?<remaining>.*) = '/${remaining}'], order = 1]"]."uri": "lb://rob-necessities-gateway"."order": 0}]Copy the code

View the global filter of all routes

Path: / physical/gateway/globalfilters, include your custom filters

{
    "org.springframework.cloud.gateway.filter.ForwardRoutingFilter@4aedac7f": 2147483647."org.springframework.cloud.gateway.filter.NettyRoutingFilter@1be7b7de": 2147483647."org.springframework.cloud.gateway.filter.WebsocketRoutingFilter@2ed4e0e9": 2147483646."org.springframework.cloud.gateway.filter.GatewayMetricsFilter@57441348": 0."org.springframework.cloud.gateway.filter.AdaptCachedBodyGlobalFilter@545c3628": - 2147482648.."org.springframework.cloud.gateway.filter.NettyWriteResponseFilter@5b0ddbcf": - 1."org.springframework.cloud.gateway.filter.RemoveCachedBodyFilter@182934f2": - 2147483648.."org.springframework.cloud.gateway.filter.LoadBalancerClientFilter@7ff167c4": 10100."org.springframework.cloud.gateway.filter.RouteToRequestUrlFilter@6c92af74": 10000."org.springframework.cloud.gateway.filter.ForwardPathFilter@7f8bc54e": 0
}
Copy the code

View the routing gateway filter factory

Path: / physical/gateway/routefilters

{
    "[MapRequestHeaderGatewayFilterFactory@72bb3f3e configClass = MapRequestHeaderGatewayFilterFactory.Config]": null."[RemoveRequestHeaderGatewayFilterFactory@6a275836 configClass = AbstractGatewayFilterFactory.NameConfig]": null."[SecureHeadersGatewayFilterFactory@7828111d configClass = SecureHeadersGatewayFilterFactory.Config]": null."[DedupeResponseHeaderGatewayFilterFactory@774f2d7f configClass = DedupeResponseHeaderGatewayFilterFactory.Config]": null."[RemoveResponseHeaderGatewayFilterFactory@3f41a1f3 configClass = AbstractGatewayFilterFactory.NameConfig]": null."[AddRequestHeaderGatewayFilterFactory@22938166 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null."[SetResponseHeaderGatewayFilterFactory@718aa49a configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null."[RequestHeaderToRequestUriGatewayFilterFactory@513f8279 configClass = AbstractGatewayFilterFactory.NameConfig]": null."[RedirectToGatewayFilterFactory@6c720765 configClass = RedirectToGatewayFilterFactory.Config]": null."[RequestHeaderSizeGatewayFilterFactory@23591a2c configClass = RequestHeaderSizeGatewayFilterFactory.Config]": null."[AddRequestParameterGatewayFilterFactory@58d85a00 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null."[ModifyResponseBodyGatewayFilterFactory@6ddd71cc configClass = ModifyResponseBodyGatewayFilterFactory.Config]": null."[SetRequestHostHeaderGatewayFilterFactory@184b8899 configClass = SetRequestHostHeaderGatewayFilterFactory.Config]": null."[RewriteResponseHeaderGatewayFilterFactory@4992e34f configClass = RewriteResponseHeaderGatewayFilterFactory.Config]": null."[RemoveRequestParameterGatewayFilterFactory@1a6864f0 configClass = AbstractGatewayFilterFactory.NameConfig]": null."[SaveSessionGatewayFilterFactory@6dac64ea configClass = Object]": null."[PrefixPathGatewayFilterFactory@b4f7e1c configClass = PrefixPathGatewayFilterFactory.Config]": null."[SetPathGatewayFilterFactory@4a547f9d configClass = SetPathGatewayFilterFactory.Config]": null."[StripPrefixGatewayFilterFactory@33fa6a8b configClass = StripPrefixGatewayFilterFactory.Config]": null."[SetRequestHeaderGatewayFilterFactory@1dbb3001 configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null."[RetryGatewayFilterFactory@1342c6e1 configClass = RetryGatewayFilterFactory.RetryConfig]": null."[AddResponseHeaderGatewayFilterFactory@62808e8d configClass = AbstractNameValueGatewayFilterFactory.NameValueConfig]": null."[RequestSizeGatewayFilterFactory@2d5cb059 configClass = RequestSizeGatewayFilterFactory.RequestSizeConfig]": null."[ModifyRequestBodyGatewayFilterFactory@5c26ab0a configClass = ModifyRequestBodyGatewayFilterFactory.Config]": null."[RewriteLocationResponseHeaderGatewayFilterFactory@d6de944 configClass = RewriteLocationResponseHeaderGatewayFilterFactory.Config]": null."[RewritePathGatewayFilterFactory@4374c051 configClass = RewritePathGatewayFilterFactory.Config]": null."[PreserveHostHeaderGatewayFilterFactory@6258ea84 configClass = Object]": null."[SetStatusGatewayFilterFactory@49a6b730 configClass = SetStatusGatewayFilterFactory.Config]": null
}
Copy the code

Refreshing the Route Cache

Path: / physical/gateway/refresh, back to 200. Note that this method is POST.

Create routing

Path: /gateway/routes/{id_route_to_create}, post method, success response body is empty.

We create a route to mine with the following parameters:

    {
      "id": "juejin"."predicates": [{"name": "Path"."args": {
            "_genkey_0":"/juejin"}}]."filters": []."uri":"https://juejin.cn/" ,
      "order":1 
    }
Copy the code

Needs to live, the interface is post, pay attention to set the request parameter type for the applicaiton/json, access interface using postman will other interface tools: http://localhost:8000/actuator/gateway/routes/juejin

The response is as follows:

Routing check interface in front of our visit, to see results: http://localhost:8000/actuator/gateway/routes/juejin

    {
        "predicate": "Paths: [/juejin], match trailing slash: true"."route_id": "juejin"."filters": []."uri": "https://juejin.cn:443/"."order": 1
    }
Copy the code

Direct access to the http://localhost:8000/juejin page jump as follows:

We found a lot of exceptions because a lot of the content of the page was not retrieved correctly through our path forwarding, including static resources and interfaces.

Delete the path

Path: /gateway/routes/{id_route_to_delete}. The interface is delete

Here we will use the remove method, we create routing deletion, call interface: http://localhost:8000/actuator/gateway/routes/juejin

The results are as follows:

3.2 What is TrustManager?

TrustManager is an interface in Java introduced since jdk1.4:

package javax.net.ssl;

public interface TrustManager {}Copy the code

It is the basic interface of the JSSE trust manager.

Responsible for managing trust materials used in making trust decisions and determining whether credentials provided by peers should be accepted.

Created by using TrustManagerFactory or by implementing one of the TrustManager subclasses.

Currently there are known sub-interfaces X509TrustManager:

package javax.net.ssl;

import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public interface X509TrustManager extends TrustManager {
    void checkClientTrusted(X509Certificate[] var1, String var2) throws CertificateException;

    void checkServerTrusted(X509Certificate[] var1, String var2) throws CertificateException;

    X509Certificate[] getAcceptedIssuers();
}
Copy the code

Known implementation class X509ExtendedTrustManager:

package javax.net.ssl;

import java.net.Socket;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

public abstract class X509ExtendedTrustManager implements X509TrustManager {
    public X509ExtendedTrustManager(a) {}public abstract void checkClientTrusted(X509Certificate[] var1, String var2, Socket var3) throws CertificateException;

    public abstract void checkServerTrusted(X509Certificate[] var1, String var2, Socket var3) throws CertificateException;

    public abstract void checkClientTrusted(X509Certificate[] var1, String var2, SSLEngine var3) throws CertificateException;

    public abstract void checkServerTrusted(X509Certificate[] var1, String var2, SSLEngine var3) throws CertificateException;
}
Copy the code

This article does not explain the specific usage, as long as a simple understanding of good, this class is very rarely used for our life work.