setAccessible을 "합법적" 사용으로만 제한하는 방법
그 힘을 알게 되면 알수록java.lang.reflect.AccessibleObject.setAccessible
나는 그것이 무엇을 할 수 있는지에 대해 더욱 놀랐다.이 내용은 질문에 대한 답변에서 수정되었습니다(반사를 사용하여 장치 테스트를 위해 정적 최종 File.separatorChar 변경).
import java.lang.reflect.*;
public class EverythingIsTrue {
static void setFinalStatic(Field field, Object newValue) throws Exception {
field.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
field.set(null, newValue);
}
public static void main(String args[]) throws Exception {
setFinalStatic(Boolean.class.getField("FALSE"), true);
System.out.format("Everything is %s", false); // "Everything is true"
}
}
정말 말도 안 되는 일을 할 수 있습니다.
public class UltimateAnswerToEverything {
static Integer[] ultimateAnswer() {
Integer[] ret = new Integer[256];
java.util.Arrays.fill(ret, 42);
return ret;
}
public static void main(String args[]) throws Exception {
EverythingIsTrue.setFinalStatic(
Class.forName("java.lang.Integer$IntegerCache")
.getDeclaredField("cache"),
ultimateAnswer()
);
System.out.format("6 * 9 = %d", 6 * 9); // "6 * 9 = 42"
}
}
아마도 API 설계자들은 얼마나 많은 정보를 얻을 수 있는지 알고 있을 것이다.setAccessible
그럴 수도 있지만, 그것을 제공할 정당한 용도가 있다는 것을 인정해야 한다.그래서 질문하겠습니다.
- 의 진정한 합법적 용도는 무엇입니까?
setAccessible
?- Java는 애초에 이러한 요구를 갖지 않도록 설계되었을까요?
- 이러한 설계의 부정적인 결과는 무엇입니까?
- 제한할 수 있나요?
setAccessible
합법적 사용에만 적용됩니까?- 경유만 되나요?
SecurityManager
?- 어떻게 작동합니까?화이트리스트/블랙리스트, 상세도 등
- 어플리케이션으로 설정해야 하는 경우가 자주 있습니까?
- 제 수업을 쓸 수 있을까요?
setAccessible
- 어떤 경우에도 사용할 수 있음SecurityManager
구성?- 아니면 구성을 관리하는 사람에게 맡겨야 하나요?
- 경유만 되나요?
한 가지 더 중요한 질문은 '이것에 대해 걱정할 필요가 있는가?'입니다.
내 수업들 중 어떤 것도 강요할 수 있는 사생활은 전혀 없는 것 같아.싱글톤 패턴(그 장점에 대한 의구심은 제쳐두고)은 이제 강제하는 것이 불가능하다.위의 제 단편에서 알 수 있듯이 Java의 기초가 어떻게 동작하는지에 대한 몇 가지 기본적인 가정조차 보장되지 않습니다.
이러한 문제는 현실적이지 않은가?
네, 방금 확인했습니다.setAccessible
Java 문자열은 불변하지 않습니다.
import java.lang.reflect.*;
public class MutableStrings {
static void mutate(String s) throws Exception {
Field value = String.class.getDeclaredField("value");
value.setAccessible(true);
value.set(s, s.toUpperCase().toCharArray());
}
public static void main(String args[]) throws Exception {
final String s = "Hello world!";
System.out.println(s); // "Hello world!"
mutate(s);
System.out.println(s); // "HELLO WORLD!"
}
}
이게 큰 걱정이라고 생각하는 사람은 저뿐인가요?
이 점에 대해 걱정할 필요가 있습니까?
작성 중인 프로그램 유형과 아키텍처에 따라 달라집니다.
만약 당신이 foo.jar라는 소프트웨어 컴포넌트를 전 세계 사람들에게 배포한다면, 어쨌든 당신은 완전히 그들의 마음대로입니다.이들은 (리버스 엔지니어링 또는 직접 바이트 코드 조작을 통해) .jar 내의 클래스 정의를 변경할 수 있습니다.JVM 등에서 코드를 실행할 수 있습니다.이 경우 걱정해도 소용없다.
HTTP를 통해 사용자 및 시스템과만 통신하고 애플리케이션 서버를 제어하는 웹 애플리케이션을 작성하는 경우에도 문제가 되지 않습니다.물론 당신의 회사의 동료 코드 작성자들은 당신의 싱글톤 패턴을 깨는 코드를 만들 수 있지만, 그들이 정말로 원할 경우에만 만들 수 있습니다.
향후 Sun Microsystems/Oracle에서 코드를 작성하는 일이며 Java 코어 또는 기타 신뢰할 수 있는 컴포넌트의 코드를 작성하는 업무를 맡고 있다면 주의해야 합니다.하지만 걱정만 하면 머리카락이 빠질 뿐이다.어느 경우든 보안 코딩 가이드라인과 내부 문서를 읽도록 지시할 수 있습니다.
Java 애플릿을 작성하려면 보안 프레임워크에 유의해야 합니다.서명되지 않은 애플릿이 setAccessible을 호출하려고 하면 보안만 발생합니다.예외.
set Accessible만이 기존의 무결성 검사를 수행하는 것은 아닙니다.sun.misc라는 API가 아닌 핵심 Java 클래스가 있습니다.메모리에 직접 액세스 하는 등, 거의 모든 것을 할 수 있는 안전하지 않습니다.Native Code(JNI; 네이티브코드)도 이러한 종류의 제어를 우회할 수 있습니다.
샌드박스 환경(Java Applets, JavaFX 등)에서는 각 클래스가 일련의 권한을 가지고 있으며 안전하지 않은, setAccessible 및 정의 네이티브 구현에 대한 액세스는 SecurityManager에 의해 제어됩니다.
"자바 액세스 수식자는 보안 메커니즘이 아닙니다.
이는 Java 코드가 실행되는 위치에 따라 크게 달라집니다.핵심 Java 클래스는 액세스 수식자를 보안 메커니즘으로 사용하여 샌드박스를 적용합니다.
set Accessible의 진정한 합법적 용도는 무엇입니까?
Java 코어 클래스는 보안상의 이유로 비공개로 유지해야 하는 항목에 쉽게 액세스할 수 있는 방법으로 사용합니다.예를 들어 Java Serialization 프레임워크는 개체를 역직렬화할 때 개인 개체 생성자를 호출하기 위해 이를 사용합니다.'시스템'에 대해서 언급이거기서...setErr이 좋은 예입니다만, 이상하게도 시스템 클래스의 메서드 setOut/setErr/setIn은 모두 네이티브 코드를 사용하여 최종 필드의 값을 설정합니다.
또 하나의 명백한 합법적 용도는 오브젝트 내부를 들여다볼 필요가 있는 프레임워크(지속성, 웹 프레임워크, 주입)입니다.
디버거는 일반적으로 동일한 JVM 프로세스에서 실행되지 않고 다른 수단(JPDA)을 사용하는 JVM과의 인터페이스이기 때문에 이 범주에 속하지 않는다고 생각합니다.
Java는 애초에 이러한 요구를 갖지 않도록 설계되었을까요?
잘 대답하기엔 꽤 심오한 질문이네요.네, 하지만 그다지 선호되지 않을 수 있는 다른 메커니즘을 추가해야 합니다.
setAccessible을 합법적인 사용으로만 제한할 수 있습니까?
적용할 수 있는 가장 간단한 OOTB 제한은 SecurityManager를 사용하여 특정 소스로부터의 코드에만 setAccessible을 허용하는 것입니다.이것이 Java가 이미 하고 있는 일입니다.JAVA_에서 제공되는 표준 Java 클래스입니다.HOME에서는 set Accessible을 실행할 수 있지만 foo.com에서 서명되지 않은 애플릿클래스는 set Accessible을 실행할 수 없습니다.앞에서 설명한 바와 같이 이 권한은 바이너리이며, 어느 쪽이든 가지고 있는지 여부에 관계없이 사용할 수 있습니다.setAccessible이 특정 필드/메서드를 수정하고 다른 필드/메서드를 거부하도록 허용하는 명확한 방법은 없습니다.그러나 Security Manager를 사용하면 반영 여부를 불문하고 클래스가 특정 패키지를 완전히 참조할 수 없습니다.
Security Manager 설정에 관계없이 setAccessible-proof로 클래스를 쓸 수 있습니까?아니면 구성을 관리하는 사람에게 맡겨야 하나요?
당신은 할 수 없고 확실히 할 수 있다.
- 의 진정한 합법적 용도는 무엇입니까?
setAccessible
?
유닛 테스트, JVM 내부 (실장 등)System.setError(...)
등입니다.
- Java는 애초에 이러한 요구를 갖지 않도록 설계되었을까요?
- 이러한 설계의 부정적인 결과는 무엇입니까?
많은 것들이 실행될 수 없을 것이다.예를 들어 다양한 Java 지속성, 직렬화 및 종속성 주입은 반사에 의존합니다.실행 시 JavaBeans 규약에 의존하는 거의 모든 것.
- 제한할 수 있나요?
setAccessible
합법적 사용에만 적용됩니까?- 경유만 되나요?
SecurityManager
?
네.
이 일을 하는 게 아니라SecurityManager
블랙리스트/화이트리스트도 좋은 생각입니다.(AFAIK)이 유일한 방법이라는 것입니다.
또한 Java 17은SecurityManager
제거하려고 합니다.JEP 411을 참조해 주세요.그것이 이것이 또 다른 나쁜 생각인 이유이다.
- 어떻게 작동합니까?화이트리스트/블랙리스트, 상세도 등
허가에 따라 다르겠지만, 그 허가는setAccessible
바이너리입니다.세분화를 원하는 경우 제한할 클래스에 대해 다른 보안 관리자와 함께 다른 클래스 로더를 사용해야 합니다.보다 세밀한 논리를 구현하는 맞춤형 보안 관리자를 구현할 수 있을 것 같습니다.
- 어플리케이션으로 설정해야 하는 경우가 자주 있습니까?
아니요.
- 제 수업을 쓸 수 있을까요?
setAccessible
- 어떤 경우에도 사용할 수 있음SecurityManager
구성?- 아니면 구성을 관리하는 사람에게 맡겨야 하나요?
아니, 넌 할 수 없고, 그래, 넌 할 수 있어.
다른 대안은 소스 코드 분석 도구(예: 커스텀)를 사용하여 이를 '강제'하는 것입니다.pmd
또는findbugs
규칙. 또는 (예를 들어)에 의해 식별되는 코드의 선택적 코드 리뷰grep setAccessible ...
.
후속 조치에 대한 응답
내 수업들 중 어떤 것도 강요할 수 있는 사생활은 전혀 없는 것 같아.싱글톤 패턴(그 장점에 대한 의구심은 제쳐두고)은 이제 강제하는 것이 불가능하다.
그게 걱정된다면, 걱정해야 할 것 같네요.하지만 실제로 다른 프로그래머에게 설계 결정을 따르도록 강요해서는 안 됩니다.만약 사람들이 당신의 싱글톤의 여러 예를 무료로 만들기 위해 반성을 사용할 정도로 충분히 어리석다면, 그들은 그 결과를 감수할 수 있다.
한편, 기밀 정보를 공개로부터 보호하는 의미를 포괄하는 「프라이버시」를 의미한다면, 그것은 잘못된 생각이다.Java 응용 프로그램에서 중요한 데이터를 보호하는 방법은 중요한 데이터를 처리하는 보안 샌드박스에 신뢰할 수 없는 코드를 허용하지 않는 것입니다.Java 액세스 수식자는 보안 메커니즘이 아닙니다.
<String example> - 이것이 큰 문제라고 생각하는 것은 저뿐입니까?
아마 :-)뿐만이 아닐 것이다.하지만 IMO, 이건 걱정거리가 아니야.신뢰할 수 없는 코드를 샌드박스에서 실행해야 한다는 것은 인정됩니다.이러한 작업을 수행하는 신뢰할 수 있는 코드/신뢰할 수 있는 프로그래머가 있는 경우, 문제는 예기치 않게 변경 가능한 문자열보다 심각합니다.(논리폭탄, 비밀경로를 통한 데이터 유출 등)
개발팀 또는 운영팀의 "나쁜 행동자" 문제에 대처(또는 완화)하는 방법이 있습니다.그러나 비용이 많이 들고 제약이 심하며 대부분의 사용 사례에서 과잉 살상이 발생합니다.
이러한 관점에서 반사는 실제로 안전/보안과 직교한다.
어떻게 하면 반사를 제한할 수 있을까요?
Java에는 보안 매니저와ClassLoader
보안 모델의 기초가 됩니다.당신의 경우는, 을 참조할 필요가 있다고 생각합니다.
그러나 이것이 반성의 문제를 완전히 해결하지는 않는다.이용할 수 있는 반사능력은 세밀한 인가방법에 따라야 하는데, 지금은 그렇지 않다.예를 들어, 특정 프레임워크가 반사(예: 휴지 상태)를 사용할 수 있지만 나머지 코드는 사용할 수 없습니다.또는 프로그램이 디버깅 목적으로 읽기 전용 방식으로만 반영되도록 허용합니다.
미래에는 주류가 될 수 있는 한 가지 접근방식은 반사 능력을 클래스에서 분리하기 위해 이른바 미러를 사용하는 것입니다.'미러' 메타 레벨 설비의 설계 원칙.그러나 이 문제를 다루는 다양한 연구가 있다.하지만 정적인 언어보다 역동적인 언어의 문제가 더 심각하다는 것에 동의합니다.
반사가 주는 초능력을 걱정해야 할까요?한마디로 이야기할 수 없군요.
네, Java 플랫폼이 보안으로 보호되어야 한다는 점에서 그렇습니다.Classloader
및 보안 매니저입니다.반성을 망치는 능력은 위반으로 볼 수 있다.
어쨌든 대부분의 시스템이 완전히 안전하지는 않다는 점에서 아니다.많은 클래스가 자주 하위 분류될 수 있으며, 그것만으로 시스템을 악용할 수도 있습니다.물론 수업도 할 수 있다.final
또는 다른 병에 분류되지 않도록 밀봉합니다.그러나 이에 따라 올바르게 보호되는 클래스(예: String)는 거의 없습니다.
자세한 설명은 최종 수업에 대한 이 답변을 참조하십시오.보안에 관한 자바 해킹에 대한 자세한 내용은 Sami Koivu의 블로그도 참조하십시오.
Java의 보안 모델은 어떤 면에서는 불충분하다고 볼 수 있습니다.NewSpeak 등의 일부 언어에서는 모듈화에 대해 보다 급진적인 접근방식을 채택하고 있습니다.이 경우 의존성 반전(기본적으로는 아무것도 없음)에 의해 명시적으로 부여되는 것만을 이용할 수 있습니다.
보안은 어쨌든 상대적인 것이라는 점도 중요합니다.언어 레벨에서는 예를 들어 모듈 폼이 CPU를 100% 소비하거나 최대 메모리 용량을OutOfMemoryException
이러한 우려는 다른 방법으로 해결할 필요가 있다.에는 자원 할당량을 되는 Java를 될 이것은 내일의 를 위한 것이
그 주제에 대해 좀 더 자세히 말할 수는 있지만, 내 요점은 알 것 같아.
언급URL : https://stackoverflow.com/questions/2481862/how-to-limit-setaccessible-to-only-legitimate-uses
'programing' 카테고리의 다른 글
Java: 정적 클래스? (0) | 2022.10.23 |
---|---|
Amazon RDS 데이터베이스 서버 인스턴스에서 "mysqladmin flush-hosts" 명령을 실행하는 방법 (0) | 2022.10.23 |
vue-router를 가져오는 동안 Vue가 정의되지 않았음 (0) | 2022.10.23 |
HTML(.html) 파일에 PHP 코드/파일을 추가하려면 어떻게 해야 하나요? (0) | 2022.10.23 |
개인 GitHub 저장소에서 pip을 사용하여 패키지를 설치할 수 있습니까? (0) | 2022.10.23 |