it-swarm-korea.com

널 포인터가 역 참조되는 Java 코드에서 실제로 악용 될 위험이 있습니까?

나는 일반적으로 잘 작성되고 구문 분석 된 Java 코드를 가지고 놀고 있지만, 내 코드 스캔 도구에서 발생하는 이상한 점이 있습니다.

널 포인터 역 참조가 프로그램을 충돌시킬 수 있다는 것을 알고 있지만 코드가 모든 예외를 포착하고 관리하기 위해 작성되었다고 가정하면 누구든지이 문제를 사용할 수있는 실제 공격을 알고 있습니까?

감사하게도받은 코드 조각 :-)

9
Rory Alsop

Null 인 포인터를 사용하려고하면 Java는 NullPointerException 을 발생시킵니다. 이것은 RuntimeException이므로이를 잡을 필요는 없지만 잡을 수 있습니다. . 예를 들어

String iAmNull = null;
iAmNull.trim();

nullPointException이 발생하고 프로그램이 종료됩니다. 그러나 당신이 그것을 잡으면

try {
    String iAmNull = null;<br>
    iAmNull.trim();<br>
} catch (NullPointerException e) {
    log.warn("Null pointer in method x")
}

계속 실행되고 단순히 오류를 기록합니다 (물론 로거를 설정 한 경우). 또는 Exception e를 잡을 수도 있습니다.

Java에서 null 포인터를 기반으로 한 공격은 이론적으로 불가능합니다. Java 가상 머신이 모든 포인터를 처리하기 때문에), 따라서 다음과 같은 경우 문제가되지 않습니다. 코드의 NullPointer.

13
Andreas Arnold

이론적으로 Java에서 모든 종류의 널 포인터 역 참조는 다른 예외와 마찬가지로 Java 내에서 처리 할 수있는 NullPointerException을 트리거합니다. 이것은 이것이 좋은 을 의미하지는 않습니다. 실제로는 결함이있는 부분을 제거하는 것 외에는 그러한 예외로부터 복구하기가 매우 어렵습니다 (즉, 쓰레드 다이를 호출하거나 포괄 절로 돌아 가기). 널 포인터를 따르는 것은 버퍼를 오버런하는 것과 유사합니다. 여전히 버그입니다. 여기서 Java와 보호되지 않는 언어 (예 : C)의 차이점은 Java가 해당 버그의 결과에 대해 더 우아하다는 것입니다. 특히 예외가 호출을 다시 전파합니다. 스택, 모니터 해제 (synchronized 키워드) 및 finally 절 실행, 결함이있는 스레드 만 영향을받습니다.

그러나 실제로 몇 가지 문제가 발생할 수 있습니다. JVM이 널 포인터 역 참조를 트랩하는 방법은 JVM 구현에 달려 있습니다. 그러나 일반적으로 구현하는 것은 다음과 같습니다. 포인터를 따라갑니다. 포인터가 null이면 메모리의 첫 번째 페이지에서 메모리 액세스가 발생하며 OS에서 액세스를 금지합니다. OS는 MMU를 통해 발생을 포착하고 상대적으로 잔인한 방식으로 애플리케이션에 알립니다 (유닉스 계열 시스템에서는 SIGSEGV 신호입니다). JVM은 정보를 받아 NullPointerException로 변환합니다.

JVM이 바이트 코드 인터프리터 또는 JIT 생성 이진 코드의 어딘가에있는 잘못된 opcode 주소 만 수신하기 때문에 신호에서 예외로의 변환은 복잡한 일입니다. JVM은 메소드와 스레드 스택을 찾아야합니다. 이것은 OS가 처음에 사물을 메모리에 저장하는 방법과 약간의 상호 작용을합니다. 이러한 코드는 요즘 주류 플랫폼에서 매우 안정적입니다. 그러나 덜 일반적인 조합 (Sun의 JDK가 FreeBSD로 포팅 됨)에서는 때때로 JVM이 호출자 스택을 찾을 수없는 null 포인터 역 참조가있었습니다 (JVM 코드는 FreeBSD가 아닌 Linux 용으로 조정되었고 분명히 만들었 기 때문입니다. 스택이 있어야하는 위치에 대한 가정, FreeBSD에서 항상 충족되지는 않았던 가정). 결과는 가장 비정상적인 방식으로 즉각적인 JVM 종료였습니다.

또 다른 가능한 문제는 액세스가 "금지 된"페이지 어딘가에 있기 때문에 널 포인터 역 참조가 포착된다는 것입니다. 즉, 주소 공간의 첫 페이지입니다. 그러나 인스턴스 필드에 액세스 할 때 JVM은 일반적으로 올바른 데이터 요소에 직접 액세스합니다. 참조가 원시 코드 수준에서 주소에 대한 포인터 인 경우 x 이고 필드가 개체 구조의 오프셋 n 에 있으면 코드는 주소 x에서 바이트를 읽습니다. + n (이것은 실제로 JVM이 객체를 내부적으로 표현하는 방법에 따라 다르지만 C와 유사한 구조가 일반적입니다). 클래스에 많은 필드가있는 경우 n 은 페이지 크기보다 클 수 있습니다.이 경우 읽기 액세스는 첫 번째 페이지에 해당되지 않습니다. , 그러나 두 번째. 이 상황에서 일어나는 일은 운영 체제에 따라 다릅니다.

"높은 오프셋의 필드"상황은 배열 액세스가 길이 확인되고 "길이"가 일반적으로 객체 헤더에 가까운 일종의 필드이기 때문에 배열에서 발생하지 않습니다. 또한 Java 클래스의 필드 수에는 제한이 있습니다 (클래스 파일 형식에는 65535로 절대 제한이 있으며 각 필드에는 이름과 유형이 있어야하므로 실제로는 그보다 낮습니다. 이것도 클래스 파일 형식이며 그보다 빨리 다른 제한에 도달합니다). 따라서 "일반적인"시스템에서는 문제가 발생하지 않습니다. Sun/Oracle VM을 실행하는 Linux. 이는 대부분 VM 구현자가 알아야 할 사항입니다.

그래서 제 충고는 NullPointerException를 버퍼 오버 플로우 (Java에서는 IndexOutOfBoundsException)처럼 심각한 버그로 간주하는 것입니다. VM 안전은 코드를 디버그하는 데 도움이 될 것입니다 (스택 추적은 정말 편리합니다). 배포하기 전에 충분히 디버그하지 않은 경우 스킨을 저장할 수 있습니다. 하지만 버그는 버그입니다.

20
Thomas Pornin

CWE-476 : NULL 포인터 역 참조 -매우 드문 상황에서 코드 실행이 가능하고 환경이 가능함을 나타냅니다. 그러나 이것은 Java에만 국한되지 않습니다. 내가 생각할 수있는 모든 익스플로잇 웹 사이트를 확인하여 null 포인터를 기반으로하는 Java 익스플로잇이 있는지, 아무것도 찾을 수 없었는지 확인했습니다.

하지만 둘러 보는 동안 Cert 사이트에서이 페이지를 발견했습니다- EXC15-J. NullPointerException을 잡지 마십시오 . 그들은 NullPointerException을 잡는 것이 기껏해야 차선책이며 예외를 피하기 위해 검사를 추가하는 대신 훨씬 느리다고 말합니다. 따라서 응용 프로그램에 따라 고려할 수 있습니다.

6
Mark Davidson

Java 코드에서 null를 역 참조하면 NPE가 발생합니다. C와 달리 오프셋을 매핑 된 메모리에 추가 할 방법이 없습니다. NPE는 스레드의 포착되지 않은 예외 핸들러를 포착하거나 전달합니다.

Java에서 실제 취약점의 원인은 nulls를 허용하지 않는 것입니다. null 변수에 대한 코드를 건너 뛰는 것은 실제로 수행 및 NPEing보다 더 위험합니다. 예를 들어, ClassLoader 참조는 기능이지만 가장 중요한 클래스 로더 (부트 클래스 로더)는 일반적으로 null로 표시됩니다 (일부 Java API는 다음과 같은 경우 추가 보안 검사를 추가합니다. 제공된 클래스 로더 참조는 null)입니다.

4