oathkeeper icon indicating copy to clipboard operation
oathkeeper copied to clipboard

Using X-Forwarded-Uri header does not URL-decode or filter queries before matching rules

Open akshualy opened this issue 3 years ago • 0 comments

Preflight checklist

Describe the bug

For context, we are hosting Ory on our servers and are using Ory Oathkeeper as a decision engine behind NGINX. When a request to our server happens, an NGINX ingress calls the decision engine to convert Kratos session cookies to an X-User-ID header. To facilitate limitations with regular NGINX ingress auth calls, we use X-Forwarded-* headers to have Oathkeeper understand the original request. We are setting the X-Forwarded-Uri header to the $request_uri variable.

It seems setting the forwarded headers results in Oathkeeper no longer filtering out queries before trying to match a rule. The URI path logs as URL encoded (see log output). I've confirmed that the oathkeeper container receives the request correctly by replacing it with netcat.

Reproducing the bug

  1. Install Oathkeeper and configure it to allow calls to /decisions
  2. Configure a rule, preferably with matching_strategy set to regex, to see a workaround
  3. Make a curl with parameters that should match this rule

Example rule:

[
  {
    "id": "example#get",
    "match": {
      "url": "http://localhost:4456/example",
      "methods": [
        "GET"
      ]
    },
    "authenticators": [
      {
        "handler": "noop"
      }
    ],
    "authorizer": {
      "handler": "allow"
    },
    "mutators": [
      {
        "handler": "noop"
      }
    ]
  }
]

Example curl:

curl -X 'GET' 'http://localhost:4456/decisions' \
    --header "X-Forwarded-Method: GET" \
    --header "X-Forwarded-Proto: http" \
    --header "X-Forwarded-Host: localhost:4456" \
    --header "X-Forwarded-Uri: /example?foo=bar"

The curl will result in a 404 unless you drop the ?foo=bar.

Relevant log output

time=2022-09-06T07:32:18Z level=info msg=started handling request http_request=map[headers:map[accept:*/* user-agent:curl/7.74.0 x-forwarded-proto:http] host:localhost:4456 method:GET path:/decisions query:<nil> scheme:http]
ime=2022-09-06T07:32:18Z level=warning msg=Access request denied audience=application error=map[debug: message:Requested url does not match any rules reason: status:Not Found status_code:404] granted=false http_host=localhost:4456 http_method=GET http_url=http://localhost:4456/example%3Ffoo=bar http_user_agent=curl/7.74.0 service_name=ORY Oathkeeper service_version=v0.39.0
time=2022-09-06T07:32:18Z level=error msg=An error occurred while handling a request code=404 debug= details=map[] error=The requested resource could not be found reason= request-id= status=404 writer=JSON
time=2022-09-06T07:32:18Z level=info msg=completed handling request http_request=map[headers:map[accept:*/* user-agent:curl/7.74.0 x-forwarded-proto:http] host:localhost:4456 method:GET path:/example%3Ffoo=bar query:<nil> scheme:http] http_response=map[status:404 text_status:Not Found took:247.054µs]

Relevant configuration

version: v0.39.2
serve:
  api:
    port: 4456
access_rules:
  matching_strategy: regexp
  repositories:
    - file://path/to/rule.json
errors:
  fallback:
    - json
log:
  level: debug
  leak_sensitive_values: true
authenticators:
  noop:
    enabled: true
authorizers:
  allow:
    enabled: true
mutators:
  noop:
    enabled: true

Version

v0.39.2

On which operating system are you observing this issue?

Linux

In which environment are you deploying?

Kubernetes

Additional Context

The mentioned workaround is to set the match URL to http://localhost:4456/example<((\\%F3).*)?>.

akshualy avatar Sep 06 '22 08:09 akshualy