I am using VSTS 2008 + C# + .Net 3.5 + Silverlight 3.0 + ASP.Net to develop a Silverlight application (a video media player) in browser and the function is simple, just use MediaElement to play a remote video file.
The remote server is Windows Server 2008 + IIS 7.0 + IIS Media Bit Rate Throttling Control.
Since the request media URL can be discovered (e.g. from traffic sniffer), and I want to know how to prevent from download directly from the Url? i.e. I want end user to use my Silverlight media player application in browser to play the file, prevent them from download to local directly. Any easy and quick solution or reference code/documents?
I might be clutching at straws here but what about using a HTTP handler to intercept requests to the media URL: When the HTTP handler encounters a request, it checks for a unique HTTP header in the request - this could be hard coded into your media player application so that the URL request is accompanied with the appropriate security header - and unless the HTTP header is present then all response is blocked. I know there are no code specifics here but it's an idea all the same.
Use the ASP.NET Authentication Service to authenticate/authorize your user
Put the video in a folder where the web.config prevents un-authenticated access to the contents
If I'm not mistaken (and to be truthful, there is a chance as I've never tried this particular scenario) ... that will protect your video content, while allowing the authorized user to access it via silverlight.
What Joel suggested above could make sense. Especially if the Silverlight hosting web application was running in an app pool that ran under a particular identity (i.e. "svcMyVideoApp"). Then you could make it where only this identity could access the content folder. Set all other requests for content to deny (except maybe your own :) )
If i'm not mistaken... if properly set up, IIS 7's media services shouldn't even serve the raw files no more then it should serve a raw unprocessed "aspx" page.
I only played with this a little a few months back, but when I installed the Media plugin for IIS 7, it was not serving the raw media files, and I could only access them via a silverlight interface. I used Expression Studio to create my silverlight viewer page and had it encode it for "smooth streaming".
A simple way would be to add a handler to catch the request like #pb said. I don't know if sending headers is the right thing or not though. A simple way would to just check if the request has a referrer..
String.IsNullOrEmpty(context.Request.ServerVariables["HTTP_REFERER"])
or you'll need authentication and to send the auth cookie with the request.
Related
Question: If I have an untrusted, user-supplied URL to a file, how do I protect myself against server-side request forgery when I download that file? Are there tools in the .NET Framework (4.8) base class library that help me, or is there some canonical reference implementation for this use case?
Details: Our web application (an online product database) allows users to upload product images. We have the requirement that users should be allowed to supply the URL to a (self-hosted) image instead of uploading an image.
So far, so good. However, sometimes our web application will have to fetch the image from the (external, user-supplied) URL to do something with it (for example, to include the image in a PDF product data sheet).
This exposes my web application to the risk of Server-Side Request Forgery. The OWASP Cheat Sheet documents this use case as "Case 2" and suggests mitigations such as validating URLs and backlisting known internal IP addresses.
This means that I cannot use the built-in methods for downloading files such as WebClient or HttpWebRequest, since those classes take care of DNS resolution, and I need to validate IP addresses after DNS resolution but before performing the HTTP request. I could perform DNS resolution myself and then create a web request with the (validated) IP address and a custom Host header, but that might mess up TLS certificate checking.
To make a long story short, I feel like I am reinventing the wheel here, for something that sounds like a common-enough use case. (I am surely not the first web developer who has to fetch files from user-supplied URLs.) The .NET Framework has tools for protection against CSRF built-in, so I'm wondering if there are similar tools available for SSRF that I just haven't found.
Note: There are similar question (such as this one) in the ssrf tag, but, contrary to them, my goal is not to "get rid of a warning", but to actually protect my system against SSRF.
Confirm the requirement with the business stakeholders. It's very possible they don't care how the file is obtained-- they just want the user to be able to specify a URL rather than a local file. If that is the case, your application can use Javascript to download the file from the browser then upload it from there. This avoids the server-side problem completely.
If you have to do it server-side, ask for budget for a a dedicated server. Locate this in your DMZ (between the perimeter firewall and the firewall that isolates your web servers from the rest of your network). Use this server to run a program that downloads the URLs and puts the data where your main application can get it, e.g. a database.
If you have to host it on your existing hardware, use a dedicated process, running in a dedicated application pool with a dedicated user identity. The proper location for this service is on your web server (not application or database servers).
Audit and monitor the security logs for the dedicated user.
Revoke any permission to private keys or local resources such as the filesystem.
Validate the protocol (http or https only).
To the extent possible, validate the IP address, and maintain a black list.
Validate the domain name to ensure it is a public URL and not something within your network. If possible, use a proxy server with public DNS.
Our application uses the Chromium Embedded Framework. We need a way to communicate to our servers within our requests that they are communicating with a Chrome browser embedded in our application. Changing the user agent isn't really an option because some sites do not play well with browsers which are not recognized. I suppose we could get around this by appending the application name to the end of the default Chromium user agent header. Our server could then check to see if the user agent header contains the name of our application. I'm unsure though if some sites will still have an issue recognizing our application with this method. I'm also unsure if there is better way to indicate this, maybe through the use of cookie or setting a custom field on the request header?
I'm protecting my MP4 files on my site from hotlinking by passing the request to a generic handler with code taken from here: VideoStreamer Iphone/Ipad. The URL to the MP4 file is dynamic for each session, which is validated by the generic handler before the MP4 is streamed to the visitor.
It seems to work great for desktop browsers, but when testing on my Android, I'm unable to play the video. Might be worth noting that I'm routing my generic handler to a route such as http://example.com/myroute/dynamicfilename.mp4 with a handler within my web.config to deal with all requests for .mp4 files.
Without routing, the playback works on the Android phone using the same code. Hence, I suspect that this has got something to do with the route. Maybe that I'm handling an MP4 file extension?
Any thoughts? Is there some other/better/recommended way to do this (maybe using context.rewrite?) or some other method in IIS that is similar to httpd mod_secdownload?
It turns out that Android (maybe iOS too) video player app at some point stops using the session passed by the browser. Hence, the first request that uses the session is valid, while the second request by the video player app receives a 404 because my generic handler could not validate the dynamically generated URL. No solution here, but it might help if somebody ends up into a similar puzzle in the future.
Q: is it possible to manipulate http request header or using any other technique in C# when making request (to servers like yahoo.com/cnn.com) using C#, so that the returned web page text(stream)'s size can be greatly reduced - a simplified webpage without all other extra scripts/image/css? or even better can I just request a sub-section of the webpage of my interest to be downloaded only? I just need the responded page to be minimized as much as possible so that it can be downloaded as fast as possible before the page can be processed later.
It really depends on the site and services it provides and configuration it has. Things that may help to look for (not a complete list):
API exposed that let you access data directly. E.g. XML or JSON type response.
Compression - your client has to request via appropriate HTTP headers, e.g. Accept-Encoding: gzip, deflate, and needless to say know how to process response accordingly. SO thread on doing this in C#.
Requesting mobile version of site if site supports such a thing. How site exposes such version really depends on the site. Some prefix their URLs with m., some respond to User-Agent string, some use other strategies...
Use HTTP Range header. Also depends if site supports it. MSDN link for .NET API.
Have a play with tweaking some of the browser capabilities in your HTTP request header, see here. Although your response to this will vary from site to site but this is how a client tells the server what it is capable of displaying and dealing with.
There is no way to ask server to render different amount of data outside of what server supports via C# or any other language. I.e. there is no generic mechanism to tell server "don't render inline CSS/JS/Images" or "don't render ad content" or even "just give me article text".
Many sites have "mobile" versions that will have potentially smaller page sizes, but likely contain different or less information than desktop version. You should be able to request mobile version by picking different url or specifying "user agent" corresponding to a phone.
Some sites provide data as RSS feed or some other means to obtain data automatically - you may want to check with each side.
If you know particular portion of the page to download you may be able to use range header for GET request, but it may not be supported by dynamic pages.
Side notes:
- most sites will server CSS/JS as separate files.
- make sure to check license to see if there are any limitations on each site.
I am currently trying to write a Windows Phone 7.1 Application that allows you to access Coursera class information, including streaming lectures.
I want to be able to also allow users to download lecture videos a slides (PDFs). Unfortunately the files are protected. This isn't normally isn't an issue. I have my ClientHttpWebRequest set up to use a CookieContainer. This is all well and good.
The fun comes when trying to use a BackgroundTransferRequest to download the assets. The class doesn't allow you to supply a CookieContainer instance for cookies. This means that I have to set the values using BackgroundTransferRequest.Headers.
Coursera returns its session cookie as an HttpOnly cookie. Unfortunately, the ClientHttpWebRequest doesn't allow you to access HttpOnly cookies from the response and, by proxy, means I can't read the session cookie from the CookieContainer either.
Is there anything obvious that I'm missing out there that will allow me to access the value that I'm interested in or do I need to come up with my own Background File Transfer infrastructure?
No, you're not missing anything. This is a gap in the SDKs offering.
I can think of 2 possible alternatives though.
Have the app run under the lock screen and handle the downloads yourself. - This is how we had to do it before background file transfer was available.
Have your own proxy server that sits between the app and the other site which can handle the cookie side of things for you and make the files available direct to the app. Obviously there are probably important security considerations to take into account before adopting this approach. There may also be additional costs for running and maintaining the server.