严重等级:高危
缺陷详解:
在构建数据驱动的应用程序时,开发者通常需要通过数据库连接字符串与数据库进行交互。将敏感信息(如密码、服务器IP地址或加密密钥)硬编码在源代码中会带来以下风险:
- 信息暴露:硬编码的密码、IP地址或密钥可能被反编译工具提取,从而被攻击者利用。
- 代码维护困难:调试和生产环境的配置不同,每次环境切换都需要手动修改代码和重新编译,增加维护成本。
- 法律后果:敏感信息的泄露可能违反行业法规,如 ITAR(国际武器贸易条例)或 HIPAA(健康保险流通与责任法案),引发法律责任。
- 易受攻击:如果恶意用户获得了源代码或类文件,他们可以直接读取硬编码的信息,绕过其他安全机制。
导致结果和风险:
- 硬编码的敏感信息容易被攻击者利用,导致数据泄露或未经授权的访问。
- 敏感数据泄露可能影响企业的合规性,带来法律和声誉风险。
缓解和预防措施:
- 配置外部化:将数据库连接信息从代码中分离出来,存储在加密的配置文件、环境变量或专用的密钥管理系统中。
- 加密存储:敏感信息应加密存储,并在运行时通过安全机制解密。
- 访问控制:确保敏感配置文件或密钥管理系统的访问权限受到严格控制。
- 最小权限原则:数据库账户应设置为只具有最低限度的操作权限,避免因密码泄露导致更大范围的风险。
测试用例
修复前的测试用例(存在漏洞):
import java.sql.Connection;
import java.sql.DriverManager;
public class HardcodedPasswordExample {
public static void main(String[] args) {
try {
// 在代码中硬编码数据库连接字符串,包括用户名和密码
String url = "jdbc:mysql://prod.company.com/production";
String username = "root";
String password = "lamepassword"; // 硬编码的密码
// 使用硬编码信息连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println("数据库连接成功!");
} catch (Exception e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
}
}
漏洞分析:
- 问题:数据库连接的敏感信息直接硬编码在程序中,易被反编译工具提取。
- 风险:攻击者可通过代码或编译文件直接获取敏感信息,访问数据库。
修复后的测试用例(安全实现):
import java.sql.Connection;
import java.sql.DriverManager;
import java.util.Properties;
import java.nio.file.Files;
import java.nio.file.Paths;
public class SecurePasswordExample {
public static void main(String[] args) {
try {
// 从外部配置文件加载数据库连接信息
Properties props = new Properties();
props.load(Files.newInputStream(Paths.get("config.properties")));
// 从配置文件中读取连接字符串、用户名和密码
String url = props.getProperty("db.url");
String username = props.getProperty("db.username");
String password = props.getProperty("db.password");
// 使用安全加载的配置信息连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println("数据库连接成功!");
} catch (Exception e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
}
}
修复点:
- 将敏感信息存储在 外部加密配置文件(如 config.properties)中,而非硬编码。
- 配置文件的访问权限受到严格控制,防止未授权访问。
示例配置文件(config.properties):
db.url=jdbc:mysql://prod.company.com/production
db.username=root
db.password=securepassword123
补充测试用例:
1. 使用环境变量存储密码:
public class EnvVariableExample {
public static void main(String[] args) {
try {
// 从环境变量中加载敏感信息
String url = System.getenv("DB_URL");
String username = System.getenv("DB_USERNAME");
String password = System.getenv("DB_PASSWORD");
// 使用环境变量连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println("数据库连接成功!");
} catch (Exception e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
}
}
2. 使用密钥管理系统:
public class SecureKeyManagementExample {
public static void main(String[] args) {
try {
// 从密钥管理系统加载敏感信息
String url = SecretManager.get("db.url");
String username = SecretManager.get("db.username");
String password = SecretManager.get("db.password");
// 使用密钥管理系统的值连接数据库
Connection connection = DriverManager.getConnection(url, username, password);
System.out.println("数据库连接成功!");
} catch (Exception e) {
System.out.println("数据库连接失败!");
e.printStackTrace();
}
}
}
漏洞修复后的优势:
- 密钥管理系统和环境变量保护了敏感信息,降低被暴露的风险。
- 数据库连接信息的动态管理提升了代码可维护性。
参考:
- CWE-259: Use of Hard-coded Password
- OWASP Top Ten: A3-Sensitive Data Exposure
工作:SAST工具推介、评测、代码审计、培训资料、应用安全咨询、SAST检测规则、安全漏洞数据处理、许可证数据处理、组件数据处理等。