설명
검증되지 않은 사용자 입력으로 데이터베이스 연결의 카탈로그를 선택하면, 애플리케이션이 의도하지 않은 데이터 영역에서 작업할 수 있습니다. java.sql.Connection.setCatalog()의 지원과 동작은 드라이버에 따라 달라집니다. 카탈로그 변경 자체가 데이터베이스 계정의 권한을 높이지는 않지만, 그 계정이 접근할 수 있는 다른 데이터가 잘못 조회·변경될 수 있습니다.
잠재적 영향
- 데이터베이스 조작: 공격자가 다른 데이터베이스로 연결을 변경하여 원하지 않는 데이터에 접근하거나 수정할 수 있습니다.
- 서비스 중단: 존재하지 않는 데이터베이스로 설정하면 애플리케이션이 정상적으로 작동하지 않을 수 있습니다.
- 접근 경계 위반: 애플리케이션 계정이 여러 카탈로그에 접근할 수 있으면 사용자나 테넌트 간 데이터 구분이 깨질 수 있습니다.
해결 방법
-
사용자 입력을 기반으로 데이터베이스 설정을 변경하지 않기
- 데이터베이스 설정은 애플리케이션 내부에서 정의된 값만 사용해야 합니다.
-
허용된 값만 선택 가능하도록 제한하기
- 서버가 관리하는 목록에서만 선택하게 하고, 현재 사용자가 그 카탈로그에 접근할 권한도 확인하세요.
-
보안 정책 적용
- 동적 선택이 필요하지 않으면 연결 구성을 고정하세요. 필요한 경우 요청별 권한과 연결 풀의 상태 초기화를 확인해 다음 요청에 설정이 남지 않게 하세요.
예시
Java 9 이상과 javax.servlet API를 사용하는 발췌입니다. 변경 후 목록은 예시이며 모든 호출자에게 허용된 카탈로그라고 가정합니다. 사용자별 권한이 다르면 별도 인가 검사가 필요합니다.
변경 전
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import javax.servlet.http.HttpServletRequest;
public class UnsafeDatabaseConfig {
public void setDatabase(HttpServletRequest request, Connection connection) throws SQLException {
String catalog = request.getParameter("db"); // 사용자 입력값을 직접 사용
connection.setCatalog(catalog);
}
}
변경 후
java
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.SQLException;
import java.util.Set;
import javax.servlet.http.HttpServletRequest;
public class SafeDatabaseConfig {
private static final Set<String> ALLOWED_CATALOGS = Set.of("main_db", "backup_db");
public void setDatabase(HttpServletRequest request, Connection connection) throws SQLException {
String catalog = request.getParameter("db");
if (catalog == null || !ALLOWED_CATALOGS.contains(catalog)) {
throw new SecurityException("Invalid database selection");
}
connection.setCatalog(catalog);
}
}
설명:
- 변경 전:
- 입력을 검증 없이
setCatalog()에 전달하여, 드라이버와 계정이 허용하는 범위에서 의도하지 않은 카탈로그를 선택할 수 있습니다.
- 입력을 검증 없이
- 변경 후:
- 허용된 데이터베이스 목록을 정의하고(
ALLOWED_CATALOGS), 사용자 입력이 이 목록에 포함된 경우에만setCatalog()를 실행하도록 제한합니다.
- 허용된 데이터베이스 목록을 정의하고(