mirror of
https://github.com/github/codeql.git
synced 2025-12-17 01:03:14 +01:00
Merge pull request #4814 from luchua-bc/java/password-in-configuration
Java: Password in Java EE configuration files
This commit is contained in:
@@ -0,0 +1,40 @@
|
|||||||
|
<!DOCTYPE qhelp PUBLIC "-//Semmle//qhelp//EN" "qhelp.dtd">
|
||||||
|
<qhelp>
|
||||||
|
<overview>
|
||||||
|
<p>
|
||||||
|
Storing a plaintext password in a configuration file allows anyone who can read the file to access the password-protected resources.
|
||||||
|
</p>
|
||||||
|
</overview>
|
||||||
|
|
||||||
|
<recommendation>
|
||||||
|
<p>
|
||||||
|
Passwords stored in configuration files should be encrypted. Utilities provided by application servers like keystore and password vault can be used to encrypt and manage passwords.
|
||||||
|
</p>
|
||||||
|
</recommendation>
|
||||||
|
|
||||||
|
<example>
|
||||||
|
<p>
|
||||||
|
In the first example, the password of a datasource configuration is stored in cleartext in the context.xml file of a Java EE application.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<p>
|
||||||
|
In the second example, the password of a datasource configuration is encrypted and managed by a password vault.
|
||||||
|
</p>
|
||||||
|
<sample src="context.xml" />
|
||||||
|
</example>
|
||||||
|
|
||||||
|
<references>
|
||||||
|
<li>
|
||||||
|
CWE:
|
||||||
|
<a href="https://cwe.mitre.org/data/definitions/555.html">CWE-555: J2EE Misconfiguration: Plaintext Password in Configuration File</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
RedHat Security Guide:
|
||||||
|
<a href="https://access.redhat.com/documentation/en-us/jboss_enterprise_application_platform/6.1/html/security_guide/Store_and_Retrieve_Encrypted_Sensitive_Strings_in_the_Java_Keystore">Store and Retrieve Encrypted Sensitive Strings in the Java Keystore</a>
|
||||||
|
</li>
|
||||||
|
<li>
|
||||||
|
SonarSource:
|
||||||
|
<a href="https://rules.sonarsource.com/java/RSPEC-2068">Hard-coded credentials are security-sensitive</a>
|
||||||
|
</li>
|
||||||
|
</references>
|
||||||
|
</qhelp>
|
||||||
@@ -0,0 +1,49 @@
|
|||||||
|
/**
|
||||||
|
* @name Password in configuration file
|
||||||
|
* @description Finds passwords in configuration files.
|
||||||
|
* @kind problem
|
||||||
|
* @id java/password-in-configuration
|
||||||
|
* @tags security
|
||||||
|
* external/cwe/cwe-555
|
||||||
|
* external/cwe/cwe-256
|
||||||
|
* external/cwe/cwe-260
|
||||||
|
*/
|
||||||
|
|
||||||
|
import java
|
||||||
|
|
||||||
|
/** Holds if the attribute value is not a cleartext password */
|
||||||
|
bindingset[value]
|
||||||
|
predicate isNotPassword(string value) {
|
||||||
|
value = "" // Empty string
|
||||||
|
or
|
||||||
|
value.regexpMatch("\\$\\{.*\\}") // Variable placeholder ${password}
|
||||||
|
or
|
||||||
|
value.matches("%=") // A basic check of encrypted passwords ending with padding characters, which could be improved to be more accurate.
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Holds if the attribute value has an embedded password */
|
||||||
|
bindingset[value]
|
||||||
|
predicate hasEmbeddedPassword(string value) {
|
||||||
|
exists(string password |
|
||||||
|
password = value.regexpCapture("(?is).*(pwd|password)\\s*=([^;:,]*).*", 2).trim() and
|
||||||
|
not isNotPassword(password)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
from XMLAttribute nameAttr
|
||||||
|
where
|
||||||
|
nameAttr.getName().toLowerCase() in ["password", "pwd"] and
|
||||||
|
not isNotPassword(nameAttr.getValue().trim()) // Attribute name "password" or "pwd"
|
||||||
|
or
|
||||||
|
exists(
|
||||||
|
XMLAttribute valueAttr // name/value pair like <property name="password" value="mysecret"/>
|
||||||
|
|
|
||||||
|
valueAttr.getElement() = nameAttr.getElement() and
|
||||||
|
nameAttr.getName().toLowerCase() = "name" and
|
||||||
|
nameAttr.getValue().toLowerCase() in ["password", "pwd"] and
|
||||||
|
valueAttr.getName().toLowerCase() = "value" and
|
||||||
|
not isNotPassword(valueAttr.getValue().trim())
|
||||||
|
)
|
||||||
|
or
|
||||||
|
hasEmbeddedPassword(nameAttr.getValue().trim()) // Attribute value matches password pattern
|
||||||
|
select nameAttr, "Plaintext password in configuration file."
|
||||||
17
java/ql/src/experimental/Security/CWE/CWE-555/context.xml
Normal file
17
java/ql/src/experimental/Security/CWE/CWE-555/context.xml
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Context>
|
||||||
|
<!-- BAD: Password of datasource is not encrypted -->
|
||||||
|
<Resource name="jdbc/exampleDS" auth="Container" type="javax.sql.DataSource"
|
||||||
|
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
|
||||||
|
username="root" password="1234"
|
||||||
|
driverClassName="com.mysql.jdbc.Driver"
|
||||||
|
url="jdbc:mysql://www.example.com:3306/proj"/>
|
||||||
|
|
||||||
|
<!-- GOOD: Password is encrypted and stored in a password vault -->
|
||||||
|
<Resource name="jdbc/exampleDS" auth="Container" type="javax.sql.DataSource"
|
||||||
|
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
|
||||||
|
username="root" password="${VAULT::exampleDS::password::N2NhZDYzOTMtNWE0OS00ZGQ0LWE4MmEtMWNlMDMyNDdmNmI2TElORV9CUkVBS3ZhdWx0}"
|
||||||
|
driverClassName="com.mysql.jdbc.Driver"
|
||||||
|
url="jdbc:mysql://www.example.com:3306/proj"/>
|
||||||
|
|
||||||
|
</Context>
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
| applicationContext.xml:9:3:9:48 | name=password | Plaintext password in configuration file. |
|
||||||
|
| context.xml:4:2:8:50 | password=1234 | Plaintext password in configuration file. |
|
||||||
|
| custom-config.xml:3:2:3:137 | value=server=myoracle.example.com;port=1521;database=testdb;username=root;password=test1234 | Plaintext password in configuration file. |
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
experimental/Security/CWE/CWE-555/PasswordInConfigurationFile.ql
|
||||||
@@ -0,0 +1,37 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://www.springframework.org/schema/beans
|
||||||
|
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd">
|
||||||
|
|
||||||
|
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource" destroy-method="close">
|
||||||
|
<property name="driverClassName" value="com.mysql.jdbc.Driver" />
|
||||||
|
<property name="url" value="jdbc:mysql://www.example.com:3306/test" />
|
||||||
|
<property name="username" value="root" />
|
||||||
|
<property name="password" value="mysecret" />
|
||||||
|
<property name="initialSize" value="30" />
|
||||||
|
|
||||||
|
<property name="maxActive" value="500" />
|
||||||
|
<property name="maxIdle" value="2" />
|
||||||
|
<property name="minIdle" value="1" />
|
||||||
|
</bean>
|
||||||
|
|
||||||
|
<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
|
||||||
|
<property name="dataSource" ref="dataSource" />
|
||||||
|
|
||||||
|
<property name="annotatedClasses">
|
||||||
|
<list>
|
||||||
|
<value>com.example.entity.Users</value>
|
||||||
|
</list>
|
||||||
|
</property>
|
||||||
|
|
||||||
|
<property name="hibernateProperties">
|
||||||
|
<value>
|
||||||
|
hibernate.dialect=org.hibernate.dialect.MySQLDialect
|
||||||
|
hibernate.hbm2ddl.auto=update
|
||||||
|
hibernate.show_sql=true
|
||||||
|
hibernate.cache.use_second_level_cache=false
|
||||||
|
hibernate.cache.provider_class=org.hibernate.cache.internal.NoCacheProvider
|
||||||
|
hibernate.generate_statistics=true
|
||||||
|
</value>
|
||||||
|
</property>
|
||||||
|
</bean>
|
||||||
|
</beans>
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<Context>
|
||||||
|
<!-- BAD: Password of datasource is in not encrypted -->
|
||||||
|
<Resource name="jdbc/exampleDS1" auth="Container" type="javax.sql.DataSource"
|
||||||
|
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
|
||||||
|
username="root" password="1234"
|
||||||
|
driverClassName="com.mysql.jdbc.Driver"
|
||||||
|
url="jdbc:mysql://www.example1.com:3306/proj"/>
|
||||||
|
|
||||||
|
<!-- GOOD: Password is encrypted and stored in a password vault -->
|
||||||
|
<Resource name="jdbc/exampleDS2" auth="Container" type="javax.sql.DataSource"
|
||||||
|
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
|
||||||
|
username="root" password="${VAULT::exampleDS2::password::N2NhZDYzOTMtNWE0OS00ZGQ0LWE4MmEtMWNlMDMyNDdmNmI2TElORV9CUkVBS3ZhdWx0}"
|
||||||
|
driverClassName="com.mysql.jdbc.Driver"
|
||||||
|
url="jdbc:mysql://www.example2.com:3306/proj"/>
|
||||||
|
|
||||||
|
<!-- GOOD: Password is not stored in the configuration file -->
|
||||||
|
<Resource name="jdbc/exampleDS3" auth="Container" type="javax.sql.DataSource"
|
||||||
|
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
|
||||||
|
username="root" password="${jdbc.password}"
|
||||||
|
driverClassName="com.mysql.jdbc.Driver"
|
||||||
|
url="jdbc:mysql://www.example3.com:3306/proj"/>
|
||||||
|
|
||||||
|
<!-- GOOD: Password is encrypted -->
|
||||||
|
<Resource name="jdbc/exampleDS4" auth="Container" type="javax.sql.DataSource"
|
||||||
|
maxTotal="100" maxIdle="30" maxWaitMillis="10000"
|
||||||
|
username="root" password="Tg2Nn7wUZOQ6Xc+1lenkZTQ9ZDf9a2/RBRiqJBCIX6o="
|
||||||
|
driverClassName="com.mysql.jdbc.Driver"
|
||||||
|
url="jdbc:mysql://www.example4.com:3306/proj"/>
|
||||||
|
</Context>
|
||||||
@@ -0,0 +1,4 @@
|
|||||||
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
|
<db-connections>
|
||||||
|
<db-connection name="oracleServerConn" value="server=myoracle.example.com;port=1521;database=testdb;username=root;password=test1234" />
|
||||||
|
</db-connections>
|
||||||
Reference in New Issue
Block a user