mirror of
https://github.com/github/codeql.git
synced 2025-12-24 04:36:35 +01:00
Move from experimental
This commit is contained in:
27
java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp
Normal file
27
java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.qhelp
Normal file
@@ -0,0 +1,27 @@
|
||||
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||
<qhelp>
|
||||
|
||||
<overview>
|
||||
<p>JavaMail is commonly used in Java applications to send emails. There are popular third-party libraries like Apache Commons Email which are built on JavaMail and facilitate integration. Authenticated mail sessions require user credentials and mail sessions can require SSL/TLS authentication. It is a common security vulnerability that host-specific certificate data is not validated or is incorrectly validated. Failing to validate the certificate makes the SSL session susceptible to a man-in-the-middle attack.</p>
|
||||
<p>This query checks whether SSL certificate is validated when username/password is sent in authenticator and when SSL is enabled.</p>
|
||||
<p>The query has code for both plain JavaMail invocation and mailing through Apache SimpleMail to make it more comprehensive.</p>
|
||||
</overview>
|
||||
|
||||
<recommendation>
|
||||
<p>Validate SSL certificate when sensitive information is sent in email communications.</p>
|
||||
</recommendation>
|
||||
|
||||
<example>
|
||||
<p>The following two examples show two ways of configuring secure emails through JavaMail or Apache SimpleMail. In the 'BAD' case,
|
||||
credentials are sent in an SSL session without certificate validation. In the 'GOOD' case, the certificate is validated.</p>
|
||||
<sample src="JavaMail.java" />
|
||||
<sample src="SimpleMail.java" />
|
||||
</example>
|
||||
|
||||
<references>
|
||||
<li>
|
||||
Log4j2:
|
||||
<a href="https://issues.apache.org/jira/browse/LOG4J2-2819">Add support for specifying an SSL configuration for SmtpAppender (CVE-2020-9488)</a>
|
||||
</li>
|
||||
</references>
|
||||
</qhelp>
|
||||
107
java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql
Normal file
107
java/ql/src/Security/CWE/CWE-297/InsecureJavaMail.ql
Normal file
@@ -0,0 +1,107 @@
|
||||
/**
|
||||
* @name Insecure JavaMail SSL Configuration
|
||||
* @description Java application configured to use authenticated mail session
|
||||
* over SSL does not validate the SSL certificate to properly
|
||||
* ensure that it is actually associated with that host.
|
||||
* @kind problem
|
||||
* @problem.severity warning
|
||||
* @precision medium
|
||||
* @id java/insecure-smtp-ssl
|
||||
* @tags security
|
||||
* external/cwe/cwe-297
|
||||
*/
|
||||
|
||||
import java
|
||||
|
||||
/**
|
||||
* The method to set Java properties
|
||||
*/
|
||||
class SetPropertyMethod extends Method {
|
||||
SetPropertyMethod() {
|
||||
this.hasName("setProperty") and
|
||||
this.getDeclaringType().hasQualifiedName("java.util", "Properties")
|
||||
or
|
||||
this.hasName("put") and
|
||||
this.getDeclaringType().getASourceSupertype*().hasQualifiedName("java.util", "Dictionary")
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The insecure way to set Java properties in mail sessions.
|
||||
* 1. Set the mail.smtp.auth property to provide the SMTP Transport with a username and password when connecting to the SMTP server or
|
||||
* set the mail.smtp.ssl.socketFactory/mail.smtp.ssl.socketFactory.class property to create an SMTP SSL socket.
|
||||
* 2. No mail.smtp.ssl.checkserveridentity property is enabled.
|
||||
*/
|
||||
predicate isInsecureMailPropertyConfig(VarAccess propertiesVarAccess) {
|
||||
exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof SetPropertyMethod and
|
||||
ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() and
|
||||
(
|
||||
getStringValue(ma.getArgument(0)).matches("%.auth%") and //mail.smtp.auth
|
||||
getStringValue(ma.getArgument(1)) = "true"
|
||||
or
|
||||
getStringValue(ma.getArgument(0)).matches("%.socketFactory%") //mail.smtp.socketFactory or mail.smtp.socketFactory.class
|
||||
)
|
||||
) and
|
||||
not exists(MethodAccess ma |
|
||||
ma.getMethod() instanceof SetPropertyMethod and
|
||||
ma.getQualifier() = propertiesVarAccess.getVariable().getAnAccess() and
|
||||
(
|
||||
getStringValue(ma.getArgument(0)).matches("%.ssl.checkserveridentity%") and //mail.smtp.ssl.checkserveridentity
|
||||
getStringValue(ma.getArgument(1)) = "true"
|
||||
)
|
||||
)
|
||||
}
|
||||
|
||||
/**
|
||||
* Helper method to get string value of an argument
|
||||
*/
|
||||
string getStringValue(Expr expr) {
|
||||
result = expr.(CompileTimeConstantExpr).getStringValue()
|
||||
or
|
||||
result = getStringValue(expr.(AddExpr).getLeftOperand())
|
||||
or
|
||||
result = getStringValue(expr.(AddExpr).getRightOperand())
|
||||
}
|
||||
|
||||
/**
|
||||
* The JavaMail session class `javax.mail.Session`
|
||||
*/
|
||||
class MailSession extends RefType {
|
||||
MailSession() { this.hasQualifiedName("javax.mail", "Session") }
|
||||
}
|
||||
|
||||
/**
|
||||
* The class of Apache SimpleMail
|
||||
*/
|
||||
class SimpleMail extends RefType {
|
||||
SimpleMail() { this.hasQualifiedName("org.apache.commons.mail", "SimpleEmail") }
|
||||
}
|
||||
|
||||
/**
|
||||
* Has TLS/SSL enabled with SimpleMail
|
||||
*/
|
||||
predicate enableTLSWithSimpleMail(MethodAccess ma) {
|
||||
ma.getMethod().hasName("setSSLOnConnect") and
|
||||
ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true
|
||||
}
|
||||
|
||||
/**
|
||||
* Has no certificate check
|
||||
*/
|
||||
predicate hasNoCertCheckWithSimpleMail(VarAccess va) {
|
||||
not exists(MethodAccess ma |
|
||||
ma.getQualifier() = va.getVariable().getAnAccess() and
|
||||
ma.getMethod().hasName("setSSLCheckServerIdentity") and
|
||||
ma.getArgument(0).(BooleanLiteral).getBooleanValue() = true
|
||||
)
|
||||
}
|
||||
|
||||
from MethodAccess ma
|
||||
where
|
||||
ma.getMethod().getDeclaringType() instanceof MailSession and
|
||||
ma.getMethod().getName() = "getInstance" and
|
||||
isInsecureMailPropertyConfig(ma.getArgument(0))
|
||||
or
|
||||
enableTLSWithSimpleMail(ma) and hasNoCertCheckWithSimpleMail(ma.getQualifier())
|
||||
select ma, "Java mailing has insecure SSL configuration"
|
||||
43
java/ql/src/Security/CWE/CWE-297/JavaMail.java
Normal file
43
java/ql/src/Security/CWE/CWE-297/JavaMail.java
Normal file
@@ -0,0 +1,43 @@
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.activation.DataSource;
|
||||
import javax.mail.Authenticator;
|
||||
import javax.mail.Message;
|
||||
import javax.mail.MessagingException;
|
||||
import javax.mail.PasswordAuthentication;
|
||||
import javax.mail.Session;
|
||||
|
||||
import org.apache.logging.log4j.util.PropertiesUtil;
|
||||
|
||||
class JavaMail {
|
||||
public static void main(String[] args) {
|
||||
// BAD: Don't have server certificate check
|
||||
{
|
||||
final Properties properties = PropertiesUtil.getSystemProperties();
|
||||
properties.put("mail.transport.protocol", "protocol");
|
||||
properties.put("mail.smtp.host", "hostname");
|
||||
properties.put("mail.smtp.socketFactory.class", "classname");
|
||||
|
||||
final Authenticator authenticator = buildAuthenticator("username", "password");
|
||||
if (null != authenticator) {
|
||||
properties.put("mail.smtp.auth", "true");
|
||||
}
|
||||
final Session session = Session.getInstance(properties, authenticator);
|
||||
}
|
||||
|
||||
// GOOD: Have server certificate check
|
||||
{
|
||||
final Properties properties = PropertiesUtil.getSystemProperties();
|
||||
properties.put("mail.transport.protocol", "protocol");
|
||||
properties.put("mail.smtp.host", "hostname");
|
||||
properties.put("mail.smtp.socketFactory.class", "classname");
|
||||
|
||||
final Authenticator authenticator = buildAuthenticator("username", "password");
|
||||
if (null != authenticator) {
|
||||
properties.put("mail.smtp.auth", "true");
|
||||
properties.put("mail.smtp.ssl.checkserveridentity", "true");
|
||||
}
|
||||
final Session session = Session.getInstance(properties, authenticator);
|
||||
}
|
||||
}
|
||||
}
|
||||
40
java/ql/src/Security/CWE/CWE-297/SimpleMail.java
Normal file
40
java/ql/src/Security/CWE/CWE-297/SimpleMail.java
Normal file
@@ -0,0 +1,40 @@
|
||||
import org.apache.commons.mail.DefaultAuthenticator;
|
||||
import org.apache.commons.mail.Email;
|
||||
import org.apache.commons.mail.EmailException;
|
||||
import org.apache.commons.mail.SimpleEmail;
|
||||
|
||||
class SimpleMail {
|
||||
public static void main(String[] args) throws EmailException {
|
||||
// BAD: Don't have setSSLCheckServerIdentity set or set as false
|
||||
{
|
||||
Email email = new SimpleEmail();
|
||||
email.setHostName("hostName");
|
||||
email.setSmtpPort(25);
|
||||
email.setAuthenticator(new DefaultAuthenticator("username", "password"));
|
||||
email.setSSLOnConnect(true);
|
||||
|
||||
//email.setSSLCheckServerIdentity(false);
|
||||
email.setFrom("fromAddress");
|
||||
email.setSubject("subject");
|
||||
email.setMsg("body");
|
||||
email.addTo("toAddress");
|
||||
email.send();
|
||||
}
|
||||
|
||||
// GOOD: Have setSSLCheckServerIdentity set to true
|
||||
{
|
||||
Email email = new SimpleEmail();
|
||||
email.setHostName("hostName");
|
||||
email.setSmtpPort(25);
|
||||
email.setAuthenticator(new DefaultAuthenticator("username", "password"));
|
||||
email.setSSLOnConnect(true);
|
||||
|
||||
email.setSSLCheckServerIdentity(true);
|
||||
email.setFrom("fromAddress");
|
||||
email.setSubject("subject");
|
||||
email.setMsg("body");
|
||||
email.addTo("toAddress");
|
||||
email.send();
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user