Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Error 403 forbidden POST login using localhost #8560

Closed
fercapi84 opened this issue Jan 2, 2023 · 8 comments · Fixed by #8642
Closed

Error 403 forbidden POST login using localhost #8560

fercapi84 opened this issue Jan 2, 2023 · 8 comments · Fixed by #8642
Assignees
Labels
closed: notabug The issue is not a bug

Comments

@fercapi84
Copy link

Expected Behavior

The POST /login response with http status 200 and CORS headers included.

Micronaut 3.7.4
curl -i -v 'http://localhost:8080/login' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://localhost:8090/' -H 'Content-Type: application/x-www-form-urlencoded' -H 'X-Requested-With: XMLHttpRequest' -H 'Authorization: Basic Og==' -H 'Origin: http://127.0.0.1:8090/' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: cors' -H 'Sec-Fetch-Site: same-site' --data-raw 'grant_type=password&username=admin&password=admin'

Connected to localhost (127.0.0.1) port 8080 (#0)
POST /login HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: application/json, text/plain, /
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://localhost:8090/
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Authorization: Basic Og==
Origin: http://127.0.0.1:8090/
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Content-Length: 49

Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< date: Mon, 2 Jan 2023 20:57:26 GMT
date: Mon, 2 Jan 2023 20:57:26 GMT
< Access-Control-Allow-Origin: http://127.0.0.1:8090/
Access-Control-Allow-Origin: http://127.0.0.1:8090/
< Vary: Origin
Vary: Origin
< Access-Control-Allow-Credentials: true
Access-Control-Allow-Credentials: true
< Content-Type: application/json
Content-Type: application/json
< content-length: 267
content-length: 267
< connection: keep-alive
connection: keep-alive

Connection #0 to host localhost left intact
{"username":"admin","roles":["ADMIN"],"access_token":"eyJhbGciOiJub25lIn0.eyJzdWIiOiJhZG1pbiIsIm5iZiI6MTY3MjY5MzA0Niwicm9sZXMiOlsiQURNSU4iXSwiaXNzIjoiY29ycy1sb2NhbGhvc3QtY29uZiIsImV4cCI6MTY3MjY5NjY0NiwiaWF0IjoxNjcyNjkzMDQ2fQ.","token_type":"Bearer","expires_in":3600}

Micronaut 3.8.0 host different than localhost
curl -i -v 'http://127.0.0.1:8080/login' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://localhost:8090/' -H 'Content-Type: application/x-www-form-urlencoded' -H 'X-Requested-With: XMLHttpRequest' -H 'Authorization: Basic Og==' -H 'Origin: http://127.0.0.1:8090/' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: cors' -H 'Sec-Fetch-Site: same-site' --data-raw 'grant_type=password&username=admin&password=admin'

Trying 127.0.0.1:8080...
Connected to 127.0.0.1 (127.0.0.1) port 8080 (#0)
POST /login HTTP/1.1
Host: 127.0.0.1:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: application/json, text/plain, /
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://localhost:8090/
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Authorization: Basic Og==
Origin: http://127.0.0.1:8090/
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Content-Length: 49

Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< date: Mon, 2 Jan 2023 20:25:31 GMT
date: Mon, 2 Jan 2023 20:25:31 GMT
< Access-Control-Allow-Origin: http://127.0.0.1:8090/
Access-Control-Allow-Origin: http://127.0.0.1:8090/
< Vary: Origin
Vary: Origin
< Access-Control-Allow-Credentials: true
Access-Control-Allow-Credentials: true
< Content-Type: application/json
Content-Type: application/json
< content-length: 267
content-length: 267
< connection: keep-alive
connection: keep-alive

Actual Behaviour

I use swagger to expose the Rest API documentation. The authentication process call the login endpoint in a different server (I use an auth-server running in other server than the business microservices).
Upgrading to micronaut 3.8.0 version the remote login in swagger doesn't work anymore (the login response is 403 forbidden). After check configuration and differents test using CURL I realize that the CORS headers isn't included in the response. Checking the source code I found some validations when the host is localhost that explain the 403 status code but for example the ip 127.0.0.1 isn't included. Is that correct?
In order to solve this problem I have to include the following configuration to use swagger in local environment

micronaut: server: cors: enabled: true configurations: web: allowedOrigins: - ^http(|s):\/\/*.*

In previous version the mentioned configuration wasn't need to include and CURL and swagger works perfectly.
In the Example Application can reproduce the behavior mentioned using the following curl

curl -i -v 'http://localhost:8080/login' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://localhost:8090/' -H 'Content-Type: application/x-www-form-urlencoded' -H 'X-Requested-With: XMLHttpRequest' -H 'Authorization: Basic Og==' -H 'Origin: http://127.0.0.1:8090/' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: cors' -H 'Sec-Fetch-Site: same-site' --data-raw 'grant_type=password&username=admin&password=admin'

Trying 127.0.0.1:8080...
Connected to localhost (127.0.0.1) port 8080 (#0)
POST /login HTTP/1.1
Host: localhost:8080
User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0
Accept: application/json, text/plain, /
Accept-Language: en-US,en;q=0.5
Accept-Encoding: gzip, deflate, br
Referer: http://localhost:8090/
Content-Type: application/x-www-form-urlencoded
X-Requested-With: XMLHttpRequest
Authorization: Basic Og==
Origin: http://127.0.0.1:8090/
Connection: keep-alive
Sec-Fetch-Dest: empty
Sec-Fetch-Mode: cors
Sec-Fetch-Site: same-site
Content-Length: 49

Mark bundle as not supporting multiuse
< HTTP/1.1 403 Forbidden
HTTP/1.1 403 Forbidden
< connection: keep-alive
connection: keep-alive
< transfer-encoding: chunked
transfer-encoding: chunked

Steps To Reproduce

1- Clone the example application repository
2- ./gradlew run
3- Execute this curl command

  • Using localhost
    curl -i -v 'http://localhost:8080/login' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://localhost:8090/' -H 'Content-Type: application/x-www-form-urlencoded' -H 'X-Requested-With: XMLHttpRequest' -H 'Authorization: Basic Og==' -H 'Origin: http://127.0.0.1:8090/' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: cors' -H 'Sec-Fetch-Site: same-site' --data-raw 'grant_type=password&username=admin&password=admin'

  • Using 127.0.0.1
    curl -i -v 'http://127.0.0.1:8080/login' -X POST -H 'User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:108.0) Gecko/20100101 Firefox/108.0' -H 'Accept: application/json, text/plain, */*' -H 'Accept-Language: en-US,en;q=0.5' -H 'Accept-Encoding: gzip, deflate, br' -H 'Referer: http://localhost:8090/' -H 'Content-Type: application/x-www-form-urlencoded' -H 'X-Requested-With: XMLHttpRequest' -H 'Authorization: Basic Og==' -H 'Origin: http://127.0.0.1:8090/' -H 'Connection: keep-alive' -H 'Sec-Fetch-Dest: empty' -H 'Sec-Fetch-Mode: cors' -H 'Sec-Fetch-Site: same-site' --data-raw 'grant_type=password&username=admin&password=admin'

Environment Information

Manjaro, Ubuntu
OpenJDK 17, 18
It works fine in Micronaut 3.7.4 and Micronaut 3.7.5

Example Application

https://github.com/fercapi84/cors-localhost-conf

Version

3.8.0

@viniciusxyz
Copy link

Maybe it's related to #8582

@sdelamo
Copy link
Collaborator

sdelamo commented Jan 9, 2023

We changed the behaviour in 3.8.x to prevent drive-by localhost attack.

#8524

My recommendation is you add configuration only for the swagger origin. Instead of something as broad as :

allowedOrigins: - ^http(|s):\/\/*.* use allowedOrigins: https://theurlwheremyswaggerlives.com

@sdelamo sdelamo added the closed: notabug The issue is not a bug label Jan 9, 2023
@nbrugger-tgm
Copy link

For me requesting localhost:8080 (my micronaut service) from localhost:4200 (my local ui) did throw the same error. Is that intended? I fixed it by requesting 127.0.0.1:8080 instead (do not ask my why it works, it just does)

@sdelamo
Copy link
Collaborator

sdelamo commented Jan 11, 2023

For me requesting localhost:8080 (my micronaut service) from localhost:4200 (my local ui) did throw the same error. Is that intended? I fixed it by requesting 127.0.0.1:8080 instead (do not ask my why it works, it just does)

I think if your app is running in localhost and the front end is running in localhost. You should be able to do:

micronaut:
  server:
    cors:
      enabled: true

Currently you will need to do:

micronaut:
  server:
    cors:
      enabled: true
      configurations:
        ui:
          allowed-origins: 'http://localhost:4200'

I will try to change this for 3.8.1

sdelamo added a commit that referenced this issue Jan 11, 2023
sdelamo added a commit that referenced this issue Jan 11, 2023
sdelamo added a commit that referenced this issue Jan 11, 2023
…s with localhost and resolved Micronaut Application host is also localhost (#8601)

* fix: OK cors=true & origin and host = localhost

Close #8560
@sdelamo
Copy link
Collaborator

sdelamo commented Jan 11, 2023

Closed via #8601

@sdelamo sdelamo closed this as completed Jan 11, 2023
@nbrugger-tgm
Copy link

nbrugger-tgm commented Jan 11, 2023

Thank you for being so quick with the fix 🎉, there is just one thing left

We changed the behaviour in 3.8.x to prevent drive-by localhost attack.
@sdelamo

I think while this ticket is closed, that there is still a bug. If your statement is true requesting the api on 127.0.0.1 with origin localhost:4200 should fail with a CORS exception as well but it doesn't. Using 3.8.0 requesting 127.0.0.1:8080 works and localhost:8080 doesn't.

So from a security perspective i believe that attackers would just need to change the drive by url from localhost to any local address. It is not a new security issue but should be fixed imo since users could believe they are safe when they are not.

Should you decide that this issue is "fixworthy" keep in mind that 127.0.0.1 is not the only local address in fact the whole of 127.0.0.0/8 could be used for this attack

@sdelamo sdelamo reopened this Jan 20, 2023
@sdelamo
Copy link
Collaborator

sdelamo commented Jan 20, 2023

@timyates could you consider the suggestions from @nbrugger-tgm ?

@timyates
Copy link
Member

@nbrugger-tgm Could you take a look at #8642

Thanks for all the help 👍

@timyates timyates linked a pull request Jan 20, 2023 that will close this issue
@sdelamo sdelamo closed this as completed Jan 28, 2023
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
closed: notabug The issue is not a bug
Projects
No open projects
Status: Done
Development

Successfully merging a pull request may close this issue.

5 participants