Best practise for secure Image downloading via WebService - wcf

I'm currently building a ASP.NET MVC 3-WebApp that handles lots of images, lets say up to 100 per page.
At the moment the WebApp itselfs serves the images. The reason is, I want to make sure that only authorized and logged on users can download the images. This approach suffers from performance, because on the one hand the Browsers loads the images sequentially, and on the other hand this scales not very well.
Therefore I would like to introduce a external WCF-WebService from another host, that serves the images and only the images. This works very well, but at the moment I have no idea how to make the Download-Url secure.
In my page from lets say "www.imageviewer.com" I would like to have many image tags like so:
[Image-Tag] Source="imageservice.imageviewer.com/Download/someID" [/Image-Tag]
I know I could send some encrypted security information within the Download Url, like UserID or other SecurityTokens and make some processing with that. But this would not prevent, that the User (or another User) can download the image in another Browser, without being logged on.
I would like to have a session-based solution. Only with a valid session after logging on to the WebApp the Browser should download the image from the WebService.
Any ideas how to solves this?

Are webservices the new regex?
Some people, when confronted with a problem, think "I know, I'll use a webservice". Now they have two problems.
Please describe in what way you think a webservice will make your images load faster? There will be more overhead (XML (un)packing, adding another layer of code), and since a webservice is not more or less an HTTP request than the thing your browser does when requesting an image you will still run into the browser's limit of connections.
A browser does not really sequentially load images, but rather does it at a rate of about two to eight at a time to the same domain.
Loading the images from different subdomains is a more common approach, and adding some lazy loading will speed it up even more. You can then still secure it, using information stored in your session, cookies or headers.
If you, on the other hand, just want an answer to your question and no friendly advice: you could simply secure your service with a Custom User Name and Password Validator, where you simply override the validator to validate against your known user credentials.

Related

Workarounds for Safari ITP 2.3

I am very confused as to how Safari 2.3 works in certain respects, and why sites can’t easily circumvent it. I don’t understand under what circumstances limits are applied, what the exact limits are, to what they are applied, and for how long.
To clarify my question I broke it down into several cases. I will be referring to Apple’s official blog post about ITP 2.3 [1] which you can quote from, but feel free to link to any other authoritative or factually correct sources in your answer.
For third-party sites loaded in iframes:
Why can’t they just use localStorage to store the values of cookies, and send this data along not as actual browser cookies🍪, but as data in the body of the request? Similarly, they can parse the response to updaye localStorage. What limits does ITP actually place on localStorage in third party iframes?
If the localStorage is frequently purged (see question 1), why can’t they simply use postMessage to tell a script on the enclosing website to store some information (perhaps encrypted) and then spit it back whenever it loads an iframe?
For sites that use link decoration
I still don’t understand what the limits on localStorage are in third party sites in iframes, which did NOT get classified as link decorator sites. But let’s say they are link decorator sites. According to [1] Apple only start limiting stuff further if there is a querystring or fragment. But can’t a website rather trivially store this information in the URL path before the querystring, ie /in/here without ?in=here … certainly large companies like Google can trivially choose to do that?
In the case a site has been labeled as a tracking site, does that mean all its non-cookie data is limited to 7 days? What about cookies set by the server, aren’t they exempted? So then simply make a request to your server to set the cookie instead of using Javascript. After all, the operator of the site is very likely to also have access to its HTTP server and app code.
For all sites
Why can’t a service like Google Analytics or Facebook’s widgets simply convince a site to additional add a CNAME to their DNS and get Google’s and Facebook’s servers under a subdomain like gmail.mysite.com or analytics.mysite.com ? And then boom, they can read and set cookies again, in some cases even on the top-level domain for website owners who don’t know better. Doesn’t this completely defeat the goals of Apple’s ITP, since Google and Facebook have now become a “second party” in some sense?
Here on StackOverflow, when we log out on iOS Safari the StackOverflow network is able to log out of multiple sites at once … how is that even accomplished if no one can track users across websites? I have heard it said that “second party cookies” still can be stored but what exactly makes a second party cookie different from a third party?
My question is broken down into 6 cases but the overall theme is, in each case: how does Apple’s latest ITP work in that case, and how does it actually block all cases of potentially malicious tracking (to the point where a well-funded company can’t just do the workarounds above) while at the same time allowing legitimate use cases?
[1] https://webkit.org/blog/9521/intelligent-tracking-prevention-2-3/

Fetching content binary from database or fetching content by its link from storage service

For an app (web + phone) there are two options:
Image binaries in database. Server replies to app HTTP request with images as base64
Images in storage service like Amazon S3 or Azure Blob Storage or a self-hosted one. Image links in database. Server handles app HTTP requests by sending back only the links to images. The app fetches the images from storage by their link
Which option above is the standard practice? Which one has less trouble down the road?
To some extent, the answer to this question is always opinion based, and partly depends on the specific use case.
I would think that the second approach is used more often. One reason is that normally, storage within a database is slightly more expensive than file storage in many cases. Also, what is the real use case? Assuming you use HTML pages that reference images via the img element or via CSS as background image, then the base64 return value would not be that useful, and OTOH the more complicated graphic at the bottom of your picture would get a bit more simple from the client view: The resolution of the link would be resolved by the server when generating the HTML and determine the src of the img, and then the browser would simply apply standard HTML logic and request the image data from the storage service via HTTP.
However, if you would want to optimize load times (and your images would be more or less unique per page so that browser caching of images across pages would not help much), then you could use data URLs embedded into the HTML, and then the first approach could potentially be useful. In this case, all the logic including the generation of the data URL within the HTML would be handled on the server, and the browser would have a single http request.

Is there a way to protect data from being scraped in a PWA?

Let’s say I have a client who has spent a lot of time and money creating a custom database. So there is a need for extra data security. They have concerns that the information from the database could get scraped if they allow access to it from a normal web app. A secure login won’t be enough; someone could log in and then scrape the data. Just like any other web app, a PWA won't protect against this.
My overall opinion is that sensitive data would be better protected on a hybrid app that has to be installed. I am leaning toward React-Native or Ionic for this project.
Am I wrong? Is there a way to protect the data from being scraped in a PWA?
There is no way to protected data visible to browser client regardless of technology - simple HTML or PWA/hybrid app.
Though you can make it more difficult.
Enforce limits on how many information a client can fetch per minute/hour/day. The one who exceed limits can be blocked/sued/whatever.
You can return some data as images rather than text. Would make extraction process a bit more difficult but would complicate your app and will use more bandwidth.
If we are talking about a native/hybrid app it can add few more layers to make it more secure:
Use HTTPS connection and enforce check for valid certificate.
Even better if you can check for a specific certificate so it's not replaced by a man-in-the-middle.
I guess iOS app would be more secure then Android as Android is easier to decompile and run modified version with removed restrictions.
Again, rate limiting seems to be the most cost effective solution.
On top of rate limiting, you can add some sort of pattern limiting. For example, if a client requests data with regular intervals close to limits, it is logical to think that requests are from a robot and data is being scrapped.
HTTPS encrypts the data being retrieved from your API, so it could not be 'sniffed' by a man in the middle.
The data stored in the Cache and IndexedDB is somewhat encrypted, which makes it tough to access.
What you should do is protect access to the data behind authentication.
The only way someone could get to the stored data is by opening the developer tools and viewing the data in InsdexedDB. Right now you can only see a response has been cached in the Cache database.
Like Alexander says, a hybrid or native application will not protect the data any better than a web app.

Nginx basic auth and number of authenticated locations

Im using basic auth in nginx, no issue there, but i would like to limit the number of distinct locations a user is authenticated,
The end goal is to prevent user sharing access data to website, since the website does real time "monitoring" of some data, i wan't that if the same user/pass combination is used from another ip, that or either both users stop getting data,
or one of them stops getting data.
I don't think that is a good idea, because a user may log in via pc and mobile phone at the same time and has two different ip addresses that way. Also http-auth isn't designed to do what you want it to. It would have to remember the ip-address and make it expire somehow, when the user leaves without logging out. Altogether would it be difficult to guess for how long the session is valid. Another problem is, that most users don't have static IPs and get disconnected by their providers every 24 hours. What happens if that occurs after a valid login?
The most popular method to deal with this kind of problems are session-cookies. These can be described as a one time password and you can use that for as long as you want or until it expires. SessionIDs are usually saved in some kind of database and making those sessions unique would not be a big deal and may therefor be what you want. Luckily the
ngx_http_auth_request_module would allow you to only implement this missing part and would bring you as close as you can get without developing your own nginx-module (see https://www.nginx.com/resources/wiki/modules/ for available modules).
On the other hand: Don't do that. Seriously. If you care for security, do not try to reinvent the wheel and use something, that has already proven. E.g. ngx_http_auth_jwt_module allows you the use of OpenID, which also sets you free from saving sensible user data on your server (because nobody wants to save passwords unless it is absolutely necessary).
Both of these methods require nginx-modules, which may not be installed on your server. If you don't have the permissions to build them, I would suggest to add that to your question, so that others can suggest solutions for non root servers.
If you want to keep it simpler you should also consider to generate download links each and every time and save ip-address and download link address in a database. Delete entries when a user downloads that file and you are done. For that to work you can use the
Content-Disposition: attachment; filename=FILENAME-HTTP-Header, so that your download.php doesn't save a file that called alike.
May be you can also find some kind of javascript to replace ngx_http_auth_jwt_module and use OpenID with http-auth. That can work, because it is possible to do the authentication with ajax as well.
Last but not least: If you still want to do http-auth, also use HTTPS, because your passwords won't be encrypted by this auth-method by default.
What you want to do is unusual so you will need to write a lot of the logic to handle the process.
Your code will need to store a User ID and IP Address pair for each loged in user and validate each attempted log in against this. As the previous answer pointed out, you will need to expire logins etc. Basically, you need to roll a session handler.
This is not impossible or particularly difficult but you need to write it yourself in one of the scripting languages available to Nginx which are either Perl, which is not recommended due to limited ecosystem in Nginx, or Lua, which is highly recommended due to the massive Nginx lua ecosystem (used by Cloudflare for instance).
You will need to compile in the 3rd party Nginx Lua Module and associated modules or just uninstall Nginx and use the Openresty Bundle which already has everything you will need included instead ... including Redis for storage if you need to scale up.
Here are some tools you can use as your building blocks
Openresty Session Library
Openresty Redis Session Library
Openresty Encrypted Session Module
Note that you can implement Openresty stuff directly in Nginx if you wish without having to run Openresty as it is just a convenient bundle of Nginx and useful module.

Login through a fancy secure web form without a UI

I am load testing a product that requires a very secure 2 factor login.
In my load testing tool you only deal with scriptet web traffic, and have no UI, JS or CSS available.
The 3 web forms I need to get through takes the user input, encrypts it - and bakes into something that looks like Base64 - it is then sent by post method. I need to be able to send this data directly from my tool. I have tons of test data, but the login mechanism is a centralized, closed service so I have no insight here.
Is this even possible to get through ? I know in theory I can automate and script anything that flows through the Internet, but I can not see a way here.
I thought about writing a small application that launches before the test, that uses the UI to punch the data, but I'm not even sure this is possible with VS2013 load tests, and considering the incredible amount of logins I need to do this will be a challange.
Any thoughts ?