🔓 Private 배열을 반환하는 Public 메서드 KISA A-6 · Private 배열 참조 반환
클래스가 내부 private 배열의 참조 그 자체를 외부에 넘겨줍니다. 호출자가 그 배열을 변조하면 객체의 보호 상태가 몰래 바뀌어, 외부에서 권한을 상승시키거나 잔액을 조작할 수 있습니다.
① getPermissions() 가 내부 배열을 반환 VULNERABLE
Account는 private permissions[]를 가집니다. 게터가 return this.permissions; — 복사본이 아닌 같은 객체를 반환합니다. 참조를 받아 변조한 뒤, 객체의 내부 상태를 다시 확인해 보세요.
객체 내부 상태 (private)
—
canDeleteUsers() / 잔액 검사
—
② 게터가 방어적 복사본을 반환 SECURE
수정된 게터는
permissions.clone()(또는 Collections.unmodifiableList(...))을 반환합니다. 호출자는 분리된 복사본을 받으므로, 변조해도 객체의 private 상태에는 영향이 없습니다.
객체 내부 상태 (private)
—
canDeleteUsers() / 잔액 검사
—
③ 취약 vs 안전 코드
VULNERABLE
// Java
public class Account {
private String[] permissions = {"READ","WRITE"};
private long[] balance = { 100 };
// returns the LIVE internal array reference
public String[] getPermissions() {
return this.permissions; // ⚠ no copy
}
public long[] getBalance() {
return this.balance; // ⚠ no copy
}
}
// caller mutates internal state from outside:
String[] p = acct.getPermissions();
p[0] = "ADMIN"; // object changed!
acct.getBalance()[0] = 999_999; // balance edited
SECURE
// Java — defensive copy on return
public class Account {
private String[] permissions = {"READ","WRITE"};
private long[] balance = { 100 };
public String[] getPermissions() {
return permissions.clone(); // detached copy
}
// or, prefer immutability:
public List<String> permissions() {
return Collections.unmodifiableList(
Arrays.asList(permissions));
}
public long[] getBalance() {
return Arrays.copyOf(balance, balance.length);
}
}
// caller's mutation hits only the copy — internals safe
acct.getPermissions()[0] = "ADMIN"; // no effect
왜 위험한가: 내부 배열 반환은 앨리어싱입니다. 호출자와 객체가 하나의 가변 객체를 공유하게 되어, 세터를 거치지 않고도 캡슐화와 클래스가 지키는 불변식(역할·잔액·한도)을 우회할 수 있습니다. 방어 핵심: 복사본 반환(
clone(), Arrays.copyOf) 또는 불변 뷰(Collections.unmodifiableList) · 가능하면 불변 타입 사용 · 가변 내부 상태의 살아있는 참조를 절대 외부에 노출하지 않기.
⚠️ 교육용 시뮬레이션입니다. 객체·private 필드·공격자는 모두 Java 동작을 모사한 페이지 내부 JavaScript mock이며 실제 시스템은 없습니다.