Description
In a multi-user environment, world-writable files allow other users to change their contents. If an application trusts and reads such a file, an attacker can alter configuration or data to change its behavior. Configuration files, token or key files, and allow-lists are examples where tampering can disable controls, load unintended paths, or cause external connections.
Potential impact
- Data tampering that changes application behavior through false configuration or input.
- Modified configuration or allow-lists that disable features, bypass checks, or enable dangerous options.
- Denial of service when important files are overwritten with empty or invalid content.
- Bypass of authentication or access controls, potentially leading to privilege escalation.
Remediation
- Do not grant world-write access. Set POSIX permissions or ACLs to the exact permissions needed. Calling
File.setWritable(true, true)alone does not remove existing group or other-user write permissions. - On POSIX file systems, pass attributes such as
rw-------toFiles.createFileorcreateTempFileso permissions are restricted at creation. - Verify the owner, actual permissions, and trustworthiness of existing content before reading. Reducing permissions does not undo tampering. Handle permission-change failures and validate or replace untrusted existing files.
- If several users need write access, restrict it to a specific group or ACL rather than everyone.
- Store sensitive files beneath trusted directories that only the owner can modify, and consider options that prevent following symbolic links.
Examples
Before
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(); // 공격자가 바꾼 내용을 그대로 신뢰
}
}
}
After
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();
}
}
}
Explanation:
- Before: The application grants world-write access and then trusts the file when reading it. Another user can overwrite its contents, changing configuration or disrupting the service.
- After: POSIX permissions of
rw-------restrict group and other-user reads and writes. This example assumes a trusted owner and parent directory. Protect the path from replacement, and do not assume that tightening permissions makes an existing file's contents trustworthy.