I haven’t blogged for quite some time, so I thought it was worth re-launching with an interesting, albeit simple, high-impact bug.
When you browse to the site, all requests are redirected to
/auth?redirect=/ (since we don’t have a valid session), which in turn redirects to Google for authentication.
The redirected URL, shown below, contains various parameters, but the most interesting one is
hd. This is used to restrict logins to a specific domain, in this case
If we try and login with an account such as
firstname.lastname@example.org, we’re redirected back to the account selection page, and if we try again we get redirected back to the same place, and so on.
However, we can simply remove this parameter. There’s no signature in the URL to prevent us from making modifications, and as indicated in the documentation, the onus is on the application to validate the returned token.
This gives us the following login URL (you may also notice I’ve removed the Google+ scope, this is purely because my test account isn’t signed up for it):
Browsing to this new URL prompts us to authorise the application.
After clicking “Accept”, a redirect is issused back to the administation panel, with our code as a parameter.
This is where the application should then exchange the code for an access token, and validate the returned user ID against either a whitelist, or at the very least verify that the domain is
But, in this case, the assumption is made that if you managed to login, you are an employee with an
userinfo.profile permission doesn’t contain the user’s email address, so the application can’t validate it if it tried.
This then presents us with the admin panel.
From here we can now manage various aspects of Periscope, including users and streams.
Twitter fixed this by making two changes. The first is to request an additional permission:
The second is to correctly validate the user on callback.
Now, the application returns a 401 when trying to authenticate with an invalid user: