[JAVA]JAVA실무
[JAVA]보안취약점 조치 예시(기초) PMD
greeniti
2025. 3. 22. 13:04
보안 취약점이 포함된 Java 코드 예제와 PMD가 이를 탐지했을 때의 수정한 코드 예시 입니다.
기초적인 내용이므로 참고만 하시기 바랍니다. 실무에서는 거의 조치되어 수정할 일이 없습니다.
1. SQL Injection 취약점 수정
🔴 취약한 코드 (PMD 경고 발생)
public void vulnerableSQL(String userInput) {
String query = "SELECT * FROM users WHERE username = '" + userInput + "'"; // 위험
Statement stmt = connection.createStatement();
ResultSet rs = stmt.executeQuery(query);
}
✅ 수정된 코드 (PreparedStatement 사용)
public void secureSQL(String userInput) throws SQLException {
String query = "SELECT * FROM users WHERE username = ?";
PreparedStatement pstmt = connection.prepareStatement(query);
pstmt.setString(1, userInput);
ResultSet rs = pstmt.executeQuery();
}
🔹 수정 이유:
- PreparedStatement를 사용하면 SQL Injection 방지가 가능합니다.
- PMD 규칙: security:AvoidUsingHardCodedSQL
2. 하드코딩된 비밀번호 제거
🔴 취약한 코드 (PMD 경고 발생)
public class HardcodedPassword {
private static final String PASSWORD = "12345"; // 위험
}
✅ 수정된 코드 (환경 변수 사용)
public class SecurePassword {
private static final String PASSWORD = System.getenv("DB_PASSWORD");
}
🔹 수정 이유:
- 환경 변수에서 비밀번호를 가져와 하드코딩을 방지함.
- PMD 규칙: security:HardCodedCredential
3. 취약한 암호화 알고리즘 수정
🔴 취약한 코드 (PMD 경고 발생)
import java.security.MessageDigest;
public class WeakHash {
public static String hashPassword(String password) throws Exception {
MessageDigest md = MessageDigest.getInstance("MD5"); // 위험
md.update(password.getBytes());
return new String(md.digest());
}
}
✅ 수정된 코드 (SHA-256 사용)
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.Base64;
public class SecureHash {
public static String hashPassword(String password) throws NoSuchAlgorithmException {
MessageDigest md = MessageDigest.getInstance("SHA-256");
md.update(password.getBytes());
return Base64.getEncoder().encodeToString(md.digest());
}
}
🔹 수정 이유:
- MD5는 취약하므로 SHA-256으로 변경.
- PMD 규칙: security:InsecureCryptoAlgorithm
4. 불안전한 객체 역직렬화 수정
🔴 취약한 코드 (PMD 경고 발생)
import java.io.ObjectInputStream;
import java.io.FileInputStream;
public class UnsafeDeserialization {
public static Object deserialize(String filename) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename)); // 위험
return ois.readObject();
}
}
✅ 수정된 코드 (ObjectInputFilter 적용)
import java.io.ObjectInputStream;
import java.io.FileInputStream;
import java.io.ObjectInputFilter;
public class SafeDeserialization {
public static Object deserialize(String filename) throws Exception {
ObjectInputStream ois = new ObjectInputStream(new FileInputStream(filename));
ois.setObjectInputFilter(filterInfo ->
filterInfo.serialClass() != null && filterInfo.serialClass().getName().startsWith("com.safe"));
return ois.readObject();
}
}
🔹 수정 이유:
- ObjectInputFilter를 사용하여 허용된 클래스만 역직렬화하도록 제한.
- PMD 규칙: security:InsecureDeserialization
📌 결론
PMD는 코드 내 보안 취약점을 찾아내고, 이를 방지할 수 있도록 가이드합니다.
✅ SQL Injection → PreparedStatement 사용
✅ 하드코딩된 비밀번호 → 환경 변수 사용
✅ 취약한 해시 알고리즘 → SHA-256 사용
✅ 불안전한 역직렬화 → ObjectInputFilter 적용