How can I deliver an an encrypted file from my web server? - asp.net

I have a web application running under Windows/IIS that includes some reports via SSRS.
I would like to be able to render a report, somehow save it on the web or SSRS file system, create an encrypted version, and deliver that encrypted file to the user.
I've considered creating a zip file with a password, but not sure about how well that would work.
What would be the best way to do this?

There are a couple of issues in this - and I have to work on the assumption that the purpose of encryption is that you want to be able to distribute the report in a way that only authorized users can view it.
The simplest way of achieving this goal would be to have a login scheme, and serve the report over HTTPS. This means only those who have a log-in can download the report, and it can't be intercepted using network sniffing.
In the past, a client insisted that they wanted to avoid allowing users to download unencrypted files, because they might forward the (unencrypted) report to un-authorized users. To meet this requirement, we created a windows service which created encrypted ZIP files; we used a service because performance tests showed that creating the ZIP in the context of a web request created a serious scalability issue.
The major problem you have with this scheme is distributing decryption keys; making sure everyone has the right key for their report is a huge pain in the backside.
It also didn't prevent users from decrypting the ZIP file and emailing on the unencrypted report - but this was a clear breach of IT policies, which was a harder point to make with unencrypted reports.

Maybe 7-zip or TrueCrypt?
Both require the installation of additional software however. I'm really not sure how strong ZIP file password protection is, so I would be hesitant to go that route without some research.
TrueCrypt is pretty secure, from my understanding.

You'll need a reference in your project to http://<Server Name>/ReportServer/ReportExecution2005.asmx. See the example included in ReportExecutionService.Render Method for how to execute and render a report. You can then take the returned byte array from the render method and create a MemoryStream based on it.
You can perform simple compression using thing in the System.IO.Compression Namespace like this:
public void CompressData(Stream uncompressedSourceStream, Stream compressedDestinationStream)
{
using (DeflateStream compressionStream = new DeflateStream(compressedDestinationStream, CompressionMode.Compress))
{
uncompressedSourceStream.CopyTo(compressionStream);
}
}
public void DecompressData(Stream compressedSourceStream, Stream uncompressedDestinationStream)
{
using (DeflateStream decompressionStream = new DeflateStream(uncompressedDestinationStream, CompressionMode.Decompress))
{
compressedSourceStream.CopyTo(decompressionStream);
}
}
using (FileStream sourceStream = File.OpenRead(#"C:\MyDir\MyFile.txt))
using (FileStream destinationStream = File.OpenWrite(#"C:\MyDir\MyCompressedFile.txt.cp"))
{
CompressData(sourceStream, destinationStream)
}
See the AesCryptoServiceProvider Class for information on how to encrypt data. It shouldn't be hard to modify the example to encrypt a stream instead of a string.
It's also possible to issue certificates to users and perform encryption/decryption based on that but it's more complicated. For that you'll need to look at the System.Security.Cryptography.X509Certificates Namespace.

Related

How do I securely read the asp.net root configuration folder?

I have a Windows Server 2008 R2 machine running IIS7.5. This webserver hosts many websites under different domains and each website contains several asp.net applications.
Support and development access to this machine is quite restricted due to customer requirements. I want to use the Microsoft.Web.Administration library to query the configuration of each of these applications in an asmx web method:
[WebMethod(MessageName = "GetDatabases")]
public List<Connection> GetDatabases()
{
List<Connection> connections = new List<Connection>();
ServerManager sm = new ServerManager();
foreach (Site site in sm.Sites)
{
foreach (Application app in site.Applications)
{
System.Configuration.Configuration config = System.Web.Configuration.WebConfigurationManager.OpenWebConfiguration(app.Path);
foreach (ConnectionStringSettings cs in config.ConnectionStrings.ConnectionStrings)
{
try
{
SqlConnectionStringBuilder builder = new SqlConnectionStringBuilder(cs.ConnectionString);
connections.Add(new Connection { Site = site.Name, Path = app.Path, Name = cs.Name, InitialCatalog = builder.InitialCatalog, DataSource = builder.DataSource });
}
catch
{
connections.Add(new Connection { Site = site.Name, Path = app.Path, Name = cs.Name});
}
}
}
}
return connections;
}
This code runs fine in Visual Studio but once deployed to the server an error occurs:
Server was unable to process request. ---> Filename: redirection.config
Error: Cannot read configuration file due to insufficient permissions
I researched how to work around this issue and found this page:
http://www.iis.net/learn/manage/configuring-security/application-pool-identities
So I created a new application pool just for this webservice and configured the Application Pool identity to have read-only access to the folder containing redirection.config (C:\Windows\System32\inetsrv\config) using the ACL of the folder. (I did this for the folder rather than the file as it seems that more than one file in the folder is required.)
My question therefore is: as long as I restrict access to the webservice properly, are there any security implications with doing this? It seems ok to me but the implications of making the configuration of these customer sites public could be career limiting to say the least!
Thanks,
Owen
EDIT: Just wondering if I have worded this question properly? So far no-one has taken a stab at answering it so this edit is mainly to bump it ;)
I'm no security expert (so take my words with a pinch of salt), but I would say that there isn't a hard and fast answer on this. However, most probably lean more towards recommending against this.
If your requirement is to allow support to see the connections your different sites use, then I see no issue creating a service like this in general principle, so long as you are careful.
That said, there are a number of things you should think long and hard about before going ahead with it:
Could the same be achieved by simply creating a secured share on the Server, and granting your support/devs RO access to that location? That may be more secure than writing your own service.
If you are doing this via a webservice, you should add security to the service to prevent unauthorised access (I'd probably use windows authentication myself, but that depends on your requirements)
I would recommend that you ensure that this service is not visible outside your Local network: you don't want someone from the wider web to be able to get onto this
Use an SSL connection for your service, to prevent packet sniffers being able to snoop on your traffic and retrieve this sensitive information.
I would recommend stripping out sensitive information from the Connection string before displaying it. At a minimum, I would remove the password. Anyone who needs the password already knows it, or knows how to get it. Anyone who doesn't need it won't be able to get it via this tool. You may also want to strip out all but the last part of the IP, it's not really secure, but it helps obfuscate information that would make it easier to hack.
Above all, you almost certainly want to communicate this to management/the customer, clearly lay out the potential risks, and detail what (if anything) you will do to mitigate it. If they sign off on it after all that, then the responsibility is really with them.
Security of the web service should be your last concern, primary concern is should you even make such a sensitive/confidential data available through a web service?
And the answer is straight NO.
More than security threats there may be quite a few legal implications on doing such a thing. Even if your customer is the sole owner of all the Apps running on their server they themselves may not be free decide about implementing such a functionality, as it may potentially be a threat to sensitive data belonging to their clients. So if you yourself are planning to make such a decision then you can very well imagine the consequences.
Moreover access to the servers and sensitive data like connection strings is restricted for obvious reasons, and that restriction should not be breached under any circumstances.

Hows does one prevent passwords and other sensitive information from appearing in an ASP.NET dump?

How does one prevent passwords and other sensitive data submitted to and received from ASP.NET web pages in IIS/ASP.NET dump files?
Steps to reproduce
Using Visual Studio 2010, create a ASP.NET MVC 3 intranet application.
Configure it to use IIS 7.5.
Fire it up and register an account (say bob123 as the user and Pa$$w0Rd as the password. I'm assuming that the SQL Express database is created and the site is fully functional.
Using task manager, right click on the w3wp process and create a dump.
Open the dump in an editor capable of displaying its contents as hex, such as SlickEdit.
Search for "Pa$$0Rd" and "Pa%24%24w0Rd" in the hex dump. You should be able to find several copies of it stored as ASCII, Unicode, or encoded.
Note that it doesn't matter whether you use HTTPS because it only encrypts the communication. ASP.NET stores that data in the clear in memory or disk.
The problem
Common wisdom has it to encrypt sensitive data and not to store it in the clear. However an employee may receive a dump of an IIS/ASP.NET application and discover passwords and other confidential data of users because this information is neither encrypted, nor is memory used by ASP.NET cleared after usage.
This puts them at risk simply because they have access to it. Dump are sometimes shared with partners (such as Microsoft) to help them diagnose issues in their code. It is a necessary part of diagnosing some really complex problems in one's application.
Things I looked at
Use SecureString for passwords and other sensitive data. However, the ASP.NET Membership provider, along with other frameworks like WCF, often accepts passwords as System.String, which means that those copies will still be in the dump.
Looked to see if there is anything in the framework to clear out a copy of System.String when it is no longer being used. I couldn't find anything.
Investigated whether one can zero out the memory used for requests and responses once IIS is done with it, but I was unable to find anything.
I investigated wether one can encrypt files IIS receives (as HttpPostFile) so that they are not stored in the clear. We may receive documents that are extremely confidential and every step is made to encrypt and protect them on the server. However, someone can extract them in the clear from an IIS dump.
What I was hoping for is to tell IIS/ASP.NET that a specific request/response contains sensitive data and that IIS/ASP.NET will clear out the memory when it is done using it.
A dump file by definition dumps all the memory the application uses at the moment it is dumped, If you were to create a filter so that certain things were excluded then you could never be sure that you had enough data to zero in on a problem.
Would you be comfortable handing over your databases / configuration settings to a third party? if not then you probably shouldn't be handing over dumpfiles either. (imho)
I know this doesn't answer the question directly but why not look at this problem differently.
You could easily put together some javascript to do the hashing client side. I would combine the password with something random such as a guid that is sent down by the server and is valid only for a single use. The data exchange would no longer contain the password and the hash could easily be compared server side. It would only be valid for the session so someone looking at the dump data couldn't use the hash to "authenticate" themselves in future.
On the file side, how are these files being uploaded? directly from a web page? There are quite a few javascript libraries that do encryption (blowfish) and I would definitely use this option when sending a sensitive file. It does have a speed penalty but you can be sure that the data is secure.

Is it worth encrypting files being stored on a server for distribution?

I'm creating a site for distributing software to clients. We're implementing lots of security bells and whistles on it to reasure the clients that software they're running wont have been tampered with.
I'm toying with the idea of encrypting the files we upload to the server, but I'm not sure if there's much point conisdering the overhead it entails. The files are decrypted anyway when being transmitted to the client. As well as this, if a hacker gets into the server and replaces the encrypted files, they can also change any hashes we made of the files to check they havnt been manipulated.
So... is it worth encrypting the uploaded files?
You should sign rather then encrypt your files.
When using PKI, it is the act of encrypt (or encrypt a hash of) your file with your private key, instead of doing so with the receiver's public key.
Then everybody that download the file can verify that the file was not tampered with.
File encryption is useful when either you share a secret with your
receivers, or that you have their public key available. Typically it
is not useful in case of file distribution as you describe it.
I will answer with a question: what is the point in encypting files on the server when you don't have any control over what the clients will do with the decrypted versions anyway?
Oh security.
How can the client be sure they're talking to the correct server.
How can the server be sure they're talking to a legal client.
How can the user be sure they're not using a compromised client etc.
Is the server in your custody or is it a shared server. How volatile is the data and is datatheft an acceptable risk or not.
Please expand your current situation. Do you use encrypted communcation. Is the communcation over internal or external lines. Do you thrust the server support team.

How to encrypt information in aspx page?

I know it's a silly question but ,
My client asked for encrypting some information form their payment system to prevent user stealing personal information.
The system is web-base and written by ASP.NET
We have tried some annoying solution such as JavaScript no right-click or css-no-print
but apparently my client didn't like it.
so are there any commercial solution to encrypt information in aspx produced html pages?
or someone can tell me how to pursuit my client to stop these "prevent stealing" idea in a web-base system?
If your client is worried about data being stolen "over-the-wire", do what Jaxidian mentioned and using SSL.
If your client is worried about users stealing data from pages they view, then tell them there's nothing they can do in a web app to stop that. Users need to download a page to view on their computers so no matter what you do, HTML web pages can always have their content downloaded by a user, even if you add some hoops to make it more difficult.
The only way to stop a user from stealing data from pages they view is to not make your app web-based. You'll have to write a native app that gets installed on users' machines with strict DRM in order to stop them from copying content. And even then, DRM can be cracked. Just look at Sony.
If your client was referring to encrypting data within your database, then you should look into AES Encryption in .NET.
SSL Certificates
Verisign
Thawte
There are many others, some trusted and others not trusted - do your homework.
<Edit> Here is a very thorough step-by-step tutorial explaining how you would go about using an SSL Cert in IIS.</Edit>
I come with some really silly answer for my client
I tried to encoding the information in aspx with Base64 like
string encoded = Convert.ToBase64String(Encoding.UTF8.GetBytes("Something"))
and decode the data with JQuery .Base 64 plugin ,
the aspx is like:
<span class="decoding"><%=encoded%></span>
with JQuery script to take all .decoding element to be decoded
$(function() {
$.base64.is_unicode = true;
$(".decoding").each(
function() {
$(this).html($.base64.decode($(this).html()));
}
);
});
so the source data will look like some meaningless string , which is my client want.
and with some evil JavaScript to prevent printing and cleaning user's clipboard.
I have completed a web-site with zero usability
and still can't prevent anything! Well done :)

Get unique System ID with Flex

Is there a way to get a unique machine-specific system ID in a Flex application running in a browser, so that is can be used for example to determine if the machine is properly licensed to run the application?
I can't think of any way to do this based off the users machine or OS. The whole point of browser applications is to have them able to run anywhere, any time via a browser. To my knowledge Flash provides no information that could reasonable be converted into a unique machine ID for licensing purposes, not even the MAC address of a network card on the machine.
Personally, I think you'd be better off requiring a username/password for users to log in, and then using a session key stored in a cookie to allow the user to skip that step (e.g. a 'remember me on this computer' type of feature, such as GMail has). This has the advantage of the user being able to run the application from any PC they like.
Create a UUID inside flex
import mx.utils.UIDUtil;
var myUUID:string = UIDUtil.createUID();
I suppose if you want to get really clever you could encrypt this string with a locally known salt and generate some encrypted license key that can't be shared. You could change the salts or keys at regular intervals to enforce license expiration.
You will need to manage the key data on a backend somehow.
ILog Elixir does this, but they do it through a traditional install process. The swc files are watermarked, but when you enter your valid serial number unmarked swc files are unlocked and the source code is made available.
I don't have any details as to how they actually go about this, but it isn't directly through flex. Perhaps researching traditional software installation processes and unlocking encrypted data that way would produce the answer you are looking for.
You cannot really access machine specific information like MAC address or other ID's from a flex app. You should probably use some other technique like using ASP.NET or JSP.

Resources