About Me · Send mail to the author(s) E-mail · Twitter

At GROSSWEBER we practice what we preach. We offer trainings for modern software technologies like Behavior Driven Development, Clean Code and Git. Our staff is fluent in a variety of languages, including English.

Feed Icon


Open Source Projects


Blogs of friends

Now playing [?]

Error retrieving information from external service.
Page 1 of 1 in the Security category

General Considerations For Securing Windows Servers On The Internet (And Anywhere Else)

Posted in IIS | Networking | PowerShell | Security | SQL Server | Windows at Friday, 08 February 2008 17:04 W. Europe Standard Time

By now there are a couple of Windows Servers that I actively manage, or, in the case of projects, I touched while moving the project forward. Most of these servers have an Internet connection. Since I've been asked how to make servers more secure and manageable, here are a couple of management rules I applied. Consider it a checklist.

  • Use a firewall and configure it accordingly.
  • Enable automatic Windows Updates and upgrade to Microsoft Update to receive updates of other Microsoft products like SQL Server.

Okay, the two above should have been obvious.

  • Keep the machine clean.
    Don't install any unnecessary software and don't leave any temporary files on the server. I've seen certificate requests lingering on drive C: and "test" folder remnants. A clean system might reveal hacker activity early in case they leave unfamiliar files behind.
  • Leverage the principle of least privilege.
    All users and service accounts should only have the minimum rights they need. Configure the file system such that system services can only access the files and folders they are in charge of. Typical example: Use a dedicated service account for SQL Server. (Setting this up on SQL 2005 is even more simple.)
  • Rename the Administrator account.
    Rename the Administrator account and make it match your preferred user naming scheme (i. e. agross). You might apply this to your whole organization if you use Active Directory. This is another hurdle to guess the Administrator account from a list of user accounts and works good with account lockout enabled (see below).
  • Create a new "Administrator" account
    and give it a very strong throw-away password. I typically use two or three concatenated GUIDs that I immediately forget. Disallow this user to change his password, remove all group memberships and disable the account.
  • Audit the hell out of the machine.
    Windows uses the Security event log to record security-related events. Configure auditing using secpol.msc and enable success and failure logging at least for
    • Account logon events,
    • Logon events and
    • Policy change.
    The last option is for tracking changes to the policy you just set.
  • Enable complexity criteria for passwords and account lockout.
    To be found in the same MMC snap-in as above. For account lockout I often go with the default values of 5 attempts and 30 minutes of threshold and duration.
  • Deactivate file sharing/Microsoft Networking on the WAN connection.
    Because it's most likely unneeded.
  • Secure RDP sessions using a certificate.
    Torsten has a nice write-up on how to leverage SSL to secure the RDP handshaking/authentication phase to overcome man-in-the-middle and ARP spoofing attacks. His article is available in German only so here's two-sentence recap: On the server's RDP security tab, enable SSL and choose the same certificate you use for HTTPS encryption. On the client side, enable server authentication.
  • Extra: Allow RDP sessions only from white-listed workstations.
    For a server that was hacked a while ago using an ARP spoofing attack (see bullet above) I wrote a Powershell script forces RDP session to originate from a list of known workstations. Each RDP user can have multiple allowed workstations. If a logon attempt occurs from another machine that RDP session is killed immediately.
    # Alert.ps1
    # Logon script for users with known RDP client names.
    # Array of users with known workstations.
    $userWorkstations = @{
    	"user2" = @("VALIDCOMPUTERNAME3")
    # Logoff executable.
    $logoffCommand = $Env:SystemRoot + "\system32\logoff.exe"
    # Trim the user name.
    $currentUser = $Env:UserName.Trim()
    # Cancel if a user that's not contained in $userWorkstations logs on.
    if ($userWorkstations.Keys -inotcontains $currentUser)
    # Send alert e-mail and log off if the user logs on from an unknown workstation.
    if ($userWorkstations[$currentUser] -inotcontains $Env:ClientName.Trim())
    	$subject = $("Unknown RDP client '{0}' for user '{1}'" -f $Env:ClientName.Trim(), $currentUser)
    	$message = New-Object System.Net.Mail.MailMessage
    	$message.From = ""
    	$message.IsBodyHtml = $false
    	$message.Priority = [System.Net.Mail.MailPriority]::High
    	$message.Subject = $subject
    	$message.Body = $subject
    	$smtp = New-Object System.Net.Mail.SmtpClient
    	$smtp.Host = "localhost"
    	# Force logoff.
    Set the script as a logon script for your users using the Alert.cmd helper script below.
    rem Alert.cmd - runs the Alert.ps1 Powershell script.
    @powershell.exe -noprofile -command .\Alert.ps1
  • Enable SQL Server integrated authentication.
    I don't see a need for SQL Server Authentication in most scenarios, especially if you're running/hosting .NET applications. However, in some projects I've worked on there seems to be a tendency towards SQL Server Authentication for no special reason.
  • Configure IIS log detail and directories.
    I tend to enable full IIS logs, that is, all information regarding a request should be logged. Also, I like my logs residing in "speaking" folders, so instead of %windir%\system32\LogFiles\W3SVC<Some number> they should be placed in %windir%\system32\LogFiles\IIS <Site name>\W3SVC<Some number>. This makes it easy to find the logs you're interested in.
  • Use SSH to connect remotely.
    There's a little free SSH server out there that should fit most user's needs. Besides a secure shell environment freeSSHd offers SFTP and port tunneling capabilities to tunnel insecure protocols. Authentication works natively against Windows accounts.
  • Deploy a server monitoring tool.
    I like to use the free MRTG tool, of course any other tool allowing you quickly view any uncommon activity to will do.
  • Use a dedicated management network interface, if possible.
    You should configure strict firewall rules for that interface. Allow access only from a known management subnet.

What rules do you apply to make your servers more secure and manageable?

Now Playing [?]: MorcheebaDive DeepEnjoy the ride (feat. Judy Tzuke)

How To Secure Your dasBlog Installation

Posted in dasBlog | Security at Friday, 08 June 2007 09:44 W. Europe Daylight Time

dasBlog LogodasBlog has a pretty large user base, and while browsing some dasBlog sites I occassionally check if they're set up securely. It's not that dasBlog is inherently insecure, but some installations allow for information leakage and most users aren't even aware of this.

Basic setup

There are a couple of locations where you can set up security for any ASP.NET application:

  • NTFS security,
  • IIS virtual directory and folder security,
  • web.config <authentication> element or a HttpForbiddenHandler for certain ASP.NET file extensions.

Note that web.config settings only apply to file extensions mapped to ASP.NET on Windows Server 2003 and before. I am working on IIS 6 here and while I like my security settings in (mostly) one place I usually go with a generic read access configuration in IIS and set the more fine-grained settings using NTFS.

When deploying dasBlog to your web server you will likely enable read access to the dasBlog folder for the IUSR and NETWORK SERVICE accounts on the NTFS Security tab. This gives the IIS and ASP.NET runtimes the rights they need to work. On the /logs, /content and /SiteConfig directories you will also need to enable change access for the NETWORK SERVICE account since this is where dasBlog stores its working data. (dasBlog is represented by the IIS worker process identity, which is NETWORK SERVICE on Windows Server 2003 and ASPNET on Windows 2000 and XP.) If anything is set up incorrectly you'll see the configuration error page when you're trying configure your blog or post a blog entry.

Folder IUSR access NETWORK SERVICE access Notes
/dasBlog root R R  
  /bin RI RI Contents protected by ASP.NET
  /content RI RI, W Blog posts, comments, trackbacks
    /binary RI RI, WI Binary content, i.e. images and enclosures
    /profiles RI RI, WI User profiles
  /DatePicker RI RI  
  /ftb RI RI  
  /images RI RI  
  /logs RI RI, W Log files
  /SiteConfig RI RI, W Config and error pages
  /smilies RI RI  
  /themes RI RI  
Legend: R=Read, RI=Read (inherited), W=Write, WI=Write (inherited)

The /logs folder

Sometimes when I visit a random dasBlog site I try to download one of dasBlog's log files which are located in the /logs folder. Since IUSR's read access is most likely inherited (RI) in this folder, anonymous users can download log files. The log file name format is publicy available so, for example, the /logs/ file contains the referrers for today. This information leakage could be easily mitigated by denying IUSR read access to the /logs folder. However, I've found at least three high-traffic blogs where this was not the case (I e-mailed the owners, things are fixed now).


Another problem that came up recently on the developer mailing list was how to keep blog templates private. Since we already incorporate the HttpForbiddenHandler for *.blogtemplate files and IIS doesn't serve files when there's no MIME type available this is really a non-issue. The template's manifest file, however, will be served but that should not bother you since there's no valuable information in it.

Special Case: The /content folder

One rather interesting place is the /content folder. Your posts, comments and blogged binary content like images are stored there. The /content/binary subfolder holds images and enclosures, i.e. basically everything you attach to a certain post. The /content/profiles folder serves as a container for user profiles stored in <Username>.format.html files. Please note that *.format.html files are always templated and served through FormatPage.aspx, that is, are never accessed by IUSR directly.

With the basic setup above, read access for anonymous users is enabled in the /content folder and its subfolders. Thus, anonymous users are able to get the raw post data by requesting the *.dayentry.xml and *.dayfeedback.xml files for a certain date, i.e. /content/2007-06-08.dayentry.xml. Again, the file name pattern is no secret.

This last piece of public information should only be served through certain channels like the templated font page or RSS. Because of dasBlog's folder structure securing the /content folder it is kind of tricky:

  • First, deny read access to the /content folder for the IUSR account.
  • In the next step, open the security tab of the /content/binary folder and break NTFS inheritance there copying all existing ACLs.
  • Delete the Deny ACL for IUSR.

Secure Configuration

In the end the NTFS security settings that work best for me look like this: (Changes red)

Folder IUSR access NETWORK SERVICE access Notes
/dasBlog root R R  
  /bin RI RI Contents protected by ASP.NET
  /content RI, RD RI, W Blog posts, comments, trackbacks
    /binary R R, W Binary content, i.e. images and enclosures
    /profiles RI, RDI RI, WI User profiles
  /DatePicker RI RI  
  /ftb RI RI  
  /images RI RI  
  /logs RI, RD RI, W Log files
  /SiteConfig RI, RD RI, W Config and error pages
  /smilies RI RI  
  /themes RI RI  
Legend: R=Read, RI=Read (inherited), W=Write, WI=Write (inherited), RD=Deny read, RDI=Deny read (inherited)

Please note that on Windows Deny ACLs have always preference over Allow ACLs.


If you're a dasBlog developer or user, please feel free to leave a comment if you (dis)like this solution, have a question or suggestions for a better solution.

Now Playing [?]: Robert Mechs – The OGD Sessions Vol. 2

Page 1 of 1 in the Security category