I need to create FTP users via a C# software, which is run Client-Side, I have no idea where to start or how to do that, I am not even sure if this is possible as this may require to be logged as root?
My other option would be to call a PHP script via the C# software, which could call a system() script?
This function needs to work on Linux shared hosting (as this is shared I can't do everything I can).
The only way YOU have to manage the FTP server is through DirectAdmin. So unless there is an API for DirectAdmin and you have access to it, or your shared hosting provider offers some kind of API, you won't be able to do this.
If you can manage your users on the shared host with system(), then by all means go that route.
If you can't, then you might need to create a script that runs on the server, that accepts incoming requests and then works directly with DirectAdmin to manage the users. This would require the script know the DirectAdmin credentials, and if any updates happen to DirectAdmin it could potentially break your script. I would be very careful with this method, as anyone with access to this script could then manage ftp users. If your client can manage these FTP users, anyone can. How will users be "authenticated" with the client if there is any authentication. If so, how are they authenticated? Because your "api" script will need to work with that authentication as well.
My question is, do you really NEED to create an FTP user? If they just need to upload a file, couldn't they simply upload a file via an online form? Or through the client? Are you required to use FTP?
EDIT:
So as I said in the comments, one idea would be to have a server side script (maybe PHP) that would handle managing the files. It would accept requests to upload/delete/blah the files. When a file is uploaded to the site it would be stored, and it would return a special token along with the location of the file.
The client would then take the token, store it locally, and when the user manages the file on the client it would use that token for future modifications. I'd generate this token randomly (not based off any data of the user). How you store the token is up to you, could be on the file system with the files or in a database.
The communication between the client and the site should be done through SSL if possible, to stop MITM attacks.
As for uploading files, it's really up to how your client authenticates it's users. If it's via a central database, the shared hosting server could access that, if you don't want to do that, then you'd need to something similar to a public key system. So that the client can send a key that the shared hosting script can tell if the user is valid or not. But then you have to have the script know when the key has been revoked, etc.
So it's up to you how you want to proceed with this part.
If this were me--and this is adding one more moving part, I realize--I'd decouple the creation of users, and place that in a long-running process on the remote server, where both the server process and the PHP facade work with something like Gearman to coordinate jobs. You're not going to be able to create the processes on the remote Linux server from C# without some external facility like rsh. Something just skeeves me out about the idea of creating users via a PHP site, unless it's only accessible over a private intranet with no external access. Having a separate process would give you just one extra step in which to validate.
Related
I'm trying to create a desktop application that will send updates to a web-service I am developing.
Ideally, the application would be configured only once and deployed to a network share. When configuring the application, the user will enter a password that is used to authenticate within the web-service. After that, a token will be created to be used on future connections.
This would allow any computer with access to the network share (even if it is not the computer in which the app was configured) to just run the application (which will connect to the web-service) without entering any credentials (because the token has been saved).
Question is: How should I protect this token?
I know that storing it client-side will never be completely secure, but I want to make it as hard as possible for someone to gain access to the plaintext token.
I'm looking for an answer that, preferably, does not depend on any operational-system resource (since the application can be executed from different devices).
Assume I have full control over the application and the web-server
I'm developing the console application using C#, but I believe this to be more of a theoretical question (not tied to any specific language)
Here are a few things I've tried/thought about:
Serializing the token using something like C#'s SecureString and storing it on a file: it's the best I've come with. But obviously, very trivial to reverse if someone gains access to the key file.
This answer suggests to use the Windows Data Protection API (DPAPI) (in C#, the ProtectedData class), but apparently, this would allow only the user who initially saved the credentials to access them, which would not work because I have to access the protected data from multiple users/devices.
Pass the token as a parameter to the application: this just changes where I'm going to store the token (on a batch file or OS task that calls the program, for example), but I don't think it makes it any more secure.
Since the user is not an administrator of the machine (this is a fundamental hypothesis), there are many ways to hide things from her.
What I propose is:
Make sure the main app runs under different credentials than the
logged user, a "special user".
Write another end-user app, just for setup, that talks to this app (using any interprocess communication you see fit, TCPIP, whatever, maybe secure but I wouldn't care too much at this). This app is used only to gather credentials and send them to the first app
Now, the main app can write the token anywhere the logged user has no access, but I recommand protected data because it's very easy to use
Here is some graphical explanation:
Since data encrypted using protected data (Windows Data Protection) can only be decrypted by the Windows user who has encrypted it, the logged on user will not be able to read the "special user" data.
I would suggest using JWT.
Your server would generate a Token after a successful authentication. The token would be sent to the client. Each subsequent call to the server would send the token in the header to the server. The server would then verify the token. If verified, the server knows the client has been authenticated.
No need to store usernames/passwords on the client.
There is no bullet-proof way to solve this problem, the client finally needs access to the server, and so can do an attacker with enough privileges on the client.
What you describe is a typical scenario for the OAuth2 protocol, since you have control over the server. With OAuth2 you cannot avoid the need to store a secret on the client, but by exchanging it for a token, you can protect the original password and you can guarantee that the token is very strong (user passwords tends to be weak).
To store the token/password on the client one could encrypt it before storage, but this immediately raises the question of where to store the key for this encryption. An attacker could extract it from the client. There are some ways, which can improve security for the key storage.
Depending on your situation you may consider the usage of a Hardware security module (HSM).
You can use an OS specific key-store like you mentioned with the data-protection-api. A key-store can only help protecting a key, because it has the support of the operating system (I think this is what you meant with SO-independend?). With the DPAPI you can not only restrict access to the logged in user, rather you can restrict it to the local machine. Key-stores are available on other operating systems as well.
Instead of storing the password on the client, it can be requested from the user each time the client starts. This can be reduced to the startup of the device, the password can then be hold exclusively in the memory.
Well, you can't protect anything in client side. Once it's there, anyone with privileged access can see it.
What you can do is make this piece of information useless without something else.
The best approach here would be to store a kind of public key in the client side and use this public key to create a hash to authenticate the user via webservice.
When the user configure the application, the server send this public key that the application stores locally. When the application call the server it will create a hash using this public key and a private key that is only known by the application and the server. Then the server can check if the hash is correct using its private key.
To improve security, you can use a timestamp in the hashing too, so it will change overtime and prevent the reuse of keys. Or it could send a new public key with the each webservice answer.
I would suggest you to use IdentityServer4 as it provides RFC compliant protocols and depending on the GrantType a client application is given in your context your desktop application.
Even though the token is in plaintext it is protected in the webservice where the Access Control(Issuer of token) validates that a token is being received from the correct client by checking the Origin in the clients request and the one stored in the database.
A theoretically question:
I have a C# Windows Form app, that sends back some user submitted data to an external mySQL server on the internet.
How do I prevent people from seeing the username and password for the mySQL server? (Eg. by decompiling the C# exe program).
Best regards
Short answer: you can't - anything that runs on a machine you don't control can be decompiled etc.
Possible option:
You might try an approach with a SSL-secured webservice on server-side which authenticated clients via client-cert (part of SSL standard). That webservice would be accessing the DB on behalf of the clients. you can then secure the connection between webservice and DB network-wise...
Typically you either prompt the user for a credential, or you if the account is public (eg. credentials are insecure, as in your case) you limit what the account is allowed to do.
I would pass the user submitted data to another service which does the actual talking to the database server. That way your connection details can be kept apart from the client.
If you cannot do that then you should create a restricted account for your mySQL database which is used by your client code.
Live with the fact, that everything the client software knows is known to the user.
Set up the smallest possible interface for he client software to use. Instead of exposing a full DB account, use one restricted to some stored procedures only. Or don't access DB directly, but via a (web) service. Then, make sure the service only exposes safe-to-execute methods.
I was thinking about how to secure the Data Layer in a C# Application, the layer could in this case be either a LINQ to SQL Model Diagram stored with the Application itself containg the connection string to the SQL Server Database.
Or it could be connectivity between the application and webservices.
Either you need to impement some sort of security, for instance, the Connection String in a Application can easily be reverse engineered and Webservices can easily be tracked and used for other reasons than the applications original purpose.
So my question is in a shorter way: How do you solve the security issues when handling Webservices and/or direct connection to a SQL Server From a Windows Forms Application?
In your case there are two main attack possibilities:
Steal the connection string and then access the database directly
Call methods in your C# code directly without using the UI
For the connection string you need to store it in an encrypted form in a config file. Problem is that there need to be enough information in the winforms app so that it can decrypt and use it.
For accessing the code directly you can use code access security and obfuscation.
In your case I would not give the windows app direct access to the database. Let the windows app call a WCF service, the the WCF service would access the database.
The user's user account is allowed to call the WCF service, the WCF service is running under an account that is allowed to access the database, the user's user account has no rights to the database.
Windows App with 3 Layers:
UI
Business (Security check what UI should be shown to the user)
Proxy
WCF Service with 2 Layers:
Facade / Business Layer (Security check is user allowed to call this method with this data)
Entity Framework datamodel
Common dll's to both Layers
Contracts / WCF Interfaces
Data Transfer Objects
For info on proxy, contracts and DTO's see this video:
http://www.dnrtv.com/default.aspx?showNum=103
Shiraz Bhaiji came close, but I think they missed the key step.
Yes, you want access to the database to be mediated by a middle tier, exposed through WCF, which imposes whatever business logic you require, including full access control. This service does have the connection string that you want to keep secret, but it's not accessible to the WinForm clients.
The key step is that the client uses the user's authentication to gain appropriate levels of access, and never has any ability to contact the database or even get full control of the middle tier. The middle tier grants access to methods based on the groups that the client user is a member of. This means that a user with low security can call any method they like, but they'll get access denied exceptions, or data filtering, or whatever other failure mode is appropriate. The user account, on its own, has no access to the database, so the middle tier can do whatever it likes.
The obvious way to bypass this would be for the client to use the account of someone with full access. Of course, if they could do that, they'd already have what they wanted.
Hopefully, this approach would be useful in solving your problem.
edit
This solution does not allow LINQ-to-SQL in the client, just the middle tier. If that's a dealbreaker, then this isn't for you. Then again, the moment the client can access the database directly, a gigantic security door is opened up, and it's hard to close. There's a huge amount of extra work involved in securing the database itself so that it provides the sort of user-based, row-level security that comes naturally from a three-tier solution. I would generally recommend against it, although I do recognize that there are times when it is entirely appropriate.
One way would be to use a Trusted Connection to SQL Server, that way you don't store the username / password in code.
I don't think there is any one-solution-fits-all to this problem, you will need analyze and adjust your solution to the particular problem you are having.
As far as I know there are no known ways of securely storing your connection information on the client side as your client is a "trusted" part of the communication to the server. No matter how you store the information, the client has to be able to reverse it or send it directly to the server, which also means that a potential attacker can repeat the process. Also any external communication directly to your database can potentially be intercepted/hacked.
The best way I can think of to protect your data is having a webservice (over a secure connection) as middleware controlling the communication with your database(which you need to secure) and adding logic to enforce whatever level of security you wish to attain. You can make it account based to grant different levels of access if needed. But the main thing is that it only allows safe/isolated operations.
To secure the webservice(middleware) there are two concerns, authentication and isolation.
Authentication
You can use the standard .NET authentication as Steven suggested. I normally prefer rolling my own solution though for two reasons. First off, so far I've mostly ended up handling more complex users/roles. For example using permission based roles so that you can check for permissions instead of specific roles.
And second, it gives you more control. You can avoid session based authentication and you can also use challenge-response, for example challenge with a timestamp and expect a hash of the timestamp+password(which the user has to enter at application start) or some other creative combination as answer, I am sure there are better hash combinations to respond with. This should also be done two-way, to make sure that the client verifies whatever it gets from the server.
Also here are some SO topics about WCF Authorization that might be interesting:
WCF Service authorization patterns
Authorization and Authentication using WCF
WCF Authorization - access to operations via claims
And also a book and a paper (not free)
Isolation
No matter how secure your authentication is, there is always the possibility of someone being able to access your webservice for malicious intents. As far as I know there is no one solution to this problem, but it is rather dependant on the specific application and how the data is structured and shared between users.
You will need to identify layers of isolation such that users cannot affect each other or the system in general, and also how the application is used. Will clients need to write data, or only read? If they write, is written data shared in any way and in what way can you isolate/verify that data? If they read, is the information private for the user, private for the system or shared among users?
For example a system for storing medical journals or personal task lists will have very isolated data and you can restrict access to your private information only (and possibly your doctor/boss depending on user groups). In this case you can isolate all data read/writes to the particular user, thus the attacker can only affect his own data, keeping everyone else safe.
If the data is shared between users you will need some way of verifying the input that is given from the user. Preferably you should also have some kind of trust-level for the user such as SO's reputation to prevent any one-time users to attempt a hack. This is really too specific to give any good advice on.
You also properly need to verify the input that you recieve to prevent hacks such as buffer overflow hacks and SQL injections. Allthough I don't know if buffer overflow is a problem with .NET, and SQL injections should be easily preventable with LINQ-to-SQL.
All in all there is no 100% guaranteed way of securing your data, and you should keep regular backups (separate from your database) of your data in case you get compromised and probably also transaction logs.
And as a final advice, if you are really serious about the security you should probably hire a security consultant and have a peek at how banks have set up their security infrastructure.
Also you can still use LINQ with webservices through LINQ to ADO.NET, though I haven't tried this myself.
This link might be more explaining How to move from LINQ to SQL to “LINQ to WCF”?
Where security is that important, for example when you are storing credit card information, you'll usually want the data repository and the webserver on seperate boxes, with a firewall between and both locked down by IP Security.
This way, only the webserver is exposed to the outside world. Your database server is sitting comfortably behind the firewall, and can only be accessed by the webserver through a certain port.
You might also consider SSL encryption on the web services and expose only HTTPS endpoints.
I am not completely clear here. If the winforms application calls webservice then use a appropriate model for mutually trusted authentication. This can be based on client and server certificates or SSL with client certs or even Net.Tcp if you are all .Net. Then however the webservice is exposed only trusted clients can communicate. The webservice can then stay behind a DMZ and the DB behind another DMZ. Use appropriate firewall rules and IPSec connection between webservice and SQL is an option.
For direct connection to SQL server to many winforms application the challenges are many.The connection to your DB has to authenticated and encrypted. In any case your SQL server will be exposed and I would not recommend such a model.
You don't secure it because you can't secure it. First you can't properly hide credentials, even though you figure out how to do that then an attacker can sniff (yes even if it's encrypted you can locally sniff) or do SQL Injection directly on the wire.
You need to write all of you webservice calls in a secure manner which doesn't require to transfer raw SQL Query or direct SQL Server connection.
Also it doesn't matter how much obfuscate or encrypt it if the code is not running your system it's not your code any more. By reverse engineering, debugging, modifying the code a potential attacker can change your application into something else and do whatever they want.
Also as someone else wrote your webservice will be open to direct access. Someone can make a call directly to your web service and ignore the GUI at all.
A secure method is:
Place the data layer behind a (WCF) service on an physically separate Application Server and have WinForms clients connect to the service using their Windows Credentials. The service then validates whether users can access the various methods in the service based on an Authorisation store (such as Active Directory), and database or combination thereof.
The data service can then use a single pooled identity to connect to a database.
One of the more common approaches with web services is to pass an encrypted username and password via the web method signature in order to validate that the user attempting to invoke the web method indeed has rights to do so.
In terms of the configuration file it is possible to encrypt the file itself or use integrated security as another poster mentioned.
It's difficult to provide a precise answer because I'm not sure what specific issues you are trying to solve and which is the key driver for securing the system.
However, in the past I have used WinForms -> WebService secure communication by utilising WSE
We used X509 certificates and WS-Security. This has the distinct advantage of providing End To End Security rather than relying on standard SSL transport.
However this in of itself doesn't solve issues like user authentication per se, in that case Mitch Wheat's answer seems a good solution.
However, your user authentication model will depend on whether this is a public distributed app, whether the number of users of the tool is large or small etc.
For small numbers of users, or where cost is not an issue, you could implement RSA SecurID authentication by setting up a RADIUS server or such like. This has the advantage in that each RSA key is unique and tied to that user ( though you can never stop a user giving out their credentials and PIN )
HTH
The answer is simple to protect sql strings is simple. NEVER make a direct connetion to SQL in the client side.
Only accept well formed, schema-validated xml serialized objects as the entrance of your program, after being authenticated in a hashed public private key pair (http://msdn.microsoft.com/en-us/library/6f05ezxy.aspx) , being the public key certificate shipped within your program, so someone eavesdropping wont discover the password.
Also, watch out for DDOS attacks. Measure the use of each webservice exposed for each client, and if the use rises above a given limit, block all incoming connections from the user, and from the user´s ip.
If I understand the OP correctly, the immutable design characteristics are a WinForms client connecting directly to a publicly accessible SQL Server?
Almost everyone who responded has basically said 'don't do this, use a web service instead'. This is good advice. Even if the ws is hacked, it can only do things it was designed to do. So an RPC WS can only execute methods already written whereas hacking a SQL Server connection would allow arbitrary SQL Execution. Also, I think you would find that a well designed web service would be more performant.
However, if you are going to do this then you must secure your SQL connection over SSL (see technet) as a start. As with secure web services (which also would use SSL) this will hide the contents of the traffic from the men in the middle.
You can't rely on the authentication of the connection string (but using it adds another layer for a hacker to get through), so you must have an application level authentication layer that you most likely would roll yourself.
Don't allow the WinForms application to connect to your operational database. Create another database instead and allow the connection string based auth to connect to it. Do not do dynamic SQL with this design, use stored procedures instead. Create stored procedures in your public database that would act as your "rpc web service" to hide the real SQL (which would query your operational database and return the results). This will hide the operational details of your schema and reduce the surface area of attack.
If procedures are out of the question because you must use dynamic SQL, still keep the public/operational database structure and use views to expose as little of the data as possible. Leverage user id and any multi-tenancy features you have in the database to pre-filter data in the view. If you can do that you reduce the surface area of attack to the connected user's data.
Without understanding why you must allow a direct sql connection, I can only say again that you shouldn't do it. What you are gaining by doing so in the short term is at the cost of your system's long term security.
I am using the WebBrowser control to add a WebInterface to C# app. My desire is to verify that only such app is able to connect to our Web server using SSL client certificates.
My idea was to embed the client certificate in the app and just use when connecting via my app. Anybody have a sugestion on how to do this? Or the only way to make it work is to load the key in the X509Store.
If I put it in X509Store, will it make my key available for general Internet Explorer Usage?
Are you sure this is what you want to do? If you embed the private key in your application (as your approach entails), an attacker can extract it and use it to authenticate their rogue software.
A server cannot authenticate client software. It can only test whether a client possesses some secret. When you embed a private key in your client and distribute it, it will not be a secret anymore.
I'd recommend authenticating users of your software, rather than the software itself. You need to let users generate their own secret, whether it is a password or a private key, and give them an incentive to protect it.
So, several thoughts here:
1.
I agree with 'erickson', validating that ONLY your app can communicate with the app is nearly impossible with your current design. It's just a matter of time before someone reverse engineer's your app and then its game over (if that's you only form of security). If you want to validate that its your app and a valid user then you need to authenticate the user as well as some mechanism of checking the signature of the app in question (which I don't believe is possible in a client-server model...after all I can always lie and say that my 'hackyou' app has the same signature as your 'realapp' and you can't verify that from the server-side)
2.
Remember the WebBrowser control is essentially a wrapper around IE, so without some tricks (which I'll get to in a sec) you would have to add the cert to the user store.
3.
Here's a hacky way to accomplish what you're asking (even though its a bad idea):
First use the WebRequest.Create to create a HttpWebRequest object
Manually load a X509Certificate2 object from either a file or the binary stream encoded in the program
use the HttpWebRequest.ClientCertificates to add your cert to the webrequest
Send the request, get the response
Send the response to the WebBrowser by pushing the ResponseStream of the HttpWebResponse to the DocumentStream of the WebBrowser
This essentially means that you will have to write some wrapper classes to handle the Requests and Responses to and from the Server and are just using the WebBrowser to handling the viewing of the HTML.
In reality, you need to redesign and look at the threats you're trying to handle!
The intent of using the key is not so much to validate the users as to restrict access to users of the app instead of using any WebBrowser. This is sort of an intranet behavior over the public internet.
This is a poor man's DRM. The losses due to people extracting the key are not that important. I think the risk of this happening is low and what we could loose is minimal.
Nevertheless if there is any other idea to restrict access to the WebServer to only users of the App I am open for any suggestions. Basically my desire is now to have a public WebServer wide open to be read by anyone, but access over the public network from diverse places is necessary so setting up a intranet infrastructure is not possible either.
I have a web application that needs to read (and possibly write) files from a network share. I was wondering what the best way to do this would be?
I can't give the network service or aspnet accounts access to the network share. I could possibly use impersonation.
The network share and the web application are both hosted on the same domain and I can create a new user on the domain specifically for this purpose however I'm not quite sure how to join the dots between creating the filestream and specifying the credentials to use in the web application.
Unfortunately the drive isn't mapped as a network drive on the machine, it's only available to me as a network share so unfortunately I can't make a transparent call.
There is one problem I can think of with impersonation... I can only impersonate one user per application domain I think but I'm happy to be corrected. I may need to write this file to several different shares which means I may have to impersonate several users.
I like the idea of creating a token... if I can do that I'll be able to ask the use up front for their credentials and then dynamically apply the security and give them meaningful error messages if access is denied... I'm off to play but I'll be back with an update.
Given everyone already has domain accounts. Try IIS integrated authentication. You will get an ugly logon box off network but your creds should pass down to the file share.
#lomaxx
Are you saying that only you have perms to the share or that you manually mapped it to a drive letter. If the later you can use ucn \host\share the same way you would use a c:\shared_folder.
Random
Would it be a burden to mirror the share to a local folder on the host? I hear ROBOCOPY is pretty handy.
Another Idea. Run IIS on your target share you can read via http and if you need to write investigate webdav.
I've had no problems connecting to network shares transparently as if they were local drives. The only issue you may have is what you mentioned: having the aspnet account gain access to the share. Impersonation is probably the best way to do this.
You should be able to use any filestream objects to access the network share as long as it has a drive letter on the server machine.
Impersonation worked well for me in this scenario. We had a wizard that uploaded a zip file through the website, but we load balanced the site. Therefore needed to setup a way to save the file on all the machines.
There are many different ways to do it. We decided to make all requests to run under the user we setup and just added the web.config entry and setup the security permissions on the folders for the user. This kb article explains the setup very well.
You do have some options and one of of those is impersonation as you mentioned. However, another one I like to use and have used in the past is a trusted service call. Let's assume for a moment that it's always much safer to limit access through IIS to ensure there are as few holes as possible. With that let's go down this road.
Build a WCF service that has a couple of entry points and the interface might look like this.
public interface IDocumentService
{
public string BuildTrustedRelationship(string privateKey);
public byte[] ReadFile(string token, string fileName);
public void WriteFile(string token, string fileName, byte[] file);
}
Now, you can host this service via a Windows service very easily and so now all you need to do is on Application_start build the relationship with the service to get your token and you're off to the races. The other nice thing here is that this service is internal, trusted, and I've even hosted it on the file server before and so it's much easier to grant permissions to this operation.
If you can create a new AD user, I think the simplest solution is to have the Application Pool run under that AD account's authority, which would mean your application is now running as the AD user. You would need to add the AD user to the IIS Worker Process Group on the machine running your application. Then as long as your AD user has write permissions on the network share, you should be able to use the UNC path in your file operations.