Can a secret token be included with an app securely? - c#

I want to create an UWP app for a web API, which provides API keys for app developers.
Basically I would need to include some constant values with my app to generate some HMAC authentication tokens and pass them in the request header.
However, I'm not familiar with how UWP apps are delivered and deployed. Probably not very securely. I'm afraid if I did this, someone would simply decompile the app and steal the keys, like how regular .NET apps can be decompiled.
So what I would like to know is if I can deploy the app with secrets, and if not, how is this kind of problem solved usually with apps?
Also, if it is possible to deploy an app with secrets securely, how can I update those secrets if I would ever need to?

What you are looking for is the Microsoft Data Protection API (see https://msdn.microsoft.com/en-us/library/ms995355.aspx).
Basically the operating system provides you a service/api which securely allows you to store data. It uses the user authentication to encrypt and decrypt data. You may delete / write a key whenever you like.
I would suggest you calculate a key using ECDH (Elliptic Curive Diffie-Hellman) between your client and server (api) and then store the mutual agreement in the keystore. You decrypt your key on runtime, you might want to store the variable then in a SecureString. However keep in mind your api needs to keep track of the generated mutual agreements (also securely).
Here Microsoft explains on how to implement DPAPI:
https://learn.microsoft.com/en-us/dotnet/standard/security/how-to-use-data-protection

Related

Store secret key securely in .NET Standard cross-platform app

I'm working on a C# PowerShell module, which is going to be a simple wrapper around some service REST API. I'd like to target PowerShell Standard / .NET Standard and make module available across all supported platforms.
For this app authentication requires API token, issued on a service website by the user. Entering key every time you open a session would be extremely inconvenient and therefore I need some way to securely store the API key in a user profile.
The problem is - I cannot find an easy way to encrypt data that has transparent cross-platform support. Initially, I wanted to use SecureString, but it is (a) deprecated and (b) doesn't seem to have good support on Linux. In a perfect world I'd like to have some mechanism similar to Windows encryption - user certificate encrypts API key and I put result in a text file in a user folder.
This is not a financial or mission-critical application, top-notch security is not required, but still keening plain text secrets in my home folder makes me nervous. Yes, I'm talking to you, AWS SDK authors :)
My first thought was: "just save secret key to ENV variables..."
But if I understood OP's question correctly, it is required to restrict unauthorized reading of this secret even on OP's machine.
One option I could see is just create a folder (or maybe file) and give it the access permissions only for one particular user. Ultimately one can create new user account which will be used to run the code in powershell and give this new user exclusive permissions to read secret file. This will prevent some 3rd party programs running from OP's account to read secret file.

Obtaining sensitive data from the user and storing it without hashing so that it can be restored

I'd like to ask for some advice on the app security when it comes to getting the password from the user and storing it.
I'm developing a tool using .NET Core (console project) and Selenium WebDriver to automate a process on a website, which requires authentication, and my concerns are following:
1. Getting the password from the user (using console) and securely handle it
2. Storing the password in a secure manner
Regarding the first point:
I've found an answer on
SO pointing out that
using
SecureString
doesn't fully prevent sensitive data to be read as at some point it
has to be converted to/from normal string. I have come across the
solution
for getting user input from console using SecureStrings, but
according to what's written
here
SecureStringToBSTR has to be used to handle the sensitive data in a
secure way. However, SecureStringToBSTR is not included in .NET
Core, because it's
available only for Windows thus I'm stuck.
As for the second point:
I cannot hash the password as it has to be restored. At first I
wanted to use platform specific solutions and check the current
platform in the app, but after a research I found out that there's API only for DPAPI for Windows, there's no API for KeyChain in MacOS (there's some workaround) and Linux doesn't have a unified way of storing sensitive data at all. The only solution I can think of is to force the user to generate public/private keys (using for example RSA which is available on all platforms, encrypt the password using public key and require private key to retrieve the password. Then I would store the encrypted password either in appsettings.json or as an Environmental variable as desribed here. Unfortunately Azure Key Vault is not free
I am aware that there are many questions similar to this, but:
I couldn't find any regarding storing passwords, most sources focus on hashing them, however, it doesn't apply to described use case
Virtually all are focused on ASP.NET Core MVC
Thanks in advance for the hints.

How do I prevent an app from using my api key?

My organization has a Win32 application that is written in the "fat client" style. I am writing a C# Client / Server solution that will replace this Win32 application. I am using ASP.NET MVC for the server and the client is a WPF application. I did my own custom implementation of the OAuth 2 spec. I am planning on creating a Restful API, and I want for not only my client to use it, but also allow 3rd parties to use it as well.
Every app will have an api key issued to it including the official client, but the official client's api key should be allowed additional api scopes (permissions) that 3rd party users aren't allowed to use. It is pretty obvious how to solve this but if you consider not everyone plays nicely, you have to ask "What would stop someone from just pretending like they are the official client and using it's api key?" Communication will be encrypted, but the server is not in the cloud or anything like that where we could control it. Our customers install the servers on their own machines and they will more than likely have access to the server application's SSL cert. Once you have that you can easily write an app that would run on our customer's machine that could glean the API key and secret from the official client app and use that info to request tokens from the server as if you were the official client.
I am planning on self signing the default key that the server uses and I could try and hide it in the application, but that really is just obfuscation. Besides, I wanted to allow users to provide their own SSL certs so browser based 3rd party applications wouldn't have issues with the browsers complaining that they are trying to communicate with on a self-signed SSL channel.
Is there anything I can do? Here are my choices as I see it:
1) I can set it up so that only SSL certs provided by us can be used and we hide them on disk encrypted using a secret that is obfuscated in the application code. We then just hope no one bothers to take the time to dig through our .net assemblies to find the secret used to encrypt/decrypt the certs on disk.
2) We allow them to provide certs so that we don't need to be involved with that process at all when they want to use a signed cert (we don't want to be in the cert business). Now we can't even hide behind obfuscation so if someone wants it, then the official client's API key and secret is easily obtainable.
Neither seems very desirable to me. Option 1 makes us have to request addition funds from them and manage SSL certs when self-signed doesn't work for them and in the end if someone really wants them they can still take the time to get them. Option 2 just makes it super easy to steal the official client's secret.
Reasons to want to limit unofficial Apps:
1. Discourage clones
A. Tell people not do it. Have a lawyer send cease and desist letters to authors of popular apps (and to anyone helping distribute them). Intermittently download them and alter the client/server code so that the popular apps will break. For added discouragement, temporarily ban any users who used the popular app. Authors will mostly give up on cloning your app; temporarily banning users will kill their install base. This is not great for your reputation.
2. Prevent unauthorized behavior.
A. Any behavior allowed by the official app should be allowed by the custom app. Whatever scenario you are worried about, block it server-side so that neither app can do it.
You can try to hide credentials (code obfuscation, hidden credentials, etc.), but this is only raises the cost/difficulty. This is often enough to discourage code theft (no need to make code theft impossible; it is sufficient to make it more difficult than copying it by hand). However, users who want to use your api in unsupported ways can work around this.
The answer is simple. each instance of you app should have its own unique key effectively a user sign up. You then ban users who infringe your rules. in this case signing in with a non authorised client. should be pretty easy to detect by pushing updates more frequently than it would be cost effective to reverse engineer them. Much like punk buster or other anti cheating tech

Is there any secure storage in Android through Monodroid out of the box?

Like many people - I am developing an app with a shared codebase (Windows Store + Android + MonoTouch + [later] WP8).
Also, as with many apps, I have local state that I need to persist for this app.
One piece of information I store is an authentication token for the signed-in user. On the Windows Store platform I have implemented the storage of this with a mixture of roaming settings (ApplicationData.Current.RoamingSettings) for the token's ancillary data (user name and issued date) and the PasswordVault for the actual token value. Thus the token is protected from OS-level introspection, because it is encrypted by the OS.
Now I'm implementing the same interface for my MonoDroid build, and I can't see any way, provided by the platform, to store data that can only be decrypted by my application - in the same way as the password vault can be used for Store apps.
As a result, at the moment, I'm simply using the Android.Content.ISharedPreferences interface via the Application.Context.GetSharedPreferences method to read and write these values.
So am I correct in my assumption that the platform (MonoDroid or Android) offers no secure storage OOB? Is the only alternative to implement encryption within the app - which will of course require baking the encryption key into the code? Or can I grab the certificate used to sign the app and use that as a key?
Ultimately it's not the end of the world if I can't encrypt this data, since the token is time-limited anyway - but it would be nice if I could actually do it properly!
You could use it with a combination of Keychain API (available in API level 14 onwards) and encrypting the data with Cipher API using the certificate from the Keychain api.
Take note:
According to Android Security Overview document, there is no guarantees if the device is rooted:
http://source.android.com/tech/security/index.html#rooting-of-devices
Maybe this quoting from here can help you:
On the android side OOB is not supported in the public API so things
get tricky. I believe this is because Honeycomb 3.2 does not have a
bluez stack that officially supports OOB bonding, but Google has some
kind of implementation coded in. I believe this because if you look at
gingerbread source code for the Bluetooth Adapter and Bluetooth Device
classes you can see OOB methods available but not exposed through the
documented API.
These methods are still public so you can call them through
reflection. Using reflection you can also get all of the method
signatures in a class. This is how I figured out what methods I had
available to me.
Beware though that many are not documented and it's not obvious what
some do. The important ones to make note of are the
readOutOfBandData() in the adapter class and setDeviceOutOfandData()
in the device class.

Securely storing (encrypting) data in an ASP.Net application

I have an asp.net application, accessed by people over the internet using web browsers. It runs on a web server and it talks to a backend database.
Some of the users would like to use the application to store some private data. The requirements of this are:
1) Only the user who stored the data should be able to see it.
2) The developers/dbas should not be able to see the data.
3) If the web server and database server were compromised a hacker must not be able to decrypt the data.
So, it's obvious I'm going to have to encrypt this data. If I encrypt it there will be a key somewhere and probably a salt/IV. The question is where do I store the data which is used to perform the decryption? If I store it in the database or the web server then a developer, dba or hacker can access it and decrypt the data.
I think my ideal solution to this would be for the private key to be on the clients machine, that way they are entirely responsible for it. But I'm not sure of how to go about this with an asp.net web application.
I believe I can create a certificate which also stores a private key (PFX). The client companies could use group policy to deploy the certificate to their domain. But it is possible that the ASP.Net application can request the web browser to send the private key to it so that it can perform the decryption? Decrypting on the client would be best but other than creating something in javascript I don't see how this is possible.
Any advice welcome.
Store the key in the mind of the user. Use any password/passphrase based key derivation algorithm you like. The standard is PBKDF2. The optimum choice of algorithm will depend on precisely what your security requirements and threat mode is. Ideally, that decision and the implementation should at least be reviewed by a security expert.
Is it possible that you deploy a ClickOnce application as a part of your solution? The ClickOnce could easily access the cert store on a local machine thus allowing you to perform client-side encryption.

Categories