How to serve videos in a website somewhat securely - security

I am asking a question that's somewhat related to these:
Secure way of serving videos
secure streaming of videos
However, no one provided an answer that seems relevant to my situation.
My situation is as follows:
I'm building a very simple Learning Management System. Students have access to Video lessons if they have paid for it. I would like to prevent:
bots/spiders from finding these videos and downloading it
for people to simply view source, copy the url of the video, and share it with other people
I doubt very much people will try to hack the site to steal the videos.
What is the best way to secure these videos from being shared? Do i have to store the videos on my webserver? Can i leverage video platforms like youtube or vimeo?

Long story short, there is no simple solution.
I will say straight up that if there was a way to stop people from downloading videos, every video website would be doing it.
I have thought of a few ways, listed out below, of what you could do to make it not worthwhile for the student/viewer to download the videos.
obscure the URL
change the URL frequently
restrict the number of downloads per IP address/subnet
make them view it in a custom-built "custom-served" video player
use a video streaming service already available
Each are discussed in greater detail below.
Obscuring the URL
You could obscure the URLs like so:
http://mylearningmanagementsystem.com.au/e12d8cd38f00f204e9801998ecc8427e/video.flv
You could calculate a hash of the name of the file itself (or salt and hash, the above is just an example) and use that in a URL.
This could be achieved in such a way that they would be obscure enough, but still bookmarkable and user-friendly for the viewers.
If you wanted to go one step further, you could have video broken up into parts - this is discussed in the custom built section.
Change the URL frequently
With some code, you could set the videos to change URLs every Sunday night at 11.59pm for your timezone. However, any page that you link to would have to be either automatically or manually updated, and that is a hassle in itself (how do you test the code/what if it falls over and you don't realise/things like that).
Even if you get all of that working, any user that bookmarked the page would suffer from link rot.
Restricting the number of downloads per IP address/subnet
With some funky server-side code, you could limit the number of times a video can be downloaded to an IP address (or depending on the user case, a subnet of the IP).
This is not my strong point, but you could look at articles on Dynamic IP Restrictions. The below is an excerpt from the website
Dynamically blocking of requests from IP address based on either of the following criteria:
The number of concurrent requests.
The number of requests over a period of time.
There is also the possibility of doing the same with Drupal.
Make them view it in a custom-built "custom-served" video player
You can go the extra mile and make your own video-management system (which it seems like you are), and serve the videos from your own server (which is what I meant by custom-served) but some programs that have attempted this were flawed like Sony's CD management software or were punishing honest users, like Apple iTunes' FairPlay DRM software.
If you do end up going the route of giving users a program/web service to watch videos and restrict them to an password/encryption key, you could annoy the customers who paid for your content in good faith. This is essentially what all copyright protection systems tried and utterly failed with, because either the program wasn't secured well enough or people simply stopped using it because it was awkward to work with.
When you serve the videos to the users, you could break them up and separate them by chapters, as in the first chapter is one video, the second is another, and so on (like below):
http://mylearningmanagementsystem.com.au/video_title/chapter_01/video.flv
http://mylearningmanagementsystem.com.au/video_title/chapter_02/video.flv
http://mylearningmanagementsystem.com.au/video_title/chapter_03/video.flv
... and you could combine that with the hashing idea in the first section (Obscuring the URL):
http://mylearningmanagementsystem.com.au/e12d8cd38f00f204/8fd3611c40e74c3d/video.flv
http://mylearningmanagementsystem.com.au/e12d8cd38f00f204/92d7f54d09c80436/video.flv
http://mylearningmanagementsystem.com.au/e12d8cd38f00f204/27bd98792bea3103/video.flv
This could have its downsides though:
low internet users who pause the video at the start to let it load, will experience issues (less common a problem now, as the internet is now much faster and easier to access)
if one video is missing, the whole video will be unplayable
how will you manage each link? Will each video name have the same hash or a different hash?
will you have to manually break up each video?
The key point here is that this does make a lot of unnecessary work for you. The next option would be to use a video streaming service that is already available.
Use a video streaming service already available
There are plenty of options out there to host and share your video. YouTube and Vimeo are two of these options. I will explain why I prefer the latter.
Password protection
If you wanted to share the videos only with a specific number of paying people, you can protect your videos with a password on Vimeo. AFAIK, YouTube does not offer this service - it only allows you to select members to view the video.
Not only that, but you can add a bunch of videos to an album (in Vimeo), and password-protect the album, so you only have to change the password for the album.
Keep in mind that you may run into increased support messages like "But is this the current password or the one for last week?"
Set embed settings
You can make the video unable to embed on any page, so that users would have to go to Vimeo directly, type in the password (if you set one above), and view it inside their web browser. AFAIK, you can embed any video from YouTube that you can view.
You will have to keep in mind that a quick Google search revealed that there are heaps of online sites that allow you to download videos from these video-hosting websites. There are even browser addons for Firefox and Chrome.
If your business depended on your videos for monetising purposes and you wanted to go one step further, there are paid streaming services that specialise on content distribution with proper access right management and content protection. One of these services is Brightcove. Excerpts from Brightcove follow:
Brightcove Video Cloud securely delivers the highest quality on-demand and live video experiences to reach your audience—no matter where they are. We simplify delivery to an increasingly complex ecosystem of devices and standards across the web, mobile and connected TVs
... and ...
Protect your valuable content
Ensure your video is safe. Use RTMPe stream encryption and SWF verification to prevent video stream ripping and content theft and ensure that your video stream plays back only in your authorized players.
Fine-grained Access Control
Pinpoint exactly when and where your content is displayed to comply with content licensing restrictions, global launch roll-out schedules or secure behind-the-firewall delivery. The user-friendly graphical interface allows you to restrict access by date, domain, geography, player or IP address. For even greater control restrict access to sensitive materials by IP address range and ensure content is accessible only from within approved networks.
At the end of the day...
If you can view it, you can download it, no matter how much you obscure it.
If there was a way to stop people from downloading videos, every video website would be doing it.
If you had unlimited resources, you could combine all of the techniques listed above to make it not worth anyone's time. But, after all the effort you put in, a viewer could always set up one of many screen capture programs to record all the videos onto their hard drive.
It's up to you, and how vigilant you want to be with your videos. Remember that the effort and time you spend making it harder to rip a video, is proportional to making it harder for regular paying customers to get and use the content as well.
More information:
How can I make a video not downloadable?
Vimeo privacy settings
Video streaming service | Online Streaming Video | Brightcove

Maybe it's a bit too late, but I'm putting this here so that it would help others.
As others have stated, there's no way to secure contents once they reach someone's computer. But we can prevent uncontrolled sharing of the content by putting some barriers in place.
One such method that I've noticed many websites including linkedin, pluralsight, and many others use is a resource url with authorization information secured with hash. Such tokens include enough information for identifying the content to be served and a time-frame between which the url is valid.
Suppose the video you want to secure is :
example.com/videos/1234.mp4
Here's an example of how you'd generate a token on first request of the resource (after you've authenticated the user and done other verfications) :
validFrom = unixTimestamp
validTo = unixTimestamp
video = 1234.mp4
privateKey = yourSecretKey
token = HASH(validFrom.validTo.videoUrl.privateKey)
Now, create a url with all the above information excluding the private key. Your final url would be something like this :
example.com/video?validfrom=1566831998&validto=1566839198&path=1234.mp4k&hash=HhgcWmRViYeQLn4AZoQvkVXotPU
Now, whenever a request is made for a video at the path /video, you'd take all the parameters from the url (excluding the hash), and create a hash as you did earlier from the parameters and your private key in the same order. The url can be said to be valid and untempered if the hash that you just generated matches with the one that was included in the URL. This same technique is used in JWT authentication and is really efficient. As you don't have to store or retrieve information to and from any database. This makes it very quick and easy to implement.
Once you've validated the token, you can return the FileStream to the media that was requested in the url.

If it is a small and not too dynamic group then youtube or vimeo might be a possible option. But it is not scalable.
If you have a dynamic audience where members may join and leave at different times then you need to have the videos encrypted on your own server.
The biggest challenge now would be the key distribution. You need to have the key scheme such that each user has a unique key but the key used to encrypt the video is the same.
Here is one possible method: https://sparrow.ece.cmu.edu/group/pub/old-pubs/elk.pdf
other algorithms you might want to look at are : MARKS, LKH, etc.

Related

Meteor Security Permissions on Uploaded Images

I'm creating a Meteor chat app. I want users to be able to send images to each other, but users not in the group/conversation shouldn't be able to see the image. My first thought was to give an image a unique ID and store the image with this ID in a public folder in my or a 3rd party server.
For example, if the user uploads an image called "name.jpg", it could be stored in Amazon S3 as A3eedAcRCqCa32451.jpg. That way, anyone with the ID can access the image, but the only people with access to the ID would be those in the group chat, since I can ensure secure access using Meteor's publish and subscribe rules. However, this doesn't feel safe to me. Is my intuition right?
If yes, how else would I do it? I searched online and on StackOverflow and couldn't find another simple way to achieve this.
You usually have two things you can do when considering granting access to resources:
Authentication and access control
Indirect object references with sufficient entropy to make brute force attacks hopeless.
Point 1 is more or less obvious.
Point 2 is actually what you have already on your mind. To reason about the security of the second approach let's consider following:
The entropy of A3eedAcRCqCa32451.jpg is about 80 bits.
The count of the domain is 2^80 = 1208925819614629174706176.
An attacker can try to guess the secret.
Let's say, he can make 10 guesses a second and on average he will guess after |domain|/2 tries.
It would take the attacker ~2 mln years to guess.
Now the domain of 80 bits is a bit small from the security perspective. Make it 128 bits by using type 4 UUIDs. I believe you see where this is going.
It depends on the security level you want...
A more secure solution would be to store in a collection the imageId and userId of people that can access the image. When someone wants to access it, you just have to check if he's in the list of allowed users.
Then as you said you can use a 3rd party storage (personally I'm using ostrio:files with Dropbox integration, the docs about it aren't up to date but I made a pull request which was accepted on the dev branch with a working example, you can take a look at it here.)
The nice thing with ostrio:files is that it offers built-in functions like onAfterUpload or interceptDownload in which you can store data about access for the first and check if access is allowed for the second.

Amazon cloudfront how to set signed url outdated if used one time

I need to protect my videos to be downlouded using "Internet Download Manager - IDM/IDMan"
i used
1. rtmp stream
2. signed URL
3. expiration date of signed URL (60seconds)
4. i set player(jwplayer)to *autostar*
AND i need to set signed url outdated if it used one time
using this solution IDM will get an url that is already used then blocked
Is there any way to configure cloudfront to use signed url just one time;
Or any solution that can protect videos to be uploaded and used in other web sites.
Please can you help?
Thanks in advance
Cloudfront does not support the ability to only play a url once and they never will. The reason is that the only way to do this will be for all their edge servers to share the information - they currently do not share state which means scaling is much easier and performance is much better.
Unfortunately, if you're looking for fine grained control over how your videos are played, you're going to need more fine grained code, which you can't do in cloudfront - you'll need to host content directly on your server.
Idea 1: Limit by count
You can implement the idea that you have - once the url has been used once, you no longer serve up that file.
Idea 2: Limit by referrer
You can look at the referrer header and if it's from your website, then allow the content to be downloaded. Otherwise, reject it. Note: this can be spoofed and a user can set the referrer header manually.
Preventing a video from being downloaded and later uploaded is technically impossible. By letting them display the video, there really isn't any way to do that without them being able to record those bits and replay them later. There are probably things, like preventing right clicks or using an odd proprietary format or something else but I'm not familiar with DRM techniques.

What's a good approach to securing MP3 files for a private podcast with Amazon S3?

I'm trying to create a private podcast feeds. Each user of my service gets an account and depending on what they pay, they will receive different content. Some content is sensitive so security is reasonably important; if any of the enclosed audio files made the rounds around the internet, it could be catastrophic for our business.
I am currently prototyping the service and MP3s are stored on S3 and they are not secured. It's time to secure them. From my research, I understand that I can, in fact, secure files on S3 with an access expiry period. But, because I have many users, signing the request with my "global" key and have an expiry probably isn't a good idea because
If I need to revoke access, I'll need to do it for everyone
Since I don't know when, exactly, their podcatcher will request the file, I don't know when to set the expiry. Sometimes, the podcatcher downloads the feed XML, but only later fetches the MP3 file so the URLs could expire before the client has a chance to fetch them (I'm thinking about iTunes, but there could be others).
The way I see it, I have two options and I'm not sure if either are workable:
Edit Another potential way, I suppose, would be to role my own security, and simply redirect to an MP3 on S3 with a short expiry if the user is good to go. This seems most sensible.
I can create user accounts on Amazon for ALL of my users and link them to an Amazon token in my database. Everyone's MP3 urls are signed with their secret token and expiry a long time from now. I don't like the idea of storing their tokens on my database, and I'm not sure if the Amazon ACL was designed for this scenario. It also means the files can still be shared if you know the URL.
I can proxy every request through my server. This means I only have one Amazon account, and I can role my own security system. But proxying every MP3 download through my server sounds slow, wasteful and expensive.
Any ideas on the best way to do this.
P.S. I'm not married to S3. Other solutions could be considered. And I'm on Heroku using Ruby, in case you care.
I am going with the redirect solution suggested elsewhere. This seems to give me the most flexibility and very low overhead. What you definitely should not do is is using links directly to S3 in your feed, because they likely expire before they are downloaded by the client.

What is a simple and secure way to transmit a login key from one website to another while redirecting a user?

I want to create a portal website for log-in, news and user management. And another web site for a web app that the portal redirects to after login.
One of my goals is to be able to host the portal and web-app on different servers. The portal would transmit the user's id to the web-app, once the user had successfully logged in and been redirected to the web app. But I don't want people to be able to just bypass the login, or access other users accounts, by transmitting user ids straight to the web app.
My first thought is to transmit the user id encrypted as a post variable or query string value. Using some kind of public/private key scenario, and adding a DateTime stamp to key to make it vary everytime.
But I haven't done this kind of thing before, so I'm wondering if there aren't better ways to do this.
(I could potentially communicate via database, by having the portal store the user id with a key in a database and passing that key to the web app which uses it to get the user id from that database. But that seems crazy.)
Can anyone give a way to do this or advice? Or is this a bad idea all-together?
Thanks for your time.
Basically, you are asking for a single-sign-on solution. What you describe sounds a lot like SAML, although SAML is a bit more advanced ;-)
It depends on how secure you want this entire thing to be. Generating an encrypted token with embedded timestamp still leaves you open to spoofing - if somebody steals the token (i.e. through a network sniffing) he will be able to submit his own request with the stolen token. Depending on the time to live you will give your token this time can be limited, but a determined hacker will be able to do this. Besides you cannot make time to live to small - you will be rejecting valid requests.
Another approach is to generate "use once" tokens. This is 'bullet proof' in terms of spoofing, but it requires coordination among all the servers within the server farm servicing your app, so that if one of them processed the token the other ones would reject it.
To make it really secure for the failover scenarios, etc. it would require some additional steps, so it all boils down to how secure you need it to be and how much you want to invest in building it up
I suggest looking at SAML
PGP would work but it might get slow on a high-traffic site
One thing I've done in the past is used a shared secret method. Some token that only myself and the other website operator knows concatenated to something identifying the user (like their user name), then hash that with a checksum algorithm such as SHA256 (you can use MD5 or SHA1 which usually are more available but they are much easier to break)
The other end should do the same thing as above. Take the passed identifying information and checksum it. Compare that to the passed checksum, if they match the login is valid.
For added security you could also concat the date or some other rotating key. Helps to run SSL on both sides as well.
In general, the answer resides somewhere in SHA256 / MD5 / SHA1 plus shared secret based on human actually has to think. If there is money somewhere, we may assume there are no limits to what some persons will do - I ran with [ a person ] in High School for a few months to observe what those ilks will do in practice. After a few months, I learned not to be running with those kind. Tediously avoiding work, suddenly at 4 AM on Saturday Morning the level of effort and analytical functioning could only be described as "Expertise" ( note capitalization ) There has to be a solution else sites like Google and this one would not stand the chance of a dandelion in lightning bolt.
There is a study in the mathematical works of cryptography whereby an institution ( with reputable goals ) can issue information - digital cash - that can exist on the open wire but does not reveal any information. Who would break them? My experience with [ person ]
shows that it is a study in socialization, depends on who you want to run with. What's the defense against sniffers if the code is already available more easily just using a browser?
<form type="hidden" value="myreallysecretid">
vis a vis
<form type="hidden" value="weoi938389wiwdfu0789we394">
So which one is valuable against attack? Neither, if someone wants to snag some Snake Oil from you, maybe you get the 2:59 am phone call that begins: "I'm an investor, we sunk thousands into your website. I just got a call from our security pro ....." all you can do to prepare for that moment is use established, known tools like SHA - of which the 256 variety is the acknowledged "next thing" - and have trace controls such that the security pro can put in on insurance and bonding.
Let alone trying to find one who knows how those tools work, their first line of defense is not talking to you ... then they have their own literature - they will want you to use their tools.
Then you don't get to code anything.

What identifying information can a website capture?

If the owner of a web site wants to track who their users are as much as possible, what things can they capture (and how). You might want to know about this in order to capture information on a site you create or, as a user, to prevent a site from capturing data on you.
Here is a starting list, but I'm sure I have missed some important ones:
Referrer (what web page had the link you followed to get here). This is a HTTP header.
IP Address of the machine you are browsing from. This is available with the HTTP headers.
User Agent (what browser you are using). This is a HTTP header.
Cookie placed on a previous visit. This is a header, available only if a cookie was placed earlier and was not deleted by the user.
Flash Cookie placed on a previous visit. Some users turn off cookies, but very few know how to turn off Flash cookies. Works like a normal cookie although it depends on Flash.
Web Bugs. Place something small (like a transparent single-pixel GIF) on the page that's served up from a 3rd party. Some third parties (such as DoubleClick) will have their own cookies and can correlate with other visits the user makes (for a fee!).
Those are the common ones I think of, but there have to be LOTS of unusual ones. For instance, this:
Time on the user's clock. Use JavaScript to transmit it.
... which I had never heard of before reading it here.
ADDED LATER (after reading this):
Please try to put just ONE item per answer, then we can use voting up to sort out the better/more-interesting ones. The list below is probably less effective.
Ah well... NEXT time I ask a question like this I'll set it up better.
And here are some of the best answers I got:
James points out that IE transmits the .NET framework version.
AviewAnew points out that one can find what sites you have visited.
Mecki points out that Screen Resolution can be determined.
Mecki also points out that any auto-fill information your browser has cached can be determined, by creating a hidden field, then reading it with JavaScript.
jjrv points out that Flash can list the fonts on the user's machine.
Kent points out that you can find out what websites a person has visited.
Silver Dragon points out you can determine the location of the mouse within the browsing window using Flash and AJAX.
Jim points out that you can tell what language the user has configured in their browser from a HTTP header.
Jim also mentions that you can detect whether people are using Greasemonkey or something similar to modify the page.
Modifications to your original:
can be escaped ( i think its an option in some browsers )
only avoidable with a proxy ( javascript can contravene this however with smart lookaround )
is unreliable, easily forged.
And assuming it was not wiped by browser closure ( session cookie ) and cookie is in the same domain/path
The real nasty ones are
Using javascript to probe your network/lan
Using javascript to access your firewall from behind the firewall and adjust its settings ( no joke )
Using the feature of the "visited link" to determine which of a list of urls have been visited. ( deep history probing ! )
Goodness knows what if the user has Windows/IE/ActiveX
There's a header that can include information about a proxy server the user is using, and that can also include the user's IP address (in which case the other IP is the one of the proxy)
Screen Resolution, Operating System, Color Depth, size of your taskbar (compare max and current resolution), if Java is enabled, Anti-Aliasing Fonts, Plugins Installed all via Javascript
A Java applet can give you a bunch of information as well, but I don't know what.
Sites you've visited
Details of your local network such as active hosts, web servers. Paper Also outlines drive-by printing, drive-by router modification
And this is all assuming the attacker doesn't pull off arbitrary code execution
Javascript can get more information than just time. E.g. screen resolution (+ color depth) being one of them.
See Getting Screen Resolution with JS
Everything JS can capture, can be transmitted using AJAX without the user performing any interaction. Other examples are (not all will work in every browser):
It can look into your browser history, e.g. what URL your browser would go if you hit back or forward.
The language of your browser (Note: usually the HTTP request will also contain a list of preferred languages for the page you request. However this list is user editable in the prefs of many browser, while JS can actually find out what the language translation your browser is using in the interface)
If your browser auto fills form fields (e.g. e-mail, username, etc.), JS can actually already read what your browser entered into the fields before you submitted the form (thus it can even read what your browser pre-filled there, even if you never submit the form at all).
A Java applet could also gather some information and transmit it, though there is not much information you wouldn't already get elsewhere. Since it's easy to get the IP of a visitor, it's possible to find out which online service he's using (looking up the IP at address services like IANA for USA or RIPE for Europe and so on) and there are services that translate IPs to country, so it's possible to find out where the user most likely is currently located.
Some additional info, that might be of interest:
Using the ip address, one can resolve the hostname, net provider / organization the IP belongs to, and rough geographic location.
Using the referer, the list of queries a specified client makes, and a reliable cookie mechanism, one can resolve the path the visitor makes (even clickthroughs to other sides, with AJAX and/or a forwarder page)
Using flash, with a combination of AJAX, the mouse location within the browsing window can be captured
The User Agent might contain information regarding operation system, installed .NET frameworks, and other curiosities
.NET framework versions are transmitted in IE, in the User Agent.
Flash can give you a list of fonts on the user's machine among other things. Javascript can send information when the mouse stops over an ad without clicking it. You can also get the window size, whether the site is open in a frame, if popups or specific plugins have been blocked, looking for Javascript features can tell if the user agent header is correct or faked...
If you're concerned about your personal security (I'm not sure if that's what you're really getting after, so my apologies if this is misguided), you can always use a Tor network. If you use Firefox, you can use Torbutton for one click enabling. It has the benefit (drawback, to some), of disabling Flash because it's otherwise impossible to protect against Flash information leaks.
You can usually determine which language the user speaks through the Accept-Language HTTP header.
You can determine whether certain applications and browser plugins are installed by looking at the Accept HTTP header.
Browser version/patchlevel and .NET framework version through the User-Agent HTTP header.
Your ISP/Employer and geographical location through IP address.
Whether or not you have visited particular URLs through CSS and/or timing load events. If a particular website has user-specific URIs, this could disclose whether you are a certain user on that site or not.
Which fonts are available through measuring ems and/or Flash.
Screen resolution, window size, timezone through JavaScript.
Where you move your mouse and keystrokes through JavaScript. For instance, you can see what people type into text boxes even if they don't hit submit.
Many UserJS/Greasemonkey scripts leak information (e.g. if you filter out certain people, the sites it is configured for may be able to find out who).
Can the browser support JS
Can the browser support flash
Operating system platform
Screen resolution
Supports CSS
Supports tables
I need to dig up the link, but if the user is using IE, with common software titles installed, determining which ones are installed is possible.
As far as I know, it's possible to get clipboard data via javascript. Not sure how possible it is by default these days, but it was all the rage not long ago. I do believe IE still allows it.
People have a habit of leaving very important data in their clipboard, so this is pretty bad.
late to the party here, the website can also scan your ports, to find what software you are running!

Resources