GithubHelp home page GithubHelp logo

cloud-foundations / keymaster Goto Github PK

View Code? Open in Web Editor NEW
114.0 6.0 13.0 4.24 MB

Short term certificate based identity system (ssh/x509 ca + openidc)

License: Apache License 2.0

Makefile 0.33% Go 94.46% CSS 0.08% JavaScript 4.33% Shell 0.54% Dockerfile 0.25%
u2f certificates ssh-certificates ssl-certificates totp 2factor openidc

keymaster's People

Contributors

bpan avatar cviecco avatar keep94 avatar rgooch avatar rkiyanchuk avatar slr9511 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar

keymaster's Issues

difficulty enrolling Yubikey

Running newest version of Firefox (85.0.2) on MacOS Catalina (10.15.7). Using a Yubikey 5C Nano, I recently had a great deal of trouble getting a replacement registered.

Firstly, I was getting delayed notifications when I attempted to go through the registration workflow. While this wasn't Keymaster's fault, it didn't do a good job of indicating that the e-mail I was looking at had an old code on it. Not entirely sure what to do here, but perhaps something involving a clear timestamp or fingerprint that should match between the e-mail and the OTP code form would be helpful. Or perhaps some way to resend a recent code and reuse it. The pathology of going through the registration cycle but never quite telling that you're one e-mail behind is very real and a pretty poor UX.

Once I got that right, I could never get Firefox to prompt when I attempted to register the key. I'd click the "Register" button but it would never pop up to read the U2F key. I was able to verify the key was installed using ykman and I was also able to register the key with Firefox on GitHub and Okta. I eventually got it working with Chrome (88.0.4324.150), so it seems to be something with Firefox specifically.

Provide a logout button in the 2FA tab

Currently, if someone types in a username which passes primary authentication (i.e. Okta is used for primary auth) and the user did not drop the @company.com part of their username, they cannot pass the 2FA step because there is no U2F token registered to [email protected]. The user is now in limbo, unable to retry with just username because they have a cookie which causes the primary authentication flow to be bypassed.

If there was a logout button during the 2FA phase, the user could recover more easily.

cloud-foundations.org has been lost?

There are references in this repo to colud-foundations.org, but that domain has either been lost or the webserver is broken (shows a pretty empty file listing now).

Is that domain still supposed to be active? If not, probably this repo should drop references to it?

Yubikey fails first time with Mac client

Occasionally, when I first auth with keymaster, I get an error like this:

computer:~ jayson$ keymaster
Password for jayson:
attempting to target 'https://keymaster.example.net' for 'jayson'
top of doU2fAuthenticate
manufacturer = "Yubico", product = "YubiKey FIDO+CCID", vid = 0x0406, pid = 0x1050
version: U2F_V2
authenticating, provide user presence
hid: general error

Oddly, if I retry immediately, it always works. Often times, it works without me even pressing the key again, too.

I don't think this is exactly the same as #2. It seems to be related to an initial error accessing the hid subsystem or something. If we did a single retry on that specific error, I suspect it would be a decent workaround.

Support openid PKCE code flow (RFC 7636)

Some endpoints (such as angular) have much better support of PKCE code flow than for the standard openid connect code flow. This feature will allow PKCE libraries to be able to use keymaster as a web idp

Support automatic generation of bootstrap OTP for new users

When a user completes primary authentication (username+password) and has no active U2F tokens, generate a short term (expires in 1 minute) OTP, use the API described in issue #14 and email the OTP value to the user, along with a clickable link to the login page.

This will allow self-service bootstrapping of new users.

Support expiring OTP injection when user has no active 2nd factors

Add a privileged API call to add an expiring One Time Password for a user if the user has no active 2nd factors registered. The OTP should be added to a database. When a user completes primary (username+password) authentication, the 2nd factor check will fall back to checking the database for the expiring OTP when there are no active 2nd factors registered for the user.

This may be used to streamline/automate the bootstrapping of users when they are first on-boarded and have no 2nd factor registered yet, when combined with issue #15.
This depends on issue #21.

Csp has unsafe-inline - style

Issue

The content security policy allows unsafe-inline for style.

Steps to reproduce

Login to keymaster (web). We will notice that the response returns the CSP header which allows unsafe inline for style.

Impact

Allowing inline styles makes one susceptible to a the "other XSS". Cross Site Styling attacks that could end up defacing the website. Unless the other CSP rules never allow any kind of request to go to a untrusted or wildcard domain, then using a carefully crafted style rules attackers could send any information included on the page to external domains and expose or otherwise use that data maliciously against users.

Remediation

Don’t allow unsafe-inline option.

Code/Lines affected

w.Header().Set("Content-Security-Policy", "default-src 'self' ;style-src 'self' fonts.googleapis.com 'unsafe-inline'; font-src fonts.gstatic.com fonts.googleapis.com")

Make test fails with go 1.15.x

1.15.x is more strict on its handling of certificates. We need to construct certificates for testing that include localhost in their SAN fields

FEATURE REQUEST: Make "needs bootstrap flow" explicit.

I've run into a few use-cases where it would be handy to be able to trigger the bootstrap workflow without deleting the current keys or where it would be handy to inhibit the bootstrap workflow but still have the user configured with no keys.

Would it be possible to do something like?

  • Add a boolean to the user DB indicating whether bootstrap was needed.
  • Default that to true or false based on some config value.
  • Have a button in the UI to flip the status.
  • Trigger the bootstrap flow based on that flag instead of "no keys".

Older Yubikeys do not work (but work elsewhere with U2F!)

Usage of keymaster (version 1.7.0)

attempting to target '' for ''
top of doU2fAuthenticate
manufacturer = "Yubico", product = "Yubikey NEO U2F", vid = 0x0113, pid = 0x1050
u2fhid: error reading response, read timed out

In Yubikey Manager GUI it shows up as Yubikey NEO 3.0.0.
U2F works fine on various websites.

x509 Certs do not validate with CA

Generated certificates do not appear to match the CA in use. I ran keymaster on the same host and attempted to validate against ca.

SSH Key works fine.

Steps to reproduce

1. Generate key

$ keymaster
Password for myuser: 
attempting to target 'https://keymaster.xxx.xxx' for 'myuser'
top of doU2fAuthenticate
manufacturer = "XXX", product = "XXX", vid = 0xXXX, pid = 0xXXX
version: U2F_V2
authenticating, provide user presence
counter = XXX, signature = XXX
Success

2. Attempt to validate key

$ cd .ssl
$ openssl verify -CAfile /etc/keymaster/adminCA.pem keymaster.cert 
O = keymaster, CN = myuser
error 20 at 0 depth lookup: unable to get local issuer certificate
error keymaster.cert: verification failed
$ openssl verify -CAfile /etc/keymaster/adminClient.pem keymaster.cert 
O = keymaster, CN = myuser
error 20 at 0 depth lookup: unable to get local issuer certificate
error keymaster.cert: verification failed

Send email to users when a U2F token is registered

Users should be alerted when a new U2F token is registered for them (whether by themselves or by an administrator). Send an email to the user for these events, including who registered the token.

Add a configuration option to control when administrators are also alerted about token registrations:

  • never
  • first time a user registers a token (i.e. on-boarding)
  • any time a user registers a token

Intermitent Superflous Error message when using okta code

There is a race condition between the background loop checking for okta push and the user sending a code. If the code is sent the background task might also send a query which will be invaldated because the user has already logged in.

We need to suspend sending background requests as soon as the user submits a code.

Yubikey not initially working with MacOS client

Running the MacOS Keymaster client with a Yubikey 5C nano plugged in I got this error:
top of doU2fAuthenticate manufacturer = "Yubico", product = "YubiKey OTP+FIDO+CCID", vid = 0x0407, pid = 0x1050 u2fhid: error reading response, read timed out
The Yubikey did not blink.

I then plugged in a Feitian U2F token as well and ran the Keymaster client again. The Feitian did not blink but the Yubikey did, so I pressed it and it worked. Before I pressed the Yubikey I pressed the (not blinking) Feitian to see what would happen and I just got OTP codes in my terminal.

I unplugged my Feitian token and tried again with just the Yubikey token and everything worked fine. I tried again and it worked.

Security Vulnerability - Content Injection

Impact:
Medium
(remotely explotiable with non-default configuration)

CVSS v 3.1 Vector:
AV:N/AC:L/PR:N/UI:R/S:C/C:L/I:N/A:N

The admin panel logs pages are vulnerable to HTML injection. An attacker can craft a phishing page using HTML + CSS and trick admins who view the page into disclosing their credentials. CSP prevents JS execution, but JS execution isn’t necessary to do damage.

keymaster_html_injection

Pass along user profile image

Some back-end primary authentication services (i.e. Okta) can provide a profile image for a user. It would be cool if Keymaster could grab this information and pass it along to downstream consumers such as Web Service Providers (SPs).

If the back-end provides a URL to the profile image, that could be passed along as-is. However, if the back-end provides the image data inline then Keymaster must store the image data. The database used for managing U2F tokens is a good place for this, as these data are already automatically replicated to Keymaster instances. Since images can be large, they should be capped in size and transcoded prior to storage to prevent excessive growth of the database.

Even if the back-end provides a URL, it may be preferable to grab the data, cap and transcode it so that internal systems can obtain the profile information without having to connect to the back-end. This would enhance privacy and resiliency.

keymaster cli doesn't work w/ keymaster behind AWS ALB

For, not so great reasons, I am unable to put the valid x509 cert on the keymaster server. For this reason I am terminating https on an ALB. This works fine for browser, but I am unable to get the keymaster cli to work through this, receiving HTTP 464.

As a workaround I had added golang.org/x/net/http2 and ensured every request in the client had client.Transport = &http2.Transport{}. This unblocked my issue.

HTTP 464
The load balancer received an incoming request protocol that is incompatible with the version config of the target group protocol.

Possible causes:

The request protocol is an HTTP/1.1, while the target group protocol version is a gRPC or HTTP/2.

The request protocol is a gRPC, while the target group protocol version is an HTTP/1.1.

The request protocol is an HTTP/2 and the request is not POST, while target group protocol version is a gRPC.

U2F redirect comes w/ semicolons

I am using keymaster as an openid connect provider. I use a U2F hardware key and Chrome 95.

After U2F SignResponse I am redirected to /idp/oauth2/authorize?access_type=offline&amp;client_id=<REDACTED>&amp;redirect_uri=https://<REDACTED>/callback&amp;response_type=code&amp;scope=openid+profile+email+offline_access&amp;state=<REDACTED>

This is causing an issue w/ the golang net/http which no longer allows semicolons in req.URL.RawQuery per line 2873.

Error in keymaster log: http: URL query contains semicolon, which is no longer a supported separator; parts of the query may be stripped when parsed; see golang.org/issue/25192

Error in the browser: '500 Internal Server Error'

This does not occur when I use TOTP. This also does not occur when I log in to keymaster directly using U2F, only when it is part of an openid connect login for a different endpoint. Additionally I have no issue if I login to keymaster first and then navigate to my openid connect endpoint.

Chrome 96 - U2F being deprecated.

It appears that Keymaster is using the deprecated U2F plugin in Chrome. This will not work after Feb 2022. I get this warning with Chrome 96.

image

Currently u2f-api.js uses the Cryptotoken extension (kmendfapggjehodndflmmgagdbamhnfd) that is built into Chrome. This is being deprecated in favor of using webauthn in future versions of Chrome and thus U2F will stop working.

AJAX requests with the oidc golib and keymaster

We have a service using the oidc golib package and keymaster for auth and would like to make AJAX requests to the service from a client-side JS app.

Currently, if the user has not gone through the auth flow to get a cookie set for the service, our AJAX POST request to the service will get redirected to the keymaster login, which will proceed to get blocked by CORS as it has no CORS headers on the response and prevent the browser from showing anything about the response.

Is there any way we could either set those headers for keymaster (not sure if thats actually what we want or how the flow would work in that case), be able to go through the flow in an iframe, or have the oidc golib package return a 401 Unauthorized with a link to the keymaster auth on AJAX requests (denoted by some header) so that we can manually redirect the user?

SameSite Unset in auth_cookie

I'm using keymaster as an openidc endpoint for a few sites and am seeing issues with the auth_cookie due to the lack of SameSite settings. I believe this should be set to "SameSite: None" if I am reading the Chrome FAQ correctly. Thoughts?

https://www.chromium.org/updates/same-site/faq

Q: What is the Lax + POST mitigation?
This is a specific exception made to account for existing cookie usage on some Single Sign-On implementations where a CSRF token is expected on a cross-site POST request. This is purely a temporary solution and will be removed in the future. It does not add any new behavior, but instead is just not applying the new SameSite=Lax default in certain scenarios.

Specifically, a cookie that is at most 2 minutes old will be sent on a top-level cross-site POST request. However, if you rely on this behavior, you should update these cookies with the SameSite=None; Secure attributes to ensure they continue to function in the future.

oauth2 login loses openid_connect_idp redirect destination

Have keymaster providing openid_connect_idp services to some services. Also have it configured to allow oauth2 logins.

When a user attempts to login to a service utilizing openid_connect_idp they are redirected to keymaster. If they click oauth2 login they are greeted with /profile/.

Steps to reproduce

  1. Go to site that utilizes openid_connect_idp from keymaster and attempt to login
  2. Click oauth2 login at the top
  3. See /profile/

Expected results
After oauth2 login succeeds I should be redirected to the original service (client under openid_connect_idp)

Security Vulnerability - Missing Authentication

Severity:

High Risk

Summary:

Missing authentication occurs when a system does not require authentication, allowing a user to escalate privileges in the system.

Details:

The security team discovered the keymaster application exposed an administrative interface at https://keymaster.example.com:6920/ that did not require authentication. By browsing to the URL, an attacker can view logs containing sensitive information such as, who is authenticating, what keys the user has registered, and the challenges used during new key registration, as shown in the attached screenshot.

An attacker can use this information to perform more sophisticated attacks.

Aud claim is not verified

Issue

Aud claim is not verified during the jwt verification step.

Steps to reproduce

NA

Impact

The "aud" (audience) claim identifies the recipients that the JWT is intended for. Each principal intended to process the JWT MUST identify itself with a value in the audience claim. If the principal processing the claim does not identify itself with a value in the "aud" claim when this claim is present, then the JWT MUST be rejected. In this case, since the aud claim is not being verified, unintended principles might be able to process the jwt claim.

Remediation

From looking at the code in the lines mentioned below, there is already a check for the issuer and the issuer value and the aud value are the same from (https://github.com/Cloud-Foundations/keymaster/blob/master/cmd/keymasterd/jwt.go#L57 ). Please add a check that will verify the aud claim as well.

Code/Lines affected

if inboundJWT.Issuer != issuer || inboundJWT.TokenType != "keymaster_auth" ||

if inboundJWT.Issuer != issuer || inboundJWT.TokenType != "storage_data" ||

Gnome Loads Bad Keys

Gnome-keyring ships with an ssh agent that will load all keys in ~/.ssh/ that have a corresponding pub key. This is documented here.

This creates the an issue for Gnome users since all temporary ssh keys are loaded. OpenSSH defaults to MaxAuthTries to 6, meaning that after a week of usage you find yourself unable to utilize new keys due to the loading of the temporary keys.

Logout does not invalidate auth cookie

Issue

Logging out of Keymaster does not invalidate the auth_cookie ie the jwt that is issued upon login.

Steps to reproduce

Login to Keymaster. Using a proxy such as Burp, one would be able to see the auth_cookie that is issued upon successful login. This is a jwt whose expiry is around 12 hrs. Send this request to the Burp repeater.
Now click logout. We will notice that the request we sent to the burp repeater will still work successfully despite the logout.
Additionally, if we re-login, the old jwt/auth-cookie will still be valid.

Impact

If a session can still be used after logging out then the lifetime of the session is increased and that gives third parties that may have intercepted the session token more time to impersonate a user.

Remediation

One possible solution would be - to store a “blacklist” of all the tokens that are no longer valid and have not expired yet. One can use a DB that has TTL option on documents which would be set to the amount of time left until the token is expired. Redis is a good option for this, that will allow fast in memory access to the list. Then, in a middleware of some kind that runs on every authorized request, one should check if provided token is in the blacklist. If it is, then throw an unauthorized error. Else, let the JWT verification handle the request and identify if the jwt already expired or is still active.
(Ref - https://medium.com/devgorilla/how-to-log-out-when-using-jwt-a8c7823e8a6)

newer Firefox fails to attempt U2F validation

I recently upgraded to Firefox 91.0.

Upon upgrading, the next time I logged in to Keymaster, I got to the point where it would ask for my Yubikey. However, the prompt just never popped up.

Did some debugging with @rgooch and he observed the following message on an already-logged-in profile page:

Your browser does not support U2F. However you can still Enable/Disable/Delete U2F tokens

Is this some sort of browser-support-detection problem? (I was unable to find a similar bug at the U2F-API page, so they may not know yet?)

Token validation for other user doesn't work

When an admin registers a U2F token for a user (by visiting the profile page for that user), an attempt to verify the token for that user does not work as expected. Instead, token verification for the signed in user (the admin) is performed.

The verification operation should specify the username corresponding to the profile page that is being viewed.

User list cleanup

Issue

The /users/ endpoint displays a list of all the Keymaster users to any logged in user. Also, there is no cleanup of this list in the backend.

Steps to reproduce

Login to keymaster (web) Go to the /users/ endpoint. One can see the names of all the users here.

Impact

There is no cleanup of users on keymaster backend. It would be great to add some mechanism to deactivate users on keymaster backend. Additionally, any logged in user can see a list of all keymaster users.

Remediation

Cleanup the user list so that only valid users are maintained in the database. Additionally, this list should ideally not be visible to non-admin users.

Keymaster timing out on RDS access

The last few days the Keymaster instances were not able to fetch the U2F token database from RDS and fell back to their cached versions. The effect on logins is a slight delay (a few seconds) but this would block people registering new U2F tokens. Restarting the daemons fixed the problem, but investigation is needed to understand why this failed and implement a permanent fix.

For reference, the instances first logged problems with fetching from RDS: GOT a timeout
The first error times were several hours apart. The timeout errors were immediately preceded by this error:
Error Preparing statement LoadUsers primary DB: write tcp XXXXX: write: broken pipe

Security Vulnerability - Insecure Input Validation

Severity:

High Risk

Summary:

Insecure input validation occurs when an application does not perform input validation before using untrusted input in a downstream component.

Details:

The keymaster application validates redirect URLs using a regular expression that does not take into account URL metacharacters such as ? and @. By using a ? character in a redirect URL, an attacker can force a victim to send their authentication credentials to an attacker controlled site. For example, this redirect_uri will send a user's credentials to rooted.systems instead of the intended target example.com

/idp/oauth2/authorize?client_id=Vpih48hsRwUv5oqpYYNg7f8u34RI1N2D%2F%2FknlziteYo%3D&redirect_uri=https%3a//rooted.systems%3f.example.com/

Upon authenticating with a malicious URL, the victim's credentials are sent to the attacker controlled site:

/?.example.com/?code=eyJhbGciOiJSUzI1NiIsImtpZCI6IiIsInR5cCI6IkpXVCJ9.[REDACTED].pBlnR6pIJxKFDiqoxz4FVmvchEDP4ubZKRQ3wk28Uu0 HTTP/1.1
Host: rooted.systems
...omitted for brevity...

As shown above, after authenticating with the malicious URL, the victm's authentication code is sent to rooted.systems as part of a URL parameter.

Where to filter usernames?

When using Okta as the primary authentication back-end, a user can enter either username or [email protected] and the Okta API will treat them equivalently. As described in issue #3, this presents a problem during the 2FA verification, as the U2F tokens are typically registered with just username. If the user tries to log in with [email protected] the token looked will fail and thus the user will not be able to complete the 2FA challenge.

Note that the Okta configuration typically has company as the domain. The implicit mapping to @company.com is internal to Okta.

Here are some potential solutions:

  1. Modify the Okta back-end to fail the login attempt if the user enters an @, thus forcing them to enter only username. This would prevent the user from getting into a limbo, half logged in state (as in issue #3), but it seems like an annoying user experience, as users have already gotten used to typing in [email protected]. Further, it may be challenging to present a clear message to the user explaining what went wrong

  2. Add a configuration option defining a filter regexp for the username string that the user enters. This provides a good user experience, but requires the administrator to modify the configuration (which may happen after some users complain and the administrator puts in the effort to figure out what's going wrong)

  3. Modify the U2F back-end to strip out the @ and everything afterwards. Again, this gives a good user experience and doesn't require tweaking by the administrator, but would hard-code in a limitation which would prevent supporting users from multiple domains (i.e. @company1.com and @company2.com).

Overall, I think option (2) is best, as it provides a good user experience and doesn't reduce potential future flexibility.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.