Introduction
Cryptography sits at the heart of secure communication. Every time you log into a server using SSH or transfer files over FTPS/SFTP, a cipher ensures your data remains protected.
But not all ciphers are equal. Some modern ciphers provide strong confidentiality and integrity, while older ones expose organisations to serious risk.

What This Article Covers
- What ciphers are used for
- How they operate in SSH and FTP
- Why older ciphers (DES, 3DES, RC4, CBC modes) are dangerous
- Real attack scenarios where weak ciphers can be exploited
- Security risks of outdated cryptography
- A Python script to check what cipher your server is actually using
What is a Cipher Used For?
A cipher is a mathematical algorithm that transforms plaintext into ciphertext and back again using encryption keys. Its core goals are:
Confidentiality
So attackers cannot read intercepted data.
Integrity
So attackers cannot alter data unnoticed.
Authenticity
So users and services trust who they’re communicating with.
Modern systems rely heavily on symmetric ciphers like AES, and asymmetric algorithms like RSA and Elliptic Curve Cryptography.
How Ciphers Are Used in SSH
SSH uses ciphers in three main phases:
1. Cipher Negotiation
The client and server exchange their supported cryptographic algorithms:
- Key exchange methods
- Host key algorithms
- Data encryption ciphers
- MAC/AEAD algorithms
Then both sides agree on one cipher suite for the session.
2. Data Encryption
Once negotiated, SSH encrypts:
- Commands
- Keystrokes
- Passwords
- File transfers (SCP/SFTP)
- Terminal output
Everything inside the SSH tunnel is encrypted.

3. Integrity Protection
SSH uses:
- AEAD modes (AES-GCM, ChaCha20-Poly1305), or
- MAC algorithms (HMAC-SHA2)
to prevent tampering and injection attacks.
How Ciphers Are Used in FTP (FTP, FTPS, and SFTP)
Traditional FTP is NOT encrypted. So two secure alternatives emerged:
FTPS (FTP over TLS)
FTPS uses TLS/SSL to protect connections, just like HTTPS.
TLS provides:
- Server authentication
- Encryption (AES-GCM, ChaCha20-Poly1305)
- Integrity protection
Both the command channel and data channel can be encrypted.
Examples of strong TLS ciphers:
- TLS_AES_256_GCM_SHA384
- ECDHE-RSA-AES128-GCM-SHA256
SFTP (SSH File Transfer Protocol)
Not related to FTP at all. It is a file-transfer protocol tunneled through SSH, so it uses SSH ciphers (AES-CTR, AES-GCM, ChaCha20-Poly1305).
SFTP inherits:
- SSH encryption
- SSH integrity protections
- SSH authentication
This makes it generally more secure and simpler to configure than FTPS.
Why Old Ciphers Are Dangerous

Many older ciphers were considered safe decades ago—but today they are broken or severely weakened.
DES / 3DES (Triple DES) – Weak Keys
Vulnerability: Too small key size
- DES uses 56-bit keys – broken by brute force long ago
- 3DES uses 112-bit effective security – borderline today
- 3DES is vulnerable to the Sweet32 attack
Real Exploitation Scenario
An attacker captures a lot of FTPS traffic using 3DES-CBC and performs a birthday attack to recover plaintext, particularly cookies or session IDs.
RC4 – Completely Broken
Vulnerability: Statistical bias
RC4 has predictable key-stream output, allowing plaintext recovery.
Real Exploitation Scenario
In a downgraded SSH or TLS connection, attacker forces RC4 and recovers your encrypted session cookies (BEAST-style attack).
CBC Mode Ciphers – Padding Oracle Attacks
CBC itself isn’t broken, but CBC in TLS/SSH is vulnerable due to:
- Padding oracle attacks
- Lucky13 attack
- POODLE-style vulnerabilities
CBC leaks information about plaintext.
Real Exploitation Scenario
An attacker intercepts FTPS/TLS traffic and uses a timing oracle to slowly decrypt encrypted traffic (Lucky13).
Export-Grade Ciphers (40-bit/56-bit) – Legacy US Regulations
Old export ciphers were intentionally weakened for export laws.
Real Exploitation Scenario
Attackers force the connection down to EXPORT ciphers via a downgrade attack (FREAK attack). Once downgraded:
- They brute force the key
- Impersonate the server
- Read all encrypted traffic
Weak Key Exchange (Diffie-Hellman Group 1 / Group 2)
DH Group 1 uses 1024-bit keys, which can be broken by modern computing power.
Real Exploitation Scenario
Attackers break DH key exchange and derive the session key, fully decrypting the SSH or FTPS session.
Security Risks of Using Outdated Ciphers
Using outdated or deprecated ciphers exposes your organisation to several risks:
1. Confidential Data Exposure
Attackers can decrypt traffic, revealing:
- Passwords
- Tokens
- PII
- Financial data
- Configuration files
2. Session Hijacking
Weak ciphers allow:
- Cookie stealing
- SSH session hijacking
- SFTP takeover
- Credential replay
3. MITM Downgrade Attacks
Attackers force a connection to fall back to a weaker cipher, then exploit it.
4. Compliance Violations
Outdated ciphers violate:
- PCI-DSS
- GDPR security requirements
- Australian Essential Eight
- CIS Benchmarks
- ISO 27001 controls
5. Increased Attack Surface
Weak crypto encourages:
- Padding oracles
- Chosen-ciphertext attacks
- Key-stream leakage
- Brute-forceable keys
What Strong Cryptography Looks Like Today
For SSH/SFTP:
- chacha20-poly1305@openssh.com
- aes256-gcm@openssh.com
- aes128-gcm@openssh.com
- aes256-ctr
For FTPS/TLS 1.2/1.3:
- TLS_AES_256_GCM_SHA384
- TLS_CHACHA20_POLY1305_SHA256
- ECDHE-RSA-AES128-GCM-SHA256
Almost all other legacy ciphers should be disabled.
Python Script to Check SSH/TLS Ciphers on a Server

Below is a Python script that detects what cipher your server is actually using.
Requires: pip install paramiko
python
#!/usr/bin/env python3
"""
Check negotiated ciphers for SSH and TLS services.
"""
import argparse
import socket
import ssl
import getpass
import paramiko
def check_ssh_cipher(host: str, port: int, username: str, password: str | None = None) -> None:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.AutoAddPolicy())
if password is None:
try:
password = getpass.getpass(f"Password for {username}@{host}: ")
except Exception:
password = None
try:
client.connect(
hostname=host,
port=port,
username=username,
password=password,
allow_agent=True,
look_for_keys=True,
timeout=10,
)
transport = client.get_transport()
remote_cipher = transport.remote_cipher
local_cipher = transport.local_cipher
print(f"[+] SSH connection established to {host}:{port}")
print(f" SSH cipher (client -> server): {remote_cipher}")
print(f" SSH cipher (server -> client): {local_cipher}")
except Exception as e:
print(f"[!] SSH connection failed: {e}")
finally:
client.close()
def check_tls_cipher(host: str, port: int) -> None:
context = ssl.create_default_context()
try:
with socket.create_connection((host, port), timeout=10) as sock:
with context.wrap_socket(sock, server_hostname=host) as ssock:
cipher, protocol, bits = ssock.cipher()
print(f"[+] TLS connection to {host}:{port}")
print(f" Protocol: {protocol}")
print(f" Cipher: {cipher} ({bits} bits)")
except Exception as e:
print(f"[!] TLS connection failed: {e}")
def main():
parser = argparse.ArgumentParser(description="Check negotiated ciphers for SSH and TLS services.")
parser.add_argument("--host", required=True, help="Target host")
parser.add_argument("--port", type=int, help="Port number")
parser.add_argument("--ssh", action="store_true", help="Check SSH cipher")
parser.add_argument("--tls", action="store_true", help="Check TLS/FTPS cipher")
parser.add_argument("--user", help="SSH username")
args = parser.parse_args()
if args.ssh:
if not args.user:
parser.error("--user is required for SSH checks")
check_ssh_cipher(args.host, args.port or 22, args.user)
if args.tls:
check_tls_cipher(args.host, args.port or 443)
if __name__ == "__main__":
main()
Security Best Practices Table
| Practice | Implementation | Benefit |
|---|---|---|
| Use AES-GCM | SSH: aes256-gcm@openssh.com TLS: TLS_AES_256_GCM_SHA384 |
Strong encryption with built-in integrity |
| Disable Weak Ciphers | Remove DES, 3DES, RC4 from config | Eliminates known vulnerabilities |
| Regular Audits | Use provided Python script monthly | Early detection of misconfigurations |
| TLS 1.3+ Only | Disable TLS 1.0/1.1 | Prevents downgrade attacks |
| Strong Key Exchange | Use ECDHE or modern DH groups | Prevents key compromise |
Final Thoughts
Ciphers are the backbone of secure communication—but only if they’re strong, modern, and correctly implemented. Outdated ciphers such as DES, 3DES, RC4, and CBC modes leave organisations vulnerable to:
- Traffic decryption
- Session hijacking
- MITM attacks
- Downgrade attacks
- Compliance issues
SSH, FTPS, and SFTP rely heavily on modern encryption to maintain confidentiality and integrity, but misconfigurations can silently undermine that protection.
With the Python script included above, you can quickly assess whether your servers are using secure ciphers—and take corrective action.
