TykTechnologies / tyk

Tyk Open Source API Gateway written in Go, supporting REST, GraphQL, TCP and gRPC protocols
Other
9.55k stars 1.07k forks source link

[TT-1944] Whitelist allow endpoint with wrong method despite of endpoint parameters #3399

Open renta opened 3 years ago

renta commented 3 years ago

Branch/Environment/Version

Describe the bug Tyk Gateway allows to send requests on endpoint in the whitelist if there is almost the same, but without parameters (see whitelist and track_endpoints section in an example API).

Reproduction steps Steps to reproduce the behavior:

{
    "name": "Service public API",
    "slug": "",
    "listen_port": 0,
    "protocol": "http",
    "enable_proxy_protocol": false,
    "api_id": "8dabc585-7070-41f9-85fd-de88f0affe62",
    "org_id": "1",
    "use_keyless": true,
    "use_oauth2": false,
    "use_openid": false,
    "openid_options": {
        "providers": null,
        "segregate_by_client": false
    },
    "oauth_meta": {
        "allowed_access_types": null,
        "allowed_authorize_types": null,
        "auth_login_redirect": ""
    },
    "auth": {
        "use_param": false,
        "param_name": "",
        "use_cookie": false,
        "cookie_name": "",
        "auth_header_name": "Authorization",
        "use_certificate": false,
        "validate_signature": false,
        "signature": {
            "algorithm": "",
            "header": "",
            "secret": "",
            "allowed_clock_skew": 0,
            "error_code": 0,
            "error_message": ""
        }
    },
    "auth_configs": null,
    "use_basic_auth": false,
    "basic_auth": {
        "disable_caching": false,
        "cache_ttl": 0,
        "extract_from_body": false,
        "body_user_regexp": "",
        "body_password_regexp": ""
    },
    "use_mutual_tls_auth": false,
    "client_certificates": null,
    "upstream_certificates": null,
    "pinned_public_keys": null,
    "enable_jwt": true,
    "use_standard_auth": false,
    "use_go_plugin_auth": false,
    "enable_coprocess_auth": false,
    "jwt_signing_method": "rsa",
    "jwt_source": "pubkeylongkeyhere",
    "jwt_identity_base_field": "sub",
    "jwt_client_base_field": "",
    "jwt_policy_field_name": "pol",
    "jwt_default_policies": [
        "default"
    ],
    "jwt_issued_at_validation_skew": 0,
    "jwt_expires_at_validation_skew": 0,
    "jwt_not_before_validation_skew": 0,
    "jwt_skip_kid": false,
    "jwt_scope_to_policy_mapping": null,
    "jwt_scope_claim_name": "",
    "notifications": {
        "shared_secret": "",
        "oauth_on_keychange_url": ""
    },
    "enable_signature_checking": false,
    "hmac_allowed_clock_skew": 0,
    "hmac_allowed_algorithms": null,
    "request_signing": {
        "is_enabled": false,
        "secret": "",
        "key_id": "",
        "algorithm": "",
        "header_list": null,
        "certificate_id": "",
        "signature_header": ""
    },
    "base_identity_provided_by": "",
    "definition": {
        "location": "header",
        "key": "version",
        "strip_path": false
    },
    "version_data": {
        "not_versioned": true,
        "default_version": "",
        "versions": {
            "0.1.0": {
                "name": "0.1.0",
                "expires": "",
                "paths": {
                    "ignored": null,
                    "white_list": null,
                    "black_list": null
                },
                "use_extended_paths": true,
                "extended_paths": {
                    "track_endpoints": [
                        {
                            "path": "/admin/users/{userId}",
                            "method": "GET"
                        },
                        {
                            "path": "/admin/users",
                            "method": "POST"
                        },
                        {
                            "path": "/admin/users/{userId}/roles",
                            "method": "GET"
                        },
                        {
                            "path": "/admin/users/{userId}/roles",
                            "method": "PUT"
                        }
                    ],
                    "white_list": [
                        {
                            "path": "/admin/users/{userId}",
                            "ignore_case": false,
                            "method_actions": {
                                "GET": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                                }
                            }
                        },
                        {
                            "path": "/admin/users",
                            "ignore_case": false,
                            "method_actions": {
                                "POST": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                                }
                            }
                        },
                        {
                            "path": "/admin/users/{userId}/roles",
                            "ignore_case": false,
                            "method_actions": {
                                "GET": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                                }
                            }
                        },
                        {
                            "path": "/admin/users/{userId}/roles",
                            "ignore_case": false,
                            "method_actions": {
                                "PUT": {
                                    "action": "no_action",
                                    "code": 200,
                                    "data": "",
                                    "headers": {}
                                }
                            }
                        }
                    ]
                },
                "global_headers": null,
                "global_headers_remove": null,
                "global_response_headers": null,
                "global_response_headers_remove": null,
                "ignore_endpoint_case": false,
                "global_size_limit": 0,
                "override_target": ""
            }
        }
    },
    "uptime_tests": {
        "check_list": null,
        "config": {
            "expire_utime_after": 0,
            "service_discovery": {
                "use_discovery_service": false,
                "query_endpoint": "",
                "use_nested_query": false,
                "parent_data_path": "",
                "data_path": "",
                "port_data_path": "",
                "target_path": "",
                "use_target_list": false,
                "cache_timeout": 0,
                "endpoint_returns_list": false
            },
            "recheck_wait": 0
        }
    },
    "proxy": {
        "preserve_host_header": false,
        "listen_path": "/admin/",
        "target_url": "http://app-nginx/api",
        "disable_strip_slash": false,
        "strip_listen_path": false,
        "enable_load_balancing": false,
        "target_list": null,
        "check_host_against_uptime_tests": false,
        "service_discovery": {
            "use_discovery_service": false,
            "query_endpoint": "",
            "use_nested_query": false,
            "parent_data_path": "",
            "data_path": "",
            "port_data_path": "",
            "target_path": "",
            "use_target_list": false,
            "cache_timeout": 0,
            "endpoint_returns_list": false
        },
        "transport": {
            "ssl_insecure_skip_verify": false,
            "ssl_ciphers": null,
            "ssl_min_version": 0,
            "ssl_force_common_name_check": false,
            "proxy_url": ""
        }
    },
    "disable_rate_limit": true,
    "disable_quota": true,
    "custom_middleware": {
        "pre": null,
        "post": null,
        "post_key_auth": null,
        "auth_check": {
            "name": "",
            "path": "",
            "require_session": false,
            "raw_body_only": false
        },
        "response": null,
        "driver": "",
        "id_extractor": {
            "extract_from": "",
            "extract_with": "",
            "extractor_config": null
        }
    },
    "custom_middleware_bundle": "",
    "cache_options": {
        "cache_timeout": 0,
        "enable_cache": false,
        "cache_all_safe_requests": false,
        "cache_response_codes": null,
        "enable_upstream_cache_control": false,
        "cache_control_ttl_header": "",
        "cache_by_headers": null
    },
    "session_lifetime": 0,
    "active": true,
    "internal": false,
    "auth_provider": {
        "name": "",
        "storage_engine": "",
        "meta": null
    },
    "session_provider": {
        "name": "",
        "storage_engine": "",
        "meta": null
    },
    "event_handlers": {
        "events": null
    },
    "enable_batch_request_support": false,
    "enable_ip_whitelisting": false,
    "allowed_ips": null,
    "enable_ip_blacklisting": false,
    "blacklisted_ips": null,
    "dont_set_quota_on_create": false,
    "expire_analytics_after": 0,
    "response_processors": null,
    "CORS": {
        "enable": false,
        "allowed_origins": null,
        "allowed_methods": null,
        "allowed_headers": null,
        "exposed_headers": null,
        "allow_credentials": false,
        "max_age": 0,
        "options_passthrough": false,
        "debug": false
    },
    "domain": "",
    "certificates": null,
    "do_not_track": false,
    "tags": null,
    "enable_context_vars": false,
    "config_data": null,
    "tag_headers": null,
    "global_rate_limit": {
        "rate": 0,
        "per": 0
    },
    "strip_auth_data": false,
    "enable_detailed_recording": false,
    "graphql": {
        "enabled": false,
        "execution_mode": "",
        "schema": "",
        "type_field_configurations": null,
        "playground": {
            "enabled": false,
            "path": ""
        }
    }
}

Actual behavior When I tested my API whitelist for /admin/users/{userId} endpoint did not work as expected. curl --location --request GET 'http://api-gateway.service.test/admin/users/1' - worked as expected curl --location --request POST 'http://api-gateway.service.test/admin/users/1' - should be blocked by Tyk whitelist filter with 403 response, but Tyk bypassed this request to the service and API service responsed with 404 error. After I've deleted endpoint /admin/users from track_endpoints and whitelist section and reloaded Tyk everything began to work right.

Expected behavior Tyk should examine endpoint for parameters and do not allow requests for endpoints with wrong method.

Screenshots/Video No

Logs (debug mode or log file): I can provide if needed.

Configuration (tyk config file):

{
  "listen_port": 8080,
  "secret": "somesecret",
  "template_path": "/opt/tyk-gateway/templates",
  "tyk_js_path": "/opt/tyk-gateway/js/tyk.js",
  "middleware_path": "/opt/tyk-gateway/middleware",
  "use_db_app_configs": false,
  "app_path": "/opt/tyk-gateway/apps/",
  "storage": {
    "type": "redis",
    "host": "redis",
    "port": 6379,
    "username": "",
    "password": "",
    "database": 0,
    "optimisation_max_idle": 2000,
    "optimisation_max_active": 4000
  },
  "enable_analytics": false,
  "analytics_config": {
    "type": "csv",
    "csv_dir": "/tmp",
    "mongo_url": "",
    "mongo_db_name": "",
    "mongo_collection": "",
    "purge_delay": -1,
    "ignored_ips": []
  },
  "health_check": {
    "enable_health_checks": true,
    "health_check_value_timeouts": 60
  },
  "optimisations_use_async_session_write": true,
  "enable_non_transactional_rate_limiter": true,
  "enable_sentinel_rate_limiter": false,
  "enable_redis_rolling_limiter": false,
  "allow_master_keys": false,
  "policies": {
    "policy_source": "file",
    "policy_record_name": "/opt/tyk-gateway/policies/policies.json"
  },
  "hash_keys": true,
  "enable_hashed_keys_listing": true,
  "close_connections": false,
  "http_server_options": {
    "enable_websockets": true
  },
  "allow_insecure_configs": true,
  "coprocess_options": {
    "enable_coprocess": true,
    "coprocess_grpc_server": ""
  },
  "enable_bundle_downloader": true,
  "bundle_base_url": "",
  "global_session_lifetime": 100,
  "force_global_session_lifetime": false,
  "max_idle_connections_per_host": 500
}

Additional context Does this issue related to https://github.com/TykTechnologies/tyk/issues/2933 and https://github.com/TykTechnologies/tyk/issues/1944 ?

Moses-oyedeji commented 3 years ago

@renta Thanks for contacting Tyk! We apologize for the delayed response. The issue is currently being reviewed and we will keep you updated as soon as we can