JAVA.SV.EMAIL.HOST

Sending e-mails to Host without validation.

To establish an SSL/TLS connection that is not vulnerable to man-in-the-middle attacks, you must ensure that the server presents the correct certificate. The certificate’s hostname-specific data needs to match the server hostname. TLS/SSL libraries provide built-in hostname verification functions that should be used.

The JAVA.SV.EMAIL.HOST checker flags cases where

  • a JavaMail javax.mail.Session session is created without a mail.smtp.ssl.checkserveridentity property or a mail.smtps.ssl.checkserveridentity property configured to true.

  • an Apache Common Email org.apache.commons.mail.SimpleEmail class is used with setSSLOnConnect(true), setStartTLSEnabled(true), or setStartTLSRequired(true) and there is no call to setSSLCheckServerIdentity(true).

Vulnerability and risk

If you do not verify the validity of the hostname server, you create connections that are vulnerable to man-in-the-middle attacks.

Mitigation and prevention

Always verify the validity of the hostname server.

Vulnerable code example 1

Copy

import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import java.io.IOException;
import java.util.Properties;


public class JavaEmailHostSecured {

    public Session getEmailSession(String args[]) throws IOException {
        Properties props = new Properties();
        String username = "username@gmail.com", password = "password";
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory");  // Noncompliant; Session is created without having "mail.smtp.ssl.checkserveridentity" set to true
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");
        Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
        return session;
    }
}

Klocwork reports a JAVA.SV.EMAIL.HOST defect on line 19, indicating, "Host validation should be done before sending e-mails."

Fixed code example 1

Copy
import javax.mail.PasswordAuthentication;
import javax.mail.Session;
import java.io.IOException;
import java.util.Properties;


public class JavaEmailHostSecured {

    public Session getEmailSession(String args[]) throws IOException {
        Properties props = new Properties();
        String username = "username@gmail.com", password = "password";
        props.put("mail.smtp.host", "smtp.gmail.com");
        props.put("mail.smtp.socketFactory.port", "465");
        props.put("mail.smtp.socketFactory.class", "javax.net.ssl.SSLSocketFactory")
        props.put("mail.smtp.auth", "true");
        props.put("mail.smtp.port", "465");
        props.put("mail.smtp.ssl.checkserveridentity", true); // Compliant
        Session session = Session.getDefaultInstance(props, new javax.mail.Authenticator() {
            protected PasswordAuthentication getPasswordAuthentication() {
                return new PasswordAuthentication(username, password);
            }
        });
        return session;
    }
}

In this fixed example, Klocwork no longer reports a JAVA.SV.EMAIL.HOST defect because the mail.smtp.ssl.checkserveridentity property is set to true.

Vulnerable code example 2

Copy
import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;

import java.io.IOException;

public class SimpleEmailHost {

    public void sendEmail() throws IOException, EmailException {
        String username = "username@gmail.com", password = "password";
        Email email = new SimpleEmail();
        email.setSmtpPort(465);
        email.setAuthenticator(new DefaultAuthenticator(username, password));
        email.setSSLOnConnect(true); // Noncompliant; 
        email.setStartTLSEnabled(true);// Noncompliant;
        email.setStartTLSRequired(true);// Noncompliant; setSSLCheckServerIdentity(true) should also be called before sending the email
        email.send();
    }
}

Klocwork reports a JAVA.SV.EMAIL.HOST defect on line 18, indicating, "Host validation should be done before sending e-mails."

Fixed code example 2

Copy
import org.apache.commons.mail.DefaultAuthenticator;
import org.apache.commons.mail.Email;
import org.apache.commons.mail.EmailException;
import org.apache.commons.mail.SimpleEmail;

import java.io.IOException;

public class SimpleEmailHost {

    public void sendEmail() throws IOException, EmailException {
        String username = "username@gmail.com", password = "password";
        Email email = new SimpleEmail();
        email.setSmtpPort(465);
        email.setAuthenticator(new DefaultAuthenticator(username, password));
        email.setSSLOnConnect(true)
        email.setStartTLSEnabled(true);
        email.setStartTLSRequired(true);
        email.setSSLCheckServerIdentity(true); // Compliant
        email.send();
    }
}

In this fixed example, Klocwork no longer reports a JAVA.SV.EMAIL.HOST defect because setSSLCheckServerIdentity is set to true.

Related checkers

Security training

Application security training materials provided by Secure Code Warrior.