JAVA.SV.EMAIL.HOST
在不验证的情况下将电子邮件发送到主机。
若要建立不容易受到中间人攻击的 SSL/TLS 连接,必须确保服务器提供正确的证书。证书的特定于主机名的数据需要与服务器主机名相匹配。TLS/SSL 库提供应该使用的内置主机名验证函数。
JAVA.SV.EMAIL.HOST 检查器会标记
-
在未将 mail.smtp.ssl.checkserveridentity 属性或 mail.smtps.ssl.checkserveridentity 属性配置为 true 的情况下创建 JavaMail javax.mail.Session 会话的情况。
-
Apache Common Email org.apache.commons.mail.SimpleEmail 类与 setSSLOnConnect(true)、setStartTLSEnabled(true) 或 setStartTLSRequired(true) 一起使用,没有调用 setSSLCheckServerIdentity(true)。
漏洞与风险
如果不验证主机名服务器的有效性,便会创建容易受到中间人攻击的连接。
缓解与预防
应始终验证主机名服务器的有效性。
漏洞代码示例 1
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 在第 19 行报告了 JAVA.SV.EMAIL.HOST 缺陷,指出“应该在发送电子邮件之前完成主机验证”。
修正代码示例 1
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;
}
}
在此修正示例中,Klocwork 不再报告 JAVA.SV.EMAIL.HOST 缺陷,因为 mail.smtp.ssl.checkserveridentity 属性已设为 true。
漏洞代码示例 2
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 在第 18 行报告了 JAVA.SV.EMAIL.HOST 缺陷,指出“应该在发送电子邮件之前完成主机验证”。
修正代码示例 2
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();
}
}
在此修正示例中,Klocwork 不再报告 JAVA.SV.EMAIL.HOST 缺陷,因为 setSSLCheckServerIdentity 已设为 true。