sul-dlss / media

placeholder (currently) for media team work
1 stars 0 forks source link

Check to see if wowza's token authentication blocks unauthorized requests for media segments #37

Closed jkeck closed 8 years ago

jkeck commented 8 years ago

The module we're adding to Wowza will intercept stream requests (playlist.m3u8 and manifest.mpd) and validate the token passed (by the stacks redirect).

We need to validate if this mechanism prevents users who can deduce how to request the file segments directly from downloading them w/o proper authorization by stacks.

jkeck commented 8 years ago

However we end up solving this, we'll need to keep in mind that a users IP could potentially change mid-stream (e.g. walking out of wifi range to a cell tower).

ndushay commented 8 years ago

We want to know what the current behavior is; @hannahfrost will talk to Mimi about legal issues.

jmartin-sul commented 8 years ago

tentative good news: it looks like you can't just go re-requesting media segments from wowza. if you pull up a purl page with a video, and you look at the network traffic in the browser debugger, you can see requests to wowza for a manifest.mpd, with a stacks_token in the URL params. the response from wowza appears to contain not a direct manifest with an actual list of chunks, but an XML response with a reference to another mpd file, seemingly guarded by its own wowza token, e.g.:

<Location>http://sul-wowza-stage:1935/stacks_test/_definst_/xv/428/cw/8400/mp4:JessieSaysNo.mp4/manifest_w804778405_qc3RhY2tzX3Rva2VuPWFHaElLMUZ2Ukdjd1MxaE5TamxKY25BMEx5dElTVkEyVFZwNFFYSjVRWGxwUzNSaE9YZEZlVGd4THpKbFpFWnVhVkE1YldsU05WSjViV2cwVHpKQk4xSnpNa1prUmtwcGFTc3dVMHRrWmtReGNHbFFkR3h3UlZCNVRGSTFNVTFJWm1wMWRWQnBaSEEzY3psVlZIWXdUbWhrUlRZM2QwdzJWbGR1ZEV0T1l6SlRObEYxTUZodWNIWldZMGN3TWtnNFRGaHJSM2dyTkdSdFZEbFVWMFJrYW5saFVtWnNZeTgwV2t4eU9FVXZhMU4ySzJzeU1XbFlWWFZoYW5reVdYZEtibFpNZUhKdFVXTTFiMEo1UXpZNGNFTXlUU3RQV0M5d1VXOVdWSG8yT0VzMmRYbHJjVmNyYXpONFNFeDJVSFUwYWl0RWQxTjNVR2hVVjNGTldWSXljazFsT1U5T2NrTmxNRlo1WlhGbk5VcDJjMWRFVUZCMVl6aDBMMkZYUTJvNU5VVkhaWFV2UjJ0T2NrMDlMUzEwVjFaVlNGWlJSbXd2YWxWc2IwTXdlblpGYzB0M1BUMCUzRC0tNjJhNzkzNDRhMGFjZTkxYjE1Y2I3ZWY3ZTQwYWQ5YjE5NDQyNjFkYw==.mpd</Location>

if you try to re-request that referenced mpd, you get a 403 forbidden.

additionally, at least for my test with "jessie says no", it appears that all the video players and all their chunks are pre-loaded. the chunk URLs look something like:

https://sul-wowza-stage.stanford.edu/stacks_test/_definst_/xv/428/cw/8400/mp4:JessieSaysNo.mp4/chunk_ctvideo_cfm4s_ridp0a0r0_cinit_w804778405_qc3RhY2tzX3Rva2VuPWFHaElLMUZ2Ukdjd1MxaE5TamxKY25BMEx5dElTVkEyVFZwNFFYSjVRWGxwUzNSaE9YZEZlVGd4THpKbFpFWnVhVkE1YldsU05WSjViV2cwVHpKQk4xSnpNa1prUmtwcGFTc3dVMHRrWmtReGNHbFFkR3h3UlZCNVRGSTFNVTFJWm1wMWRWQnBaSEEzY3psVlZIWXdUbWhrUlRZM2QwdzJWbGR1ZEV0T1l6SlRObEYxTUZodWNIWldZMGN3TWtnNFRGaHJSM2dyTkdSdFZEbFVWMFJrYW5saFVtWnNZeTgwV2t4eU9FVXZhMU4ySzJzeU1XbFlWWFZoYW5reVdYZEtibFpNZUhKdFVXTTFiMEo1UXpZNGNFTXlUU3RQV0M5d1VXOVdWSG8yT0VzMmRYbHJjVmNyYXpONFNFeDJVSFUwYWl0RWQxTjNVR2hVVjNGTldWSXljazFsT1U5T2NrTmxNRlo1WlhGbk5VcDJjMWRFVUZCMVl6aDBMMkZYUTJvNU5VVkhaWFV2UjJ0T2NrMDlMUzEwVjFaVlNGWlJSbXd2YWxWc2IwTXdlblpGYzB0M1BUMCUzRC0tNjJhNzkzNDRhMGFjZTkxYjE1Y2I3ZWY3ZTQwYWQ5YjE5NDQyNjFkYw==_mpd.m4s

again, the segment seems to have its own token built into the URL, and trying to replay the request results in a 403.

someone should pair with me for a few minutes if possible and at least look over my shoulder to make sure i'm not missing anything while looking at the network traffic. also, i haven't tried things like constructing URLs that might get at manifests that list chunks directly, or constructing URLs to retrieve chunks directly. i'm not sure i have an informed idea of what such a URL might look like.

it also occurred to me that we should probably email wowza support and describe this question and get their official position on it. i'm guessing others have to have run into this question before.

the actual content of the chunks is, of course, available to the user since they are playing the video. for example, the browser debugger shows the response to each chunk, so you can imagine that a dedicated nefarious user who has access might write a script to play the video but record the contents of the media chunks they get back, which they could then stitch back together into a playable video file. one way to prevent that problem with really sensitive content would be to restrict access to reading room only and to make it hard to exfiltrate content from reading rooms (not sure if that's already the approach, having never visited one of the reading rooms myself).

jmartin-sul commented 8 years ago

here's the content of a helpful email exchange i had with wowza support, where they explained the options available to us for securing streams (TL;DR: it appears that they support a similar token auth scheme to ours, as suspected based on the testing described above):

my original message:

Hello,

We're using Wowza to serve streaming audio and video. We wrote a plugin that denies access to streams in the absence of a valid token issued by another service of ours (https://github.com/sul-dlss/dlss-wowza/blob/master/src/edu/stanford/dlss/wowza/SulWowza.java). We were also concerned that a user might be able to replay requests for the individual segments listed in the stream manifest (e.g. captured from the traffic monitor of the browser debugger). Our worry is that if a user can replay requests for segments, they could do something like construct a new manifest which points to the segments on Wowza, and use that manifest to replay or share the stream in the absence of a valid auth token from our service (the token we issue is time limited, and is essentially intended for immediate use).

What protection is there against this sort of user behavior? My initial testing showed that the manifest Wowza returns actually points to another manifest which appears to be protected by a Wowza issued token, and the individual segments listed there also seem to be protected by usage-limiting tokens. Is this always how streams are served? Is my understanding correct that Wowza is protecting the segments it serves with a similar expiring token mechanism to the one we're using? If so, what causes the Wowza tokens to expire (e.g. time limited, single use, etc)? Finally, are there other ways to construct Wowza URLs to get at a manifest or at the content of a stream segment if the user knows the Wowza application name and the name of the stream they're interested in?

Obviously the user could also capture the content of each segment as they receive it for the first time, assuming they had a valid token from our service for the particular stream in the first place. So we know that we have to have some trust in the machine/end-user receiving the stream. We're just trying to figure out the corner cases so that we can document the limits of our system so that we can judge how to serve sensitive content as we bring our streaming service online.

Thanks very much... -john

their reply:

[wowza support rep], Jun 13, 3:33 AM CDT: Hello,

Thank you for contacting Wowza support. You have the possibility of using the Wowza Secure Token V2 protection for outgoing/playback streams. The token can be configure to expire after a certain time, but you cannot specify the number of times it can be used. However, you can specify the client IP for which a particular token is valid. If a playback client is trying to access the same playback URL, using a different client IP than the one for which the token was generated, the playback attempt will fail. Using the secure toke, a playback client will request the stream playlist and starting with chunklist and the individual media chunks, the token information is incorporated into the chunklist and media chunk name.

In addition to the Secure Token protection, you can also choose to encrypt the media chunks as well. Using an external logic (or internal, through a Wowza custom module) you will provide the decryption key to the authorized playback client only.

Here are some forum articles that you might find useful: https://www.wowza.com/forums/content.php?620-How-to-protect-streaming-using-SecureToken-in-Wowza-Streaming-Engine https://www.wowza.com/forums/content.php?60-How-to-secure-Apple-HTTP-Live-Streaming-(AES-128-external-method) https://www.wowza.com/forums/content.php?59-How-to-use-the-internal-method-of-AES-128-encryption-to-secure-live-or-VOD-streams-sent-to-Apple-iOS-devices-(ModuleEncryptionHandlerCupertinoStreaming) https://www.wowza.com/forums/content.php?245-How-to-test-AES-encryption-for-Apple-HLS-streams

Regards, [wowza support rep]

so it appears that Wowza offers what we're looking for. would be good to confirm w/ the docs, but it appears the token protection is enabled by default, or at least it was enabled on the application on which i was testing.

jmartin-sul commented 8 years ago

i think this can be closed, since it was about investigation, and the investigation into what options are available seems to be complete.

one final note: if you read the first doc linked in the wowza support reply, you'll notice that it actually seems to describe a feature in wowza that's very similar to the token system we implemented in stacks. (hash some expected values related to the stream and user, pass the resultant hash to the user in the streaming link, wowza checks the hash when the user makes the request, wowza serves the stream if the hash matches a hash generated from what should be the same expected values). that feature is turned off by default (and would require additional and possibly redundant stacks work to enable, considering our existing token mechanism).

since the testing i did seems to indicate that there's already other protection enabled by default to stop replay attacks, and since we've already implemented a token generation mechanism for authorizing streaming requests, i'd propose that we close this issue, with the expectation that there's no further configuration to be done on this specific front.