这篇文章上次修改于 1164 天前,可能其部分内容已经发生变化,如有疑问可询问作者。

漏洞说明

Windows server 2016远程桌面服务SSL加密默认是开启的,且有默认的CA证书。由于SSL/ TLS自身存在漏洞缺陷,当开启远程桌面服务,使用漏洞扫描工具扫描,发现存在SSL/TSL漏洞。
例如如下漏洞:
img

修复办法

1、登录服务器,打开windows powershell,运行gpedit.msc,打开“本地组策略编辑器”。
img

2、打开“本地组策略编辑器”-“计算机配置”-“管理模板”-“网络”-“SSL配置设置”, 在“SSL密码套件顺序”选项上,右键“编辑”。

img

img

3、在“SSL密码套件顺序”选在“已启用(E)” ,在“SSL密码套件”下修改SSL密码套件算法,仅保留TLS 1.2 SHA256 和 SHA384 密码套件、TLS 1.2 ECC GCM 密码套件。
删除原有内容替换为:

TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P256,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256_P521,TLS_ECDHE_ECDSA,WITH_AES_256_GCM_SHA384_P384,TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384_P521,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P256,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256_P521,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P521,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P256,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P384,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256_P521,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P384,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384_P521,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_NULL_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA

修改后,点击“应用”、“确定”,即可。
img
原本内容为:

TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,TLS_DHE_RSA_WITH_AES_256_GCM_SHA384,TLS_DHE_RSA_WITH_AES_128_GCM_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256,TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,TLS_DHE_RSA_WITH_AES_256_CBC_SHA,TLS_DHE_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_AES_256_GCM_SHA384,TLS_RSA_WITH_AES_128_GCM_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA256,TLS_RSA_WITH_AES_128_CBC_SHA256,TLS_RSA_WITH_AES_256_CBC_SHA,TLS_RSA_WITH_AES_128_CBC_SHA,TLS_RSA_WITH_3DES_EDE_CBC_SHA,TLS_DHE_DSS_WITH_AES_256_CBC_SHA256,TLS_DHE_DSS_WITH_AES_128_CBC_SHA256,TLS_DHE_DSS_WITH_AES_256_CBC_SHA,TLS_DHE_DSS_WITH_AES_128_CBC_SHA,TLS_DHE_DSS_WITH_3DES_EDE_CBC_SHA,TLS_RSA_WITH_RC4_128_SHA,TLS_RSA_WITH_RC4_128_MD5,TLS_RSA_WITH_NULL_SHA256,TLS_RSA_WITH_NULL_SHA,TLS_PSK_WITH_AES_256_GCM_SHA384,TLS_PSK_WITH_AES_128_GCM_SHA256,TLS_PSK_WITH_AES_256_CBC_SHA384,TLS_PSK_WITH_AES_128_CBC_SHA256,TLS_PSK_WITH_NULL_SHA384,TLS_PSK_WITH_NULL_SHA256

4、重启服务器即可。

禁止使用RC4加密算法

需要禁止 RC4 加密算法时,可以通过设置以下注册表项来完全禁用 RC4 密码套件。通此时,任何只能使用 RC4 的客户端或服务器将不再能连接到你的服务器。部署此设置的客户端将无法连接到需要 RC4 的站点,部署此设置的服务器将无法为必须使用 RC4 的客户端提供服务。

  • [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 128/128]
    “Enabled”=dword:00000000
  • [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 40/128]
    “Enabled”=dword:00000000
  • [HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\RC4 56/128]
    “Enabled”=dword:00000000

Solve Sweet32

提供的脚本如下

<#
.Synopsis
   Solve Sweet32 Short description
.DESCRIPTION
   Long description
.EXAMPLE
   Example of how to use this cmdlet
.EXAMPLE
   Another example of how to use this cmdlet
.INPUTS
   Inputs to this cmdlet (if any)
.OUTPUTS
   Output from this cmdlet (if any)
.NOTES
   General notes
.COMPONENT
   The component this cmdlet belongs to
.ROLE
   The role this cmdlet belongs to
.FUNCTIONALITY
   The functionality that best describes this cmdlet
#>

[CmdletBinding()]
param(
    [Parameter(position=0,Mandatory=$false)][ValidateSet("SWEET32","TLS1.0","Both")]$Solve="Both"
)

function Write-Log{
    [CmdletBinding()]
    #[Alias('wl')]
    [OutputType([int])]
    Param(
        # The string to be written to the log.
        [Parameter(Mandatory=$true,
                   ValueFromPipelineByPropertyName=$true,
                   Position=0)]
        [ValidateNotNullOrEmpty()]
        [Alias("LogContent")]
        [string]$Message,

        # The path to the log file.
        [Parameter(Mandatory=$false,
                   ValueFromPipelineByPropertyName=$true,
                   Position=1)]
        [Alias('LogPath')]
        [string]$Path=$DefaultLog,

        [Parameter(Mandatory=$false,
                    ValueFromPipelineByPropertyName=$true,
                    Position=2)]
        [ValidateSet("Error","Warn","Info","Load","Execute")]
        [string]$Level="Info",

        [Parameter(Mandatory=$false)]
        [switch]$NoClobber
    )


    Process{

        if ((Test-Path $Path) -AND $NoClobber) {
            Write-Warning "Log file $Path already exists, and you specified NoClobber. Either delete the file or specify a different name."
            Return
        }

        # If attempting to write to a log file in a folder\/path that doesn't exist
        # to create the file include path.
        elseif (!(Test-Path $Path)) {
            Write-Verbose "Creating $Path."
            $NewLogFile = New-Item $Path -Force -ItemType File
        }

        else {
            # Nothing to see here yet.
        }

        # Now do the logging and additional output based on $Level
        switch ($Level) {
            'Error' {
                Write-Host $Message -ForegroundColor Red
                Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") ERROR: `t $Message" | Out-File -FilePath $Path -Append
                break;
            }
            'Warn' {
                Write-Warning $Message
                Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") WARNING: `t $Message" | Out-File -FilePath $Path -Append
                break;
            }
            'Info' {
                Write-Host $Message -ForegroundColor Green
                Write-Verbose $Message
                Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") INFO: `t $Message" | Out-File -FilePath $Path -Append
                break;
            }
            'Load' {
                Write-Host $Message -ForegroundColor Magenta
                Write-Verbose $Message
                Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") LOAD: `t $Message" | Out-File -FilePath $Path -Append
                break;
            }
            'Execute' {
                Write-Host $Message -ForegroundColor Cyan -BackgroundColor DarkBlue
                Write-Verbose $Message
                Write-Output "$(Get-Date -Format "yyyy-MM-dd HH:mm:ss") EXEC: `t $Message" | Out-File -FilePath $Path -Append
                break;
            }
        }
    }
}
function Test-RegistryValue {
    param (
        [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$Path,
        [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$Value
    )
    try{
        if( (Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value -ErrorAction Stop) -eq 0 ){
            return  $true
        }
        return $false
    }
    catch{
        return  $true
    }
}
function Test-RegistryProperty {
    param (
        [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$Path,
        [parameter(Mandatory=$true)] [ValidateNotNullOrEmpty()]$Value
    )
    try{
        if( (Get-ItemProperty -Path $Path | Select-Object -ExpandProperty $Value) -eq 0 ){
            return  $true
        }
        return $false
    }
    catch{
        return  $true
    }
}

$Global:CleanUpGlobal=@()
$Global:CleanUpVar=@()

$global:ScriptLocation = $(get-location).Path
$global:DefaultLog = "$global:ScriptLocation\Sweet32.log"

$Global:CleanUpGlobal+="ScriptLocation"
$Global:CleanUpGlobal+="DefaultLog"
################################################################################SWEET32######################################################################
###                 Source : https:\/\/bobcares.com\/blog\/how-to-fix-sweet32-birthday-attacks-vulnerability-cve-2016-2183\/3\/                                 ###               
################################################################################SWEET32######################################################################

if( ($Solve -eq "Both") -or ($Solve -eq "SWEET32") ){
    Write-Log -Level Load -Message "Solving vulnerability --> SWEET32"

    $TripleDES168="HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Ciphers\Triple DES 168\/168"
    $testkey = Test-path $TripleDES168

    #Create Key Triple DES 168 (A key is a folder in the registry)
    if(!$testkey){
        Write-Log -Level info -Message "Creating Key $TripleDES168"
        New-Item -Path $TripleDES168 -Force | Out-Null
    }
    else{
        Write-Log -Level Warn -Message "They key already exits ($TripleDES168)"
    }

    #Create The property "Enabled" with value 0
    $testentry= Test-RegistryValue -Path $TripleDES168 -Value "Enabled"
    if(!$testentry){
        Write-Log -Level Info -Message "Creating new Enabled Property with value 0"
        New-ItemProperty -PropertyType DWORD -Path $TripleDES168 -Name "Enabled" -Value 0  -Force | Out-Null
    }
    else{
        Write-Log -Level Info -Message "The registry entry with property enabled = 0, already exists"
    }
}

#############################################################################################################################################################
###   Protocols : https:\/\/blogs.msdn.microsoft.com\/friis\/2016\/07\/25\/disabling-tls-1-0-on-your-windows-2008-r2-server-just-because-you-still-have-one\/     ###
#############################################################################################################################################################

if( ($Solve -match "Both") -or ($Solve -match "TLS1.0") ){

    Write-Log -Level Load -Message "Solving vulnerability --> TLS1.0"

    #Define Variables and Arrays
    $TLSRoot = "HKLM:\SYSTEM\CurrentControlSet\Control\SecurityProviders\SCHANNEL\Protocols"
    $TLSArray =@("TLS 1.0","TLS 1.1","TLS 1.2")
    $ClientServer= @("Client","Server")

    foreach($tls in $TLSArray){ #foreach root item check if it's there, 
        $rootpath = "$TLSRoot\$tls"

        if(! (Test-Path $rootpath)){ #if it's doesn't exists, create it  (Remember a key is a folder in registry).
            Write-Log -Level Info -Message "Create new Key ($rootpath)"
            new-item -Path $rootpath -Force | Out-Null
        }

        foreach($cs in $ClientServer){ #cs => Client\/Server array.
            $cspath = "$rootpath\$cs"

            if(! (Test-Path $cspath) ){ #check if the cspath exists (if not create it, if it is, check the property "Enabled" for TLS 1.0 and TLS 1.1 , and "DisabledByDefault" for TLS 1.2
                New-Item -Path "$cspath" -Force | Out-Null
                if($tls -eq "TLS 1.0" -or $tls -eq "TLS 1.1"){ #If tls 1.0 enabled 0 (disabled)
                    if(! (Test-RegistryProperty  "$cspath" -Value "Enabled")){
                        Write-Log -Level Info -Message "Creating new property Enabled = 0 for $tls in ($cspath)"
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "Enabled" -Value 0 -Force | Out-Null
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "DisabledByDefault" -Value 1 -Force | Out-Null
                    }
                }
                else{ #if tls 1.2 (is not disabled by default and it's enabled
                    if(! (Test-RegistryProperty "$cspath" -Value "DisabledByDefault")){
                        Write-Log -Level Info -Message "Creating 'Enabled' and 'DisabledByDefault' for $tls in ($cspath)"
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "DisabledByDefault" -Value 0 -Force | Out-Null
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "Enabled" -Value 4294967295 -Force | Out-Null #Enable tls 1.0 or 1.1
                    }
                }
            }
            else{ #if the root exists Check the property Enabled for tls1.0 and "Disabledbydefault" for 
                if($tls -eq "TLS 1.0" -or $tls -eq "TLS 1.1"){ #If tls 1.0 enabled 0 (disabled)
                    if(! (Test-RegistryProperty  "$cspath" -Value "Enabled")){
                        Write-Log -Level Info -Message "Creating new property Enabled = 0 for $tls in ($cspath)"
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "Enabled" -Value 0 -Force | Out-Null
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "DisabledByDefault" -Value 1 -Force | Out-Null
                    }
                }
                else{
                    if(! (Test-RegistryProperty "$cspath" -Value "DisabledByDefault")){
                        Write-Log -Level Info -Message "Creating 'Enabled' and 'DisabledByDefault' for $tls in ($cspath)"
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "DisabledByDefault" -Value 0 -Force | Out-Null
                        New-ItemProperty -PropertyType DWORD -Path "$cspath" -Name "Enabled" -Value 4294967295 -Force| Out-Null
                    }
                }
            }
        }
    }
}

Write-Log -Level Info "Cleaning up variables"
    $CleanUpVar | ForEach-Object{
        Remove-Variable $_
    }
    $CleanUpGlobal | ForEach-Object{
        Remove-Variable -Scope global $_
    }

更新windows

如果服务器可以联网,及时更新安全更新补丁