We have a windows application (C# .net) and we'll be giving installers to client. The requirement is that once the application has been installed , user should not be able to edit the system time/date . This is to make sure that the application generated dates/reports are not manipulated.
My target OS is Win-XP
What is the best way to do that ?
Does OS provide any facility to do that ?
Client machine is a stand alone machine and is not on any network.
Thanks in Advance
As said here already, you can use group policies, but they are easily circumvented. Also, your customers may react hostile (rightfully so) if your app does that. Still, in case your application is in a closed network, talk to the sysadmin and get it rolled out as a policy.
If you really need a trusted time source, then do so: Write a Web Service or use an existing NTP Service that your application contacts and use the time returned by that trusted service. Then use signing techniques to prevent tampering with the reports afterwards.
Downside: you need internet access. Possibility is to have the client setup a NTP Server within their network (AFAIK Windows Domain Controllers can do that automatically?) and use that, but then the client can again tamper with it.
But bottom line is: Contact a webservice to make tampering hard or use group policies to make tampering easy. Making tampering impossible isn't possible anyway.
That sounds more like a server-fault question; I wonder if "group policy" is the way to do that on a per-machine basis;
However - for a programming answer - why not get the time from a central server when your app starts? Calculate the offset from the local time and apply that throughout your app.
If security needs to be tight you may need to sign the response from the server to prevent spoofing (in particular via "hosts" etc).
You block this by changing Windows Policy. You can either do this from Active Directory (Group Policy) or by manipulating the local seurity policy.
See link: http://www.sevenforums.com/tutorials/113557-date-time-allow-prevent-users-groups-changing.html
But I would rather recommend that you check time with an online server instead. Preventing such a thing for users may give them big problems if their BIOS resets or something.
I don't think that is possible because that is related to group policy rather than your application changing any system settings which will prevent users from changing system date time. Go through these it might come of use -
If XP Pro, use the Group Policy Editor to create fine-grained
permissions.Start>Run gpedit.msc [enter]
If XP Home, look at Doug Knox's Security Console and see if it will do
the job for you: http://www.dougknox.com
No, you can't prevent a basic OS function like this (aside from a group policy...but not programmatically, especially if the users had admin permissions). If you could do this programmatically, it could easily be exploited for mis-use (changing the time and breaking Kerberos authentication for example).
Only through Domain policy - admins must prevent the user not to mess with the time.
Windows 2008 has an option to sync time with internet.
Alternative is that you create a web service that your app could access through internet and get the non-modified time.
You need to implement local or group policy for that. I don't know if you can easily manipulate it from C#.
Assuming these machines are not actually under your administrative control then clearly you can't do this. But an alternative would be to get the time used to generate your timestamps from an external web service, you could use some sort of encryption to access the service to ensure the client can't tamper with the result en-route.
Related
I've been asked to write a C# application to run on a Windows 7 machine to display the time of day, weather, etc.. That I can do. What I'm looking for is guidance to run the application on a Windows7 machine without logging as a user. In essence the machine would simply be a CPU with a screen. No keyboard or mouse. I've seen deployments done on MS-PixelSense (use to be MS-Surface) using a service ID.
If I need to signin, user policies kick in, screen savers enable, etc.. I'm assuming if I use an automatic Service ID, I can let the application override most of the settings keeping the screen on and needed privileges assigned / locked down to the service ID.
Any information / suggestions are appreciated....
First, some background informations:
Accessing a network share
If a process running on your client wants to access a (CIFS) share, it has to be run under a user account (or "Service ID") which has access rights to this share. There is a way (if the client is a member of Active Directory) that the machine name appended with $ (which is in fact the machine account’s name in AD) has to be entered in the ACL (Share / NTFS), but this is not a very "usual" way.
See also https://serverfault.com/questions/41130/network-service-account-accessing-a-folder-share
Windows Service running under a user account (aka technical account or Service ID)
A service running under a user account cannot access the GUI. There are some tricks, and some years ago I wrote a tool which allows a service to start another GUI program, where the GUI is displayed above the Ctrl-Alt-Del dialog. But this does not work under Windows 7 anymore.
But even a service which runs under local system cannot display a GUI on the logon screen.
You would have to write a Credential Provider.
See
Windows service showing a GUI when no user is logged in
https://stackoverflow.com/a/3074040/4547223
Another very deep technically article. It says it is possible to display a GUI on the secure desktop / logon screen. I have not yet tested this myself:
http://calebdelnay.com/blog/2012/01/displaying-a-program-on-the-windows-secure-desktop
Autologon
The most well known way is still the "classic" autologin.
See https://security.stackexchange.com/questions/10170/how-secure-is-windows-auto-logon for some explanations and links.
The medium secure way is to store the password as LSA secret (can be done in C# with P/Invoke or with some tools).
If I need to signin, user policies kick in, screen savers enable, etc.
Yes, but this can be handled, you probably have to create an own AD OU with an own policy for that.
I'm assuming if I use an automatic Service ID, I can let the application override most of the settings keeping the screen on and needed privileges assigned / locked down to the service ID.
A service ID /technical account is basically the same as a normal personal user account.
In some Active Directory enterprise environments a technical account has restrictions that it cannot log on interactively and other restrictions. But it still IS a "user account"
Logonexpert (http://www.logonexpert.com/)
I tested this (trial version). It is a nice, small tool which does it’s job. It is more safe than "normal autologon", however in the end, it is not much different from normal classic autologon. One benefit: it stores the password more recurely, but in theory, some hacker may still decompile the program and find out a way to decrypt it. And more important for you: Beside the more safe password store, it does not gain you much. You still have a user login same as normal autologon.
A few suggestions
Probably you can use a local user account on the client system and use normal autologon mechanism. And then you should consider that the client system does not poll for new data on a network share, but instead another server program (implemented as a service, running under a technical domain account) pushes data on a network share on the client.
Doing it this way, the client code does not need to access network shares, with the benefit, that a malicious attacker also has no access to network shares.
If you really need to access a network share from the local user context, you can probably logon to the server, as explained in my answer here:
https://stackoverflow.com/a/28749093/4547223
You have to to change the registry code part with the access to the CIFS share.
But doing it this way, you again have a password, which you have to encrypt and store. I do not recommend this.
In the end...
Windows does not make it easy what you want to do. If you are not strictly bound to Windows, you can consider using a Raspberry Pi with Raspbian (a Debian derived Linux). You can install Chromium browser, which displays a web page on the server and updates automatically. We use this with great success for some time.
We have an ASP.NET 4.0 Web application that connects to a SQL Server on a separate machine across a LAN. I use a ConnectionString (with SQL Server authentication) stored in my Web.config to do this. Basically, it's a fairly traditional Web-Server-to-SQL strategy.
However, one of our clients is arguing that this strategy is not secure. This client says that we should only connect to the SQL Server through a separate Web Services layer.
I really don't want to rewrite this app just to satisfy this client. What should I tell him? Does any one know how I might best refute this?
Thanks in advance...
Security is always a trade-off. What is the client really afraid of?
Having database credential "in the clear"? I have seen auditors point this out as a potential vulnerability, but really, if someone has compromised your web server they can run arbitrary code against the database, so encrypting database credentials doesn't really buy you much.
Your web app should be using a minimal-rights user to connect to the database, so compromising the web server should only give you the rights to read & update data. How would that change if everything went through a web services layer? Again, there is a very real cost - in complexity, and in performance - by going to a web services layer. Only the client can answer whether or not that cost is worth it.
If this is a web project, you need to change IIS servers running user to a domain user and give permission on sql server to that user.
Than you can use SSPI on your connection string like below.
Like this, you don't need to keep your username or password clearly on web.config.
<configuration>
<system.web>
<identity impersonate="true"/>
</system.web>
and your connectionString
"Integrated Security=SSPI;Initial Catalog=TestDb;Data Source=10.10.10.10"
There are many customers that argue the work of an IT professional, just like there are many people visiting the doctor asking for the medicine instead of what disease they have, because they already know the answer since they read about it on the internet.
I mean, they ask you to build the application and you as an IT professional should know best when your application works as expected. You as a professional should have balls to tell your customer that if he think can get somewhere else better, he should go there or perhaps build the application himself; that's what have done in the past with positive results :)
Regarding security; perhaps for their confidence you can encrypt the web.config and show them, but actually it means nothing; if someone can access the server, they could decode it. On the other hand, someone that want to break in to your database should pass trough a lot of barriers. It's hard to break in, perhaps impossible. Another options is simply blocking connections from outside network the network or ip range or whatever. I think this shouldn't be something to worry about.
There much more and either more realistic concerns to worry about, such as preventing cross site scripting and such common treats.
The client is wrong introducing another tier would not automatically improve security.
In a nutshell use SQL server roles for data access for example the built in data_reader and data_writer roles are a good place to start. Always use the most appropriate least privilege account for the application. If you only need to read data use an account that only has access to read.
Use Windows authentication where possible, if this isn't possible then at least encrypt the connectionstring.
More information on how to do what I've described can be found at http://msdn.microsoft.com/en-us/library/ff650037.aspx#pagpractices0001_dataaccess
One possibility is to encrypt the section in the web.config. So, only user who can access the webserver directly can decrypt this section.
Here is how this works with the help of the iisreg-tool:
http://msdn.microsoft.com/en-us/library/zhhddkxy.aspx
You could enable Encrypted connections in your database and tell the client that the connections are encrypted so fully secure?
To make it more secure, and satisfy your customer you can use Tunneling between your computers.
You setup a server tunneling program where the database exist, and client tunneling programs on the client computer. You connect the one computer to the other via tunneling, and the database connection happens over tunneling.
And everything is exchange high secure (and compressed if the tunneling support it).
http://en.wikipedia.org/wiki/Tunneling_protocol
http://en.wikipedia.org/wiki/HTTP_tunnel
Ps I connect to my server only via tunneling for anything that I do.
I never liked using the web config. The registry is more secure.
Best Practices is to:
Hide the important items of the connection string in the registry
Encrypt the important items in the connection like user names, passwords and server name in the
registry
Access the registry through a class
Build the connection string on the fly and only when needed per page
Error handle every page so the connection string won't show, in case of error
Always close the connections once done. Avoid memory leaks
Always close and reset DataReaders
For additional Security
You can build a separate program to create the connection string and
reference that project as a library inside the solution
If you want to be really secure your client is correct. Send the information to a dll that will communicate with the DB. This is a lot of work
Sources:
From ScottGu # http://msdn.microsoft.com/en-us/library/Aa302406
Scalability:
In regards to scalability: Creating\Editing registry keys across a web farm can be accomplished very easily, with custom admin software.
http://weblogs.asp.net/scottgu/archive/2010/09/08/introducing-the-microsoft-web-farm-framework.aspx
On a final note to all the people who voted me down. Security out of the box is just not enough. Security is an Art and not Science.
Hackers know where the password is stored by default......
ASP.NET 4.0 Fans
Microsoft makes it easy for asp.net 4.0 web sites to deploy registry settings:
http://msdn.microsoft.com/en-us/library/dd394698.aspx
So in the past I have always developed windows forms client software while inside the work network, we went on the lazy rule that no external hardware is allowed on site, nobody can tamper with the hardware so software was always going to be run within the network which were all joined, this allowed me to lazily set the context as follows:
WindowsPrincipal wp = new WindowsPrincipal(WindowsIdentity.GetCurrent());
Thread.CurrentPrincipal = wp;
So now I have been asked to write an application which is going to be running on sales-rep laptops. I can't 100% guarantee that they don't take that software and run on their home PC and have it "pretend joined" to a network. I know I can detect what network name they might be joined to, but what is the correct approach for guaranteeing that the network IS in fact OUR network? Is there some sort of fingerprint I can embed inside the application itself for determining if the network is our work network?
Gosh, that's what you meant. Head meets table in my place.
What you need is a License-Server. You're obviously describing a company license situation! Do you have an MSSQL-Server in your network?
Create a User like your_program_nameLCU (license check user)
Create a database where the user has read access
Create a Try-Catch for the situation when the database is not accessable
Obviously he's not in your network so shut down the program!
Addition to that:
It work's very well with VPN! And I guess that's what needed too!
If it is just a basic network name check you want you can just use the identity name (WindowsIdentity.GetCurrent().Name) which should contain DOMAIN\username. Once you have that plenty of ways to split the strnig and retrieve the DOMAIN name (see Built-in helper to parse User.Identity.Name into Domain\Username).
As wegginho mentioned in the comments though someone could theoretically set their network name to the same network.
I'm writing a simple service to set the default printer based on where I'm connected, but I'm having trouble using WMI in my service. The more I think about it the less I think it's possible to do what I'm trying to do; as a service is not associated with a particular user, but I thought I would ask about it anyway in case my suspicions are wrong.
Here is what I'm doing.
Service subscribes to NetworkChange.NetworkAvailabilityChanged event.
When event is received query WMI SELECT * FROM Win32_Printer WHERE Network=true.
Loop through the ManagementObjectCollection and check the status of each printer.
If the printer is connected call ManagementObject.InvokeMethod("SetDefaultPrinter",null)
When I check the Security event log I noticed Failure Audit events "Unknown username or bad password", which I'm assuming is because I did not explicitly supply that information.
Is there a way to do this without specifying a username and password, or are credentials required for security purposes?
The service must run as some user, for example NETWORK SERVICE, LOCAL SERVICE or SYSTEM. You need to make sure the given account has permission to do what you want.
To change the permission of a deployed service on Windows go to Start > Administrative Tools > Services then you can change the service account for a given service.
I know this is an old question but i feel the existing answer doesn't quite provide a manageable solution.
As pointed out to effect a users default printer selection you need to be authenticated as that user and whilst it is possible to set a windows service to logon as a specific user a better solution would be to ...
Create a winforms program using a hidden form and launch it when the user logs on using Task Scheduler.
This way the PC can be used by many users and benefit from the application without having to change the service logon settings.
I suggested a winforms application as it has a low entry bar, you can use any other kind of invisible from a UI perspective project type.
you should use linqtowmi for this it works great!
I'm currently in the process of creating a Windows service application which will monitor changes to certain keys made in the HKEY_USERS registry. The way I do this is by collecting the SID of the current user. The issue I'm having is that its returning the administrators SID due to the service currently running as local system.
What I need the system to do is collect and return the SID of the currently logged in user (by this I dont mean the local service, local system or network service but the person whos logged into windows via the GINA), so what I need the service to do is run as that user. This will also allow the service to write back to the users network drive which is the intention of this program.
The issue I'm having is that when I try and install a user service using installutil.exe it asks for a username and password now I've tried my own credentials (I have an admin and non admin account) but it isn't having any of it plus I want the user to change depending on the person logging on and not to be fixed. Is there any way to do this?
The "The current user" assumption is a desktop Windows concept, and with Fast User Switching even that is not true anymore. The Windows services layer is rather common across desktop and server variants, and doesn't really deal well with this. It sits below the interactive sessions layer. One of the ways this manifests itself is in the ability to run services even if there are zero users logged in.
This all seems a bit confused. There can be any number of people logged on via remote desktops etc. If you as a service want to see their registry, you definitely wont get there via HKCU. If you want something like this, you should be using an autorun exe rather than a service. Anything like inspecting sessions and injecting stuff into them to access the loaded registry hive in the session is way overkill and not likely to be clean in any way.
You can find a process that runs with every user like explorer.exe then get the SID of the user that runs the process (you can use WMI like in the function here)