Skip to content

Security protection of various files in Win32 OpenSSH

Joey Aiello edited this page May 13, 2017 · 28 revisions

Secure protection of keys

Starting with the release of v0.0.13.0, Win32-OpenSSH ensures files are secure before they are loaded. ssh-keygen.exe generates protected key files as well.

The following files need to be "secure":

  • on the client-side
    • user's private keys
    • user's ssh_config located at ~\.ssh\config
  • on the server-side
    • user's authorized_keys
    • private host keys

"Secure" means:

  1. The file owner of these files must be one of the following (additionally, no other users or groups may have any access to the files):
    • the local Administrators group
    • LocalSystem account
    • a user in the local Administrators group
    • the user associated with a user key or user config
  2. NT Service\sshd must have (and only have) Read access to authorized_keys and all host keys. (Note: this means that NT Service\sshd cannot have Write access or Full Control.)

Utility scripts to adjust file permissions

The following scripts are used in instructions below to help with managing the permissions of key files:

Set-SecureFileACL

Set-SecureFileACL removes inherited ACLs on a file, assigns the current user as an owner (unless the -Owner parameter is specified), and grants the owner Full Control of the file:

function Set-SecureFileACL
{
    param(
        [string]$FilePath,
        [System.Security.Principal.NTAccount]$Owner = $null
        )

    $myACL = Get-ACL -Path $FilePath
    $myACL.SetAccessRuleProtection($True, $True)
    Set-Acl -Path $FilePath -AclObject $myACL

    $myACL = Get-ACL $FilePath
    $actualOwner = $null
    if($owner -eq $null)
    {
        $actualOwner = New-Object System.Security.Principal.NTAccount($($env:USERDOMAIN), $($env:USERNAME))
    }
    else
    {
        $actualOwner = $Owner
    }

    $myACL.SetOwner($actualOwner)

    if($myACL.Access)
    {
        $myACL.Access | % {
            if(-not ($myACL.RemoveAccessRule($_)))
            {
                throw "failed to remove access of $($_.IdentityReference.Value) rule in setup "
            }
        }
    }

    $objACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
        ($actualOwner, "FullControl", "None", "None", "Allow")
    $myACL.AddAccessRule($objACE)
    Set-Acl -Path $FilePath -AclObject $myACL
}

Example: Setting the owner of authorized_keys

$user = "<myusername>"
$objUser = New-Object System.Security.Principal.NTAccount($user)
Set-SecureFileACL -filepath $env:systemdrive\Users\$user\.ssh\authorized_keys -owner $objUser

Add-PermissionToFileACL

Add-PermissionToFileACL grants NT Service\sshd read permission to a file.

function Add-PermissionToFileACL
{
    param(
        [string]$FilePath,
        [System.Security.Principal.NTAccount] $User,
        [System.Security.AccessControl.FileSystemRights]$Perm)

    $myACL = Get-ACL $filePath
    $objACE = New-Object System.Security.AccessControl.FileSystemAccessRule `
        ($User, $perm, "None", "None", "Allow")
    $myACL.AddAccessRule($objACE)
    Set-Acl -Path $filePath -AclObject $myACL
}

Example: Setting owner of public host key to NT Service\sshd

Add-PermissionToFileACL -FilePath "$hostKeyFilePath.pub" -User "NT Service\sshd" -Perm "Read"

Managing keys end-to-end for Win32-OpenSSH

Generating new keys using v0.0.13.0

If you've generated your host or user keys with ssh-keygen.exe after build v0.0.13.0, the user you've used to generated them will be the owner and have Full Control access. However, some files will still require some ACL modification.

  1. If the generated keys (both private and public) are going to be used as host keys, you must grant NT Service\sshd Read access:
Add-PermissionToFileACL -FilePath $hostPrivateKeyFilePath -User "NT Service\sshd" -Perm "Read"
Add-PermissionToFileACL -FilePath "$hostPrivateKeyFilePath.pub" -User "NT Service\sshd" -Perm "Read"
  1. On the server running sshd, grant NT Service\sshd Read access to authorized_keys in ~\.ssh\:
$user = '<myusername>'
$userProfilePath = "$env:systemdrive\Users\$user"
Add-PermissionToFileACL -FilePath "$userProfilePath\.ssh\authorized_keys" -User "NT Service\sshd" -Perm "Read"
  1. On the client machine, if a user has a ssh_config at ~\.ssh\config, make sure that the user is the owner and has Full Control:
Set-SecureFileACL '~\.ssh\config'

Transitioning existing keys to v0.0.13.0

If you have host or user keys that were generated before build v0.0.13.0, you'll need to secure those key files before using them v0.0.13.0 or later.

The keys generated by ssh-keygen.exe before v0.0.13.0 inherit permissions from the parent folder. That means that some disallowed accounts may also have access to the file.

  1. On the server running sshd, change the file permission of the private host key to set the current user as owner and grant current user Full Control and NT Service\sshd Read access.
Set-SecureFileACL -FilePath $hostPrivateKeyFilePath
Add-PermissionToFileACL -FilePath $hostPrivateKeyFilePath -User "NT Service\sshd" -Perm "Read"
  1. On the server running sshd, grant NT Service\sshd Read access to the public host key:
Add-PermissionToFileACL -FilePath $hostPublicKeyFilePath -User "NT Service\sshd" -Perm "Read"
  1. Before using a user key file with ssh-add, scp, ssh, or sftp, make sure that the file is owned by the user, and that the user has Full Control.
Set-SecureFileACL -FilePath $userPrivateKeyFilePath
  1. On the server running sshd, change the file permission of authorized_keys in a user's home directory to set the current user as owner and grant the current user Full Control and NT Server\sshd Read access.
$user = '<myusername>'
$userProfilePath = "$env:systemdrive\Users\<user>"
$objUser = New-Object System.Security.Principal.NTAccount($user)
Set-SecureFileACL "$userProfilePath\.ssh\authorized_keys" -owner $objUser
Add-PermissionToFileACL -FilePath "$userProfilePath\.ssh\authorized_keys" -User "NT Service\sshd" -Perm "Read"
  1. On the client, if a user has their own ssh_config located at ~\.ssh\config, it must be owned by that user (or a group to which that user belongs):
Set-SecureFileACL "~\.ssh\config"
Clone this wiki locally