과도한 전역 쓰기 및 읽기 권한

다른 사용자가 쓸 수 있는 파일을 신뢰하고 읽는 위험

설명

멀티 유저 환경에서 파일에 전역 쓰기(world-writable) 권한이 있으면, 다른 사용자가 그 파일 내용을 임의로 바꿀 수 있습니다. 애플리케이션이 해당 파일을 신뢰하고 읽으면, 공격자는 설정값이나 데이터 조작을 통해 동작을 바꾸거나 오동작을 유도할 수 있습니다. 예를 들어 설정 파일, 토큰/키 파일, 허용 목록 등 신뢰 입력을 가정하는 파일을 월드 쓰기로 둔 뒤 읽으면, 제3자가 내용을 바꿔 서비스 설정 변조, 임의 경로 로드, 의도치 않은 외부 연결 등을 유발할 수 있습니다.

잠재적 영향

  • 데이터 변조: 다른 사용자가 파일 내용을 바꿔 잘못된 설정/데이터로 애플리케이션 동작을 변경할 수 있음
  • 설정 위·변조: config, allowlist 등을 조작해 기능 비활성화, 우회, 위험한 옵션 활성화를 유도할 수 있음
  • 서비스 장애(DoS): 중요 파일을 빈 내용/쓰레기로 덮어써 애플리케이션 예외 발생 및 중단을 초래할 수 있음
  • 보안 통제 우회: 인증/접속 제어 관련 파일을 조작해 우회 또는 권한 상승 상황을 만들 수 있음

해결 방법

  • 최소 권한 원칙: 전역 쓰기를 허용하지 말고 POSIX 권한이나 ACL을 필요한 권한으로 정확히 설정하세요. File.setWritable(true, true)만 호출하면 기존 그룹·다른 사용자 쓰기 권한은 제거되지 않습니다.
  • 안전한 생성: POSIX 파일 시스템에서는 Files.createFile/createTempFile에 rw------- 같은 파일 속성을 전달해 생성 시점부터 권한을 제한하세요.
  • 읽기 전 검증: 소유자, 실제 권한과 내용의 신뢰성을 확인하세요. 권한을 줄여도 이미 변조된 내용은 복구되지 않습니다. 권한 변경 실패를 처리하고, 신뢰할 수 없는 기존 파일은 검증하거나 교체하세요.
  • 그룹/ACL 사용: 여러 사용자 쓰기가 꼭 필요하면 전역이 아닌 특정 그룹 또는 ACL로 제한
  • 민감 파일 경로 보호: 신뢰 디렉터리(소유자만 쓰기 가능) 아래에 저장하고, 심볼릭 링크 따라가기 금지 옵션 고려

예시

변경 전

java
import java.io.*;
import java.nio.file.*;

public class InsecureConfigReader {
    // 취약: 월드 쓰기 후 같은 파일을 신뢰하고 읽음
    public static String loadApiToken() throws Exception {
        File f = new File("/var/app/config/token.txt");
        if (!f.exists()) {
            f.getParentFile().mkdirs();
            f.createNewFile();
        }
        // 잘못된 권한: 모든 사용자에게 쓰기 허용
        f.setWritable(true, false); // world-writable

        try (BufferedReader br = new BufferedReader(new FileReader(f))) {
            return br.readLine(); // 공격자가 바꾼 내용을 그대로 신뢰
        }
    }
}

변경 후

java
import java.io.*;
import java.nio.file.*;
import java.nio.file.attribute.*;
import java.util.Set;

public class SecureConfigReader {
    public static String loadApiToken() throws Exception {
        Path path = Paths.get("/var/app/config/token.txt");
        Files.createDirectories(path.getParent());

        // 1) POSIX 권한을 소유자 전용으로 강제 (rw-------)
        Set<PosixFilePermission> ownerOnly = PosixFilePermissions.fromString("rw-------");
        if (Files.notExists(path)) {
            Files.createFile(path, PosixFilePermissions.asFileAttribute(ownerOnly));
        } else {
            // 기존 파일이라면 Others/Group 쓰기 제거
            Files.setPosixFilePermissions(path, ownerOnly);
        }

        // 2) 추가 방어: JVM File API로도 world write 제거 후, 소유자 쓰기만 허용
        File f = path.toFile();
        f.setWritable(false, false); // group/others 쓰기 제거
        f.setWritable(true, true);   // owner만 쓰기 허용

        try (BufferedReader br = Files.newBufferedReader(path)) {
            return br.readLine();
        }
    }
}

설명:

  • 변경 전: 파일에 월드 쓰기 권한을 부여한 채로 같은 파일을 신뢰하고 읽습니다. 다른 사용자가 내용을 덮어쓸 수 있어 설정 변조, 잘못된 동작, 서비스 장애가 발생할 수 있습니다.
  • 변경 후: POSIX 권한을 rw-------로 설정하여 그룹·다른 사용자의 읽기와 쓰기를 제한합니다. 예시는 신뢰할 수 있는 소유자와 상위 디렉터리를 전제로 합니다. 공격자가 경로를 교체할 수 없도록 보호하고, 기존 파일은 권한 변경만으로 내용까지 신뢰하지 마세요.

참조