PHP Insecure FTP Usage

Medium Risk Insecure Communication
phpftpplaintextinsecure-protocolcredentialsfile-transfer

What it is

The PHP application uses FTP protocol for file transfers, which transmits data including credentials in plaintext over the network. This vulnerability exposes sensitive information to eavesdropping and man-in-the-middle attacks, as FTP does not provide encryption.

// Vulnerable: Insecure FTP usage function uploadFileViaFtp($localFile, $remoteFile, $ftpHost, $username, $password) { // Dangerous: FTP transmits credentials and data in plaintext $ftpConnection = ftp_connect($ftpHost); if (!$ftpConnection) { throw new Exception('Could not connect to FTP server'); } // Credentials sent in plaintext if (!ftp_login($ftpConnection, $username, $password)) { ftp_close($ftpConnection); throw new Exception('FTP login failed'); } // File data transmitted unencrypted if (!ftp_put($ftpConnection, $remoteFile, $localFile, FTP_BINARY)) { ftp_close($ftpConnection); throw new Exception('File upload failed'); } ftp_close($ftpConnection); return true; } // Usage with sensitive data $result = uploadFileViaFtp('/tmp/sensitive.txt', '/remote/sensitive.txt', 'ftp.example.com', 'user', 'password');
// Secure: Using SFTP with phpseclib require_once 'vendor/autoload.php'; use phpseclib3\Net\SFTP; use phpseclib3\Crypt\PublicKeyLoader; function uploadFileViaSftp($localFile, $remoteFile, $sftpHost, $username, $privateKey) { try { // Secure: SFTP with SSH encryption $sftp = new SFTP($sftpHost); // Use key-based authentication (more secure than passwords) $key = PublicKeyLoader::load(file_get_contents($privateKey)); if (!$sftp->login($username, $key)) { throw new Exception('SFTP authentication failed'); } // Encrypted file transfer if (!$sftp->put($remoteFile, $localFile, SFTP::SOURCE_LOCAL_FILE)) { throw new Exception('SFTP upload failed'); } $sftp->disconnect(); return true; } catch (Exception $e) { error_log('SFTP error: ' . $e->getMessage()); throw new Exception('Secure file transfer failed'); } } // Alternative: Using cURL for SFTP function uploadFileViaCurlSftp($localFile, $remoteFile, $sftpHost, $username, $privateKey) { $ch = curl_init(); $url = "sftp://$sftpHost/$remoteFile"; $fp = fopen($localFile, 'r'); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_USERPWD, $username); curl_setopt($ch, CURLOPT_SSH_PRIVATE_KEYFILE, $privateKey); curl_setopt($ch, CURLOPT_UPLOAD, true); curl_setopt($ch, CURLOPT_INFILE, $fp); curl_setopt($ch, CURLOPT_INFILESIZE, filesize($localFile)); curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_SFTP); $result = curl_exec($ch); $httpCode = curl_getinfo($ch, CURLINFO_HTTP_CODE); fclose($fp); curl_close($ch); if (!$result || $httpCode !== 0) { throw new Exception('SFTP upload failed'); } return true; } // Usage with secure transfer try { $result = uploadFileViaSftp('/tmp/sensitive.txt', '/remote/sensitive.txt', 'sftp.example.com', 'user', '/path/to/private_key'); } catch (Exception $e) { error_log('Secure file transfer error: ' . $e->getMessage()); // Handle error appropriately }

💡 Why This Fix Works

See fix suggestions for detailed explanation.

Why it happens

PHP applications use the standard FTP protocol (RFC 959) implemented through ftp_connect(), ftp_login(), ftp_get(), and ftp_put() functions that transmit all data including authentication credentials, commands, and file contents in unencrypted plaintext over TCP port 21. Developers choose FTP for its simplicity, wide server support, and straightforward PHP API without understanding that FTP provides zero encryption or confidentiality protection. When applications connect to FTP servers using ftp_login($conn, $username, $password), the username and password traverse the network in cleartext visible to anyone monitoring network traffic through packet sniffers (Wireshark, tcpdump), compromised network equipment, or man-in-the-middle positions. File transfer operations using ftp_get() and ftp_put() similarly transmit complete file contents unencrypted, exposing sensitive data including database backups, configuration files containing API keys, user data exports, or business documents. Attackers positioned on the network path—compromised WiFi access points, malicious ISPs, nation-state adversaries monitoring internet backbones—can passively capture FTP traffic extracting credentials for later account access and sensitive file contents for data theft, or actively manipulate transferred files injecting malware into software updates distributed via FTP.

Root causes

Using FTP Instead of Secure Alternatives like SFTP or FTPS

PHP applications use the standard FTP protocol (RFC 959) implemented through ftp_connect(), ftp_login(), ftp_get(), and ftp_put() functions that transmit all data including authentication credentials, commands, and file contents in unencrypted plaintext over TCP port 21. Developers choose FTP for its simplicity, wide server support, and straightforward PHP API without understanding that FTP provides zero encryption or confidentiality protection. When applications connect to FTP servers using ftp_login($conn, $username, $password), the username and password traverse the network in cleartext visible to anyone monitoring network traffic through packet sniffers (Wireshark, tcpdump), compromised network equipment, or man-in-the-middle positions. File transfer operations using ftp_get() and ftp_put() similarly transmit complete file contents unencrypted, exposing sensitive data including database backups, configuration files containing API keys, user data exports, or business documents. Attackers positioned on the network path—compromised WiFi access points, malicious ISPs, nation-state adversaries monitoring internet backbones—can passively capture FTP traffic extracting credentials for later account access and sensitive file contents for data theft, or actively manipulate transferred files injecting malware into software updates distributed via FTP.

Legacy Code that Hasn't Been Updated to Use Secure Protocols

Production applications contain FTP implementations written years or decades ago when FTP was the standard file transfer protocol, before SFTP (SSH File Transfer Protocol, 1990s) and FTPS (FTP over SSL/TLS, late 1990s) became widely available and recommended. These legacy code sections persist in production systems through several factors: lack of security awareness in original development (FTP was universally accepted in 1990s/early 2000s), technical debt accumulation where security upgrades get deprioritized against new features, "if it ain't broke don't fix it" mentality treating working FTP code as low-priority for refactoring, dependency on third-party FTP servers that haven't upgraded to SFTP/FTPS requiring continued FTP support for integration, and missing documentation about security implications of FTP usage making developers unaware of the vulnerability. Migration barriers include different APIs between ftp_* functions and SFTP libraries (requiring code refactoring not simple configuration changes), server-side upgrades needed to support SFTP/FTPS that require coordination with external partners or hosting providers, testing requirements to validate secure alternatives work identically to FTP for file transfer workflows, and authentication changes from password-based FTP to key-based SSH authentication for SFTP requiring certificate management infrastructure.

Lack of Awareness About FTP Security Implications

Development teams implement FTP file transfers without understanding that FTP protocol design predates modern security requirements and provides no encryption, authentication protection, or data integrity verification. Developers believe that using FTP over private networks (corporate VPNs, internal LANs) provides sufficient security through network isolation, not recognizing that insider threats, compromised network infrastructure, or lateral movement from other breached systems can still intercept FTP traffic on supposedly private networks. The misconception that FTP passwords provide security leads developers to focus on strong password policies while ignoring that strong passwords offer no protection when transmitted in plaintext for network capture. FTP's active mode (server initiates data connections) and passive mode (client initiates data connections) complexities involving multiple TCP connections and dynamic port allocation create firewall configuration challenges that developers focus on solving, distracting from the fundamental lack of encryption. Training materials and tutorials continue showing FTP examples without security warnings, perpetuating insecure practices. Compliance frameworks (PCI DSS, HIPAA, GDPR) explicitly prohibit unencrypted transmission of sensitive data, but developers unfamiliar with these requirements unknowingly violate compliance using FTP for regulated data transfer. The gradual nature of security risks—no immediate visible problems when FTP works correctly—creates false sense of security until a breach reveals captured credentials or stolen files.

Missing Encryption for File Transfer Operations

Applications implement file transfer functionality for backup operations, data synchronization, content deployment, or user file sharing using FTP without implementing any encryption layer, leaving sensitive operational data exposed. Automated backup systems using cron jobs or scheduled tasks execute ftp_put() to transfer database dumps, application logs, or user data backups to remote servers nightly, transmitting potentially sensitive information (customer records, payment data, authentication tokens in logs) unencrypted across networks. Content Management Systems (CMS) and deployment tools use FTP to upload website files, themes, plugins, or application code to production servers, exposing source code that may contain hardcoded secrets, proprietary algorithms, or security vulnerabilities to network eavesdropping. Data integration pipelines transferring files between business systems—ERP to warehouse management, CRM to email marketing platforms, point-of-sale to accounting systems—use FTP for convenience without considering that business data (sales figures, customer lists, inventory levels) transmits without encryption. Development workflows using FTP to deploy code from local machines or CI/CD servers to staging/production environments expose application source code and configuration files. The absence of encryption extends beyond credential theft to compromise of file integrity—attackers can not only read transferred files but modify them in transit injecting backdoors into deployed code, corrupting backup data, or altering business data files without detection.

Transmitting Sensitive Files Over Unencrypted Connections

Organizations use FTP to transfer files containing regulated sensitive information—personally identifiable information (PII), protected health information (PHI), payment card data (PCI), financial records, trade secrets—violating data protection regulations and exposing data to breach risks. Healthcare applications transferring patient records, lab results, or insurance claims via FTP violate HIPAA Security Rule requirements for encryption of electronic protected health information in transit. E-commerce systems transmitting order data, customer information, or payment details via FTP violate PCI DSS requirement 4.1 mandating encryption for cardholder data transmission over open public networks. Financial services applications using FTP for transaction files, account statements, or tax documents violate banking regulations (GLBA, SOX) requiring encryption for financial data in transit. Government contractors and regulated industries (defense, critical infrastructure) using FTP for sensitive documents violate NIST SP 800-171, FISMA, or industry-specific requirements mandating encryption. The combination of FTP's plaintext transmission with sensitive data creates audit failures, compliance violations, regulatory fines (GDPR penalties up to €20 million or 4% of revenue), legal liability for data breaches, contractual violations with business partners requiring secure transmission, and reputational damage when breaches become public. Beyond regulatory compliance, ethical obligations to protect user privacy and data security make unencrypted transmission of sensitive files through FTP an irresponsible practice endangering individuals whose data is exposed to potential identity theft, financial fraud, or privacy violations.

Fixes

1

Replace FTP with SFTP (SSH File Transfer Protocol)

Migrate all FTP file transfer operations to SFTP which provides encryption, strong authentication, and data integrity protection through the SSH protocol. Install phpseclib/phpseclib library via Composer: composer require phpseclib/phpseclib providing pure PHP SFTP implementation: use phpseclib3\Net\SFTP; $sftp = new SFTP('host'); $sftp->login('user', $password); $sftp->put('remote.txt', 'local.txt', SFTP::SOURCE_LOCAL_FILE); Alternatively use PHP's SSH2 extension (requires compilation with --with-ssh2): $connection = ssh2_connect('host', 22); ssh2_auth_pubkey_file($connection, 'user', '/path/to/public_key', '/path/to/private_key'); $sftp = ssh2_sftp($connection); file_put_contents('ssh2.sftp://' . intval($sftp) . '/remote.txt', file_get_contents('local.txt')); For cURL-based SFTP: curl_setopt($ch, CURLOPT_URL, 'sftp://host/remote.txt'); curl_setopt($ch, CURLOPT_PROTOCOLS, CURLPROTO_SFTP); curl_setopt($ch, CURLOPT_SSH_PRIVATE_KEYFILE, '/path/to/key'); SFTP provides military-grade encryption (AES-256, ChaCha20-Poly1305) protecting credentials and file data from eavesdropping. Implement key-based authentication instead of passwords: generate SSH key pairs using ssh-keygen -t ed25519 -C "user@host", distribute public keys to SFTP servers, protect private keys with file permissions (chmod 600), and optionally encrypt private keys with passphrases. Configure SFTP client settings: disable outdated SSH protocol versions (only use SSHv2), verify host key fingerprints preventing man-in-the-middle attacks: $sftp->getServerPublicHostKey() compare against known_hosts, set connection timeouts, enable compression for large files. Test SFTP connectivity and performance comparing transfer speeds, validate encryption using Wireshark confirming traffic is encrypted, verify authentication methods work reliably.

2

Use FTPS (FTP over SSL/TLS) for Encrypted FTP Connections

If SFTP migration is infeasible due to server constraints, implement FTPS (FTP Secure) adding TLS/SSL encryption to FTP protocol while maintaining FTP command structure and server compatibility. Enable FTPS in PHP using ftp_ssl_connect() instead of ftp_connect(): $ftpsConn = ftp_ssl_connect('host', 21); if (!$ftpsConn) { throw new Exception('FTPS connection failed'); } ftp_login($ftpsConn, 'user', 'password'); ftp_pasv($ftpsConn, true); This establishes TLS-encrypted control connection protecting credentials and commands. Configure explicit FTPS (FTPS-E, AUTH TLS) which starts as plaintext FTP then upgrades to TLS, or implicit FTPS (FTPS-I) which uses TLS from connection start on port 990. Set ftp_pasv($conn, true) to enable passive mode avoiding firewall issues with TLS data connections. Validate that both control and data channels use encryption—some FTPS configurations encrypt control channel only, leaving file transfers unencrypted; configure ftp_set_option($ftpsConn, FTP_USEPASVADDRESS, false) if needed for NAT traversal. Server-side FTPS configuration requires SSL/TLS certificates: obtain certificates from Let's Encrypt or commercial CAs, configure FTP server (vsftpd, ProFTPD, FileZilla Server) with ssl_enable=YES, force_local_data_ssl=YES, force_local_logins_ssl=YES ensuring encryption for all operations. Test FTPS connections verifying encryption: use openssl s_client -connect host:21 -starttls ftp to inspect TLS negotiation and certificate validation. Monitor for issues: FTPS has firewall complexity requiring additional ports for data connections, some FTP clients don't support FTPS requiring client upgrades, and certificate expiration requires monitoring and renewal procedures.

3

Implement Secure File Transfer Alternatives like SCP

Use SCP (Secure Copy Protocol) based on SSH protocol for simple encrypted file transfers without the complexity of full SFTP session management. Implement SCP using PHP's ssh2 extension: $connection = ssh2_connect('host', 22); ssh2_auth_pubkey_file($connection, 'user', 'public_key', 'private_key'); ssh2_scp_send($connection, 'local.txt', '/remote/path/file.txt', 0644); for uploads, or ssh2_scp_recv($connection, '/remote/path/file.txt', 'local.txt'); for downloads. For systems without ssh2 extension, execute scp command via shell: exec('scp -i /path/to/key local.txt user@host:/remote/path/', $output, $returnCode); though this requires proper input sanitization to prevent command injection: escapeshellarg() for all user-controlled values. Use rsync over SSH for synchronization operations: exec('rsync -avz -e "ssh -i /path/to/key" /local/dir/ user@host:/remote/dir/', $output, $returnCode); providing efficient delta transfers, directory synchronization, compression, and encryption. SCP advantages include simplicity (single command for file transfer), SSH infrastructure reuse (same keys and configuration as SSH), low overhead for small files, and wide server support (any SSH server supports SCP). Disadvantages include lack of directory listing (can't browse remote files), no resume capability for interrupted transfers, and limited error reporting. For applications requiring file browsing or complex operations, use SFTP instead. Implement key management: store SSH private keys securely with restricted permissions (0600), use different keys for different environments (development, staging, production), rotate keys periodically, and implement key passphrase protection in secure key management systems (HashiCorp Vault, AWS Secrets Manager). Monitor SCP operations through logging, implement timeout settings preventing hung connections, handle errors appropriately with retry logic and alerting.

4

Use HTTPS-Based File Upload/Download Mechanisms

Replace FTP with HTTPS-based file transfer using HTTP POST/PUT for uploads and GET for downloads, leveraging existing web server infrastructure and SSL/TLS encryption. Implement server-side upload endpoint using PHP: if ($_SERVER['REQUEST_METHOD'] === 'POST' && isset($_FILES['file'])) { $uploadDir = '/secure/uploads/'; $filename = basename($_FILES['file']['name']); move_uploaded_file($_FILES['file']['tmp_name'], $uploadDir . $filename); } with authentication (Bearer tokens, API keys, OAuth), input validation (file type, size limits, virus scanning), and secure file storage. For large files, implement chunked upload: accept multipart requests processing file chunks sequentially or in parallel, track upload progress in sessions or databases, support resume capability for interrupted transfers. Client-side upload using cURL: $ch = curl_init('https://api.example.com/upload'); $file = new CURLFile('/path/to/file.txt', 'text/plain', 'file.txt'); curl_setopt($ch, CURLOPT_POST, true); curl_setopt($ch, CURLOPT_POSTFIELDS, ['file' => $file, 'token' => $apiToken]); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, true); For downloads: curl_setopt($ch, CURLOPT_URL, 'https://api.example.com/download?id=123'); curl_setopt($ch, CURLOPT_HTTPHEADER, ['Authorization: Bearer ' . $token]); Implement access control: authenticate requests, verify authorization for specific files, generate time-limited signed URLs for temporary access, log all file operations for audit trails. Use Content-Disposition headers for download filenames: header('Content-Disposition: attachment; filename="' . basename($file) . '"'); HTTPS advantages include: reuse of existing web infrastructure, familiar HTTP semantics, built-in authentication mechanisms (HTTP Basic, OAuth, JWT), integration with CDNs for global distribution, and browser compatibility for user-facing uploads. Consider implementing resumable uploads using protocols like TUS (tus.io) or custom range request handling for large files. Monitor transfer performance, implement rate limiting preventing abuse, validate content types preventing malicious file uploads.

5

Ensure All File Transfers Use Encryption

Audit entire codebase and infrastructure for unencrypted file transfer protocols (FTP, HTTP, Telnet, rsh/rcp) and systematically migrate to encrypted alternatives. Create comprehensive inventory: grep codebase for ftp_connect, ftp_login identifying FTP usage; search for http:// URLs in file transfer contexts; review cron jobs, scheduled tasks, and automation scripts for file transfer commands; examine third-party integrations for protocol usage; inventory file transfer dependencies and libraries. For each identified usage, assess: data sensitivity (does transfer include PII, credentials, proprietary data?), compliance requirements (HIPAA, PCI DSS, GDPR regulations), network path (crosses internet, private network, or localhost), frequency (one-time migration vs. regular automated transfers), and available secure alternatives on both client and server sides. Implement encryption migration plan: prioritize highest risk transfers (sensitive data over internet) for immediate remediation, schedule medium risk transfers (private networks) for near-term migration, plan low risk transfers (localhost) for eventual upgrade. Document migration for each transfer: old protocol and new protocol, authentication changes (passwords to keys), code modifications required, testing procedures, rollback plans. Configure enforcement: disable FTP services on servers (shutdown vsftpd, disable FTP in hosting control panels), implement network firewall rules blocking outbound FTP connections (port 21, 20), use security scanning tools (nmap, vulnerability scanners) detecting FTP services on your infrastructure, implement static code analysis rejecting commits with ftp_* function usage. Verify encryption: use protocol analyzers (Wireshark) confirming transferred data is encrypted not plaintext, test with invalid certificates verifying proper certificate validation, perform penetration testing attempting to intercept file transfers. Monitor ongoing: log all file transfer operations including protocol used, alert on unencrypted transfer attempts, review third-party vendor protocols during procurement and security reviews.

6

Consider Cloud Storage APIs for Secure File Operations

Migrate file transfer workflows to cloud storage services (AWS S3, Google Cloud Storage, Azure Blob Storage) providing built-in encryption, authentication, access control, and audit logging eliminating need for FTP/SFTP server management. For AWS S3: use AWS SDK for PHP composer require aws/aws-sdk-php; $s3 = new Aws\S3\S3Client(['version' => 'latest', 'region' => 'us-east-1', 'credentials' => ['key' => $accessKey, 'secret' => $secretKey]]); $s3->putObject(['Bucket' => 'bucket', 'Key' => 'file.txt', 'SourceFile' => '/path/to/local.txt', 'ServerSideEncryption' => 'AES256']); All S3 transfers use HTTPS encryption, supports server-side encryption (SSE-S3, SSE-KMS), provides IAM-based access control, versioning, lifecycle policies, and CloudTrail audit logs. For Google Cloud Storage: $storage = new Google\Cloud\Storage\StorageClient(['keyFilePath' => '/path/to/service-account.json']); $bucket = $storage->bucket('bucket-name'); $bucket->upload(fopen('/path/to/file.txt', 'r'), ['name' => 'file.txt', 'predefinedAcl' => 'private']); supports customer-managed encryption keys, VPC Service Controls, detailed access logs. For Azure Blob Storage: $blobClient = BlobRestProxy::createBlobService($connectionString); $blobClient->createBlockBlob('container', 'blob-name', $content); provides encryption at rest, Azure AD authentication, RBAC, immutable storage. Implement access patterns: generate pre-signed URLs for time-limited file access without credentials, use SDK direct uploads from browsers reducing server load, implement multipart uploads for large files (>100MB), enable versioning for file history and recovery. Configure security: enable encryption in transit and at rest, implement bucket policies restricting public access, use IAM roles for service authentication instead of long-lived access keys, enable MFA delete for critical buckets, configure CORS policies for browser uploads, implement lifecycle policies automatically deleting old files. Monitor usage: enable access logging, set up alerts for unusual access patterns, implement cost monitoring preventing bill shock from excessive transfers. Cloud storage advantages: no server management (fully managed services), built-in redundancy and availability, global CDN integration, unlimited scalability, compliance certifications (SOC2, ISO 27001, HIPAA), automatic encryption, detailed audit trails, and pay-per-use pricing often cheaper than dedicated FTP/SFTP infrastructure.

Detect This Vulnerability in Your Code

Sourcery automatically identifies php insecure ftp usage and many other security issues in your codebase.