TLS Version 1.0 Protocol Detection and TLS Version 1.1 Deprecated Protocol mean a service accepts handshakes using TLS 1.0 or 1.1, both deprecated by RFC 8996. To fix it, disable TLS 1.0 and 1.1 in the TLS stack serving that port (Schannel registry on Windows, ssl_protocols in nginx, SSLProtocol in Apache), keep TLS 1.2 and 1.3 enabled, restart, and rescan.
What the scanner is actually detecting
This is a remote test. The scanner offers only TLS 1.0 (or only TLS 1.1) in a handshake and records whether the service completes it. It never reads your registry or config files, so it reports what each port actually negotiates.
| Scanner | How the finding appears |
|---|---|
| Nessus | Plugin 104743, TLS Version 1.0 Protocol Detection, and plugin 157288, TLS Version 1.1 Deprecated Protocol. Tenable rates both Medium. |
| Qualys | QID 38628 and QID 38794 (TLS 1.0 and TLS 1.1 support) |
| Greenbone / OpenVAS | OID 1.3.6.1.4.1.25623.1.0.117274 (deprecated TLS protocol detection) |
| Rapid7 | Equivalent TLS 1.0 and TLS 1.1 support checks |
Read the plugin output first: it names the port, and it is often not 443. RDP (3389), SQL Server (1433), LDAPS (636), WinRM over HTTPS (5986) and management consoles on 8443 show up regularly, and each may use a different TLS stack.
Real-world risk
Stated honestly: this is not a remote code execution bug, and there is no one-shot exploit that decrypts a modern TLS 1.0 session. Microsoft states that its own TLS 1.0 implementation has no known security vulnerabilities. The problem is the protocol design. RFC 8996 deprecated both versions because their handshake integrity depends on SHA-1, they cannot use authenticated encryption such as AES-GCM, and keeping extra versions enabled widens the room for downgrade and misconfiguration. Older attacks such as BEAST targeted TLS 1.0 CBC mode and were mitigated in clients years ago.
The practical pressure is compliance and compatibility. Tenable notes that PCI DSS v3.2 required TLS 1.0 to be disabled by June 30, 2018, with narrow exceptions, so this finding will fail an ASV or internal PCI DSS Requirement 11.3 scan. Major browsers dropped TLS 1.0 and 1.1 in 2020, so any client still using them is an old one worth identifying. Treat this as a normal-cycle hardening fix, done first on internet-facing and cardholder-data systems.
How to confirm it on the host
From a Linux or macOS machine, try each deprecated version against the flagged port:
openssl s_client -connect host.example.com:443 -tls1 -cipher 'DEFAULT:@SECLEVEL=0' </dev/null
openssl s_client -connect host.example.com:443 -tls1_1 -cipher 'DEFAULT:@SECLEVEL=0' </dev/null
A completed handshake prints a certificate chain and a line such as Protocol : TLSv1. The @SECLEVEL=0 part matters: the OpenSSL 3.0 migration guide states that TLS 1.0 and 1.1 no longer work at the default security level of 1, so without it your own client may refuse the handshake and make a vulnerable server look fixed. Add -servername www.example.com to test a specific virtual host. For a second opinion that lists every accepted version per port:
nmap -sV --script ssl-enum-ciphers -p 443,3389 host.example.com
On Windows, check the Schannel protocol keys:
Get-ChildItem 'HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocols' -Recurse
If there is no TLS 1.0 or TLS 1.1 key, the OS default applies. Microsoft’s Schannel protocol table lists both versions as enabled by default on every in-market release, including Windows Server 2022 and Windows Server 2025. On Linux web servers, find where protocols are set:
grep -rn "ssl_protocols" /etc/nginx/
grep -rni "SSLProtocol" /etc/apache2/ /etc/httpd/
How to fix it
Windows Server (Schannel: IIS, RDP, SQL Server, WinRM, LDAPS)
Back up the current state first:
reg export "HKLMSYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocols" C:Tempschannel-protocols-backup.reg
Then create the Server subkeys for TLS 1.0 and TLS 1.1 with Enabled = 0 and DisabledByDefault = 1 (both DWORD). The Client subkeys are optional: add them only if outbound TLS 1.0 and 1.1 from this server should also be blocked.
$base = 'HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocols'
foreach ($proto in 'TLS 1.0','TLS 1.1') {
foreach ($role in @('Server')) { # use @('Server','Client') to also block outbound use
$key = "$base$proto$role"
if (-not (Test-Path $key)) { New-Item -Path $key -Force | Out-Null }
New-ItemProperty -Path $key -Name 'Enabled' -Value 0 -PropertyType DWord -Force | Out-Null
New-ItemProperty -Path $key -Name 'DisabledByDefault' -Value 1 -PropertyType DWord -Force | Out-Null
}
}
Leave TLS 1.2 (and TLS 1.3 on Windows Server 2022 and later) alone. Next, make .NET Framework applications use the OS defaults instead of hardcoded older protocols:
foreach ($p in 'HKLM:SOFTWAREMicrosoft.NETFrameworkv4.0.30319',
'HKLM:SOFTWAREWOW6432NodeMicrosoft.NETFrameworkv4.0.30319') {
New-ItemProperty -Path $p -Name 'SchUseStrongCrypto' -Value 1 -PropertyType DWord -Force | Out-Null
New-ItemProperty -Path $p -Name 'SystemDefaultTlsVersions' -Value 1 -PropertyType DWord -Force | Out-Null
}
Microsoft’s .NET guidance recommends the same two values under v2.0.50727 if .NET Framework 3.5 applications run on the host. Finally, reboot. Microsoft notes that new protocol settings apply only to newly acquired credential handles and that services reuse handles, so a restart of each service is the minimum and a reboot is the reliable option.
For many servers, push the same values with Group Policy Preferences (Computer Configuration > Preferences > Windows Settings > Registry) and add them to your Windows Server hardening checklist so new builds ship without legacy TLS. Remember that Schannel settings do not affect third-party TLS stacks installed on the same machine, such as Java or OpenSSL-based services.
Apache HTTP Server
Set the directive at server config level (outside any VirtualHost) and remove per-vhost SSLProtocol lines that re-add old versions:
SSLProtocol -all +TLSv1.2 +TLSv1.3
TLSv1.3 requires OpenSSL 1.1.1 or later; on older builds use -all +TLSv1.2. Apache’s documentation also notes that a per-vhost SSLProtocol is only honored from 2.4.42 built against OpenSSL 1.1.1 or later; on older combinations the first vhost on that IP and port decides, which is exactly what a scanner connecting by IP hits.
apachectl configtest
systemctl reload apache2 # httpd on RHEL-family systems
nginx
ssl_protocols TLSv1.2 TLSv1.3;
Put it in the http block. nginx has defaulted to TLSv1.2 and TLSv1.3 since 1.23.4, so on a recent build the finding means some file sets older versions explicitly; the grep above will find it. When the directive is set per server block, nginx may use the value from the default server for that IP and port, so fix the default_server too.
nginx -t
systemctl reload nginx
Tomcat and other Java services
In Tomcat 9 and 10.1 the SSLHostConfig protocols attribute defaults to all, which includes TLSv1 and TLSv1.1. Set it explicitly in server.xml:
<SSLHostConfig protocols="TLSv1.2,TLSv1.3">
Older Tomcat 9 configurations may use the Connector attribute sslEnabledProtocols=”TLSv1.2,TLSv1.3″, a deprecated alias for the same setting. For other Java applications, add TLSv1, TLSv1.1 to jdk.tls.disabledAlgorithms in conf/security/java.security (lib/security/java.security on JDK 8), then restart the service.
How to verify the fix and rescan
- Repeat the openssl s_client -tls1 and -tls1_1 tests, with and without -servername where virtual hosts are involved. Both must fail with a handshake error or protocol version alert.
- Run openssl s_client -connect host.example.com:443 -tls1_2 </dev/null and confirm it still succeeds, so you know the service is up and not just broken.
- Run the nmap command again and confirm only TLSv1.2 and TLSv1.3 are listed for every flagged port.
- Rescan the flagged hosts with the same scanner and policy that raised the finding. Only a clean rescan closes it.
What can break and how to roll back
- Old clients: anything that cannot negotiate TLS 1.2, such as Windows 7 or Server 2008 R2 where TLS 1.2 was never enabled, old Java runtimes, embedded devices and older printers or scanners.
- Hardcoded applications: .NET Framework apps targeting 4.5.2 or earlier default to older protocols, which is why SchUseStrongCrypto matters.
- SQL Server: Microsoft lists SQL Server 2012, 2014 and 2016 builds without the TLS 1.2 update (KB3135244) as known to fail.
- Outbound calls: if you set the Client keys, connections from this server to legacy partner APIs, SMTP relays or old LDAPS endpoints will fail.
To roll back on Windows, delete the values you added (the OS default then applies) and reboot:
Remove-ItemProperty -Path 'HKLM:SYSTEMCurrentControlSetControlSecurityProvidersSCHANNELProtocolsTLS 1.0Server' -Name Enabled,DisabledByDefault
Repeat for each key you created. On Apache, nginx or Tomcat, restore the previous directive and reload. Test in staging first and roll out by server group.
Common false positive reasons
Genuine false positives are rare because the scanner completes a real handshake. When the finding looks wrong, or Nessus 104743 is still showing after a registry change, it is almost always one of these:
- No restart: the registry is correct but IIS, RDP or SQL Server still hold old credential handles.
- Wrong key: only the Client subkey was set, or the key name is misspelled (it must be TLS 1.0Server, with a space).
- Different TLS stack: the flagged port belongs to a Java, OpenSSL or appliance-based service that ignores Schannel. If it is 3389, review your RDP hardening settings as well.
- Upstream termination: a load balancer, WAF or reverse proxy terminates TLS, so the fix belongs there.
- Default virtual host: the scanner connects by IP without SNI and reaches a default server or base vhost that still allows TLS 1.0.
- Configuration drift: a GPO, local policy or configuration management run puts the old values back.
FAQ
Do I need to reboot after changing the Schannel registry keys?
At minimum, restart every Schannel-based service, because running services reuse credential handles created under the old settings. A reboot is simplest.
Should I set Enabled = 0 or DisabledByDefault = 1?
Enabled = 0 is the value Microsoft’s current Schannel documentation describes as disabling a protocol regardless of what an application requests. DisabledByDefault = 1 is the companion value still listed in Microsoft’s .NET TLS guidance. Setting both is harmless and satisfies baselines that check for either.
Is TLS 1.0 already disabled on Windows Server 2022 or 2025?
No. Microsoft’s Schannel protocol support table shows TLS 1.0 and 1.1 enabled by default on both. The default-off change Microsoft announced applies to Insider builds from 2024 onward, not in-market versions, so you still need the explicit keys.
Does fixing TLS 1.0 also fix the TLS 1.1 finding?
No. They are separate keys and separate plugins (104743 and 157288), so disable both and verify each.
Tracking this finding across many hosts
On a large estate, the hard part is proving that every flagged port actually closed. If that is where you are, SITEY is a self-hosted vulnerability management platform that imports findings from 16 scanners (Nessus results arrive as uploaded .nessus exports) and can retest individual Nessus findings after a change. Its AI can draft host-specific remediation scripts, such as the Schannel change above, which run through agents on Windows and Linux endpoints only after a human approves them, followed by a retest to verify closure.