2014-12-03 2 views
2

Java 응용 프로그램에서 TCP 연결을 허용하는 ServerSocket을 만드는 경우 연결할 수있는 프로세스를 제한하는 방법이 있습니까? 예를 들어다른 프로세스가 ServerSocket을 사용할 수 없도록 ServerSocket을 보호하는 방법은 무엇입니까?

이 내 현재 코드입니다 : (

ServerSocket serverSocket = new ServerSocket(1234); 
Socket socket = serverSocket.accept(); 

및 내 네트워크의 다른 장치와 동일한 시스템에서 실행되는 경우에도 다른 프로세스에 연결할 수 없습니다 있는지 확인하려면이 만약 그렇다면 보안 상 위험 할 것입니다.) 루프백 주소에만 serverSocket을 바인딩하여 전자를 해결할 수 있었지만 (로컬 호스트에 대해서 socket.getRemoteAddress() 포인트가 지정되어 있는지 확인해도 문제가 없었지만) 현재의 프로세스를 제한하는 방법을 찾지 못했습니다.

Android에서이 작업을 수행 할 때 더 많은 문제가 있습니다. 내 응용 프로그램에서는 WebView (내 프로세스 소유)을 만들고이를 serverSocket으로 지정하려고하지만 다른 응용 프로그램이이 응용 프로그램에 연결할 수 없도록하려고합니다.

이 문제를 해결할 방법이 있습니까?

답변

0

다른 프로세스가 ServerSocket에 연결하는 것을 막을 수 있다고 생각하지 않지만 사용자가 또는 다른 프로세스에 속하는지 확실하게 결정할 수있는 연결을 허용합니다.

InetSocketAddress remoteAddress = (InetSocketAddress) socket.getRemoteSocketAddress(); 
String hostname = remoteAddress.getHostName(); 
if (!hostname.equals("localhost")) { socket.close(); } 

이 또는 당신이 (EJP 언급처럼) 127.0.0.1 또는 0.0.0.0과 같은 루프백 주소로 소켓을 바인딩하고이 단계를 건너 뛸 수 있습니다 : 첫 번째 단계는 연결이 로컬 호스트에서 유래 경우 알아낼 수 있습니다. localhost에서 연결이되었다는 것을 알게되면 원격 포트를 찾아 프로세스가 소유하고 있는지 파악해야합니다.

int remotePort = remoteAddress.getPort(); 
if (ownPort(remotePort) == 1) { socket.close(); } 

는 지금까지 내가 아는 한, 자바는 프로세스 포트를 나열하는 데 사용할 수있는 API가없는하지만 당신은 JNI를 통해 그렇게 확실히 할 수 있습니다.

private native int doOwnPort(int port); 

그리고 네이티브 쪽 :

JNIEXPORT jint JNICALL Java_something_doOwnPort(JNIEnv *env, jobject object, jint port) { 
    long totalFDs = getdtablesize(); 
    struct sockaddr_in sa; 
    struct stat sb; 
    // Iterate through all file descriptors 
    for (int i = 0; i < totalFDs; ++i) { 
     // Check if "i" is a valid FD 
     memset(&sb, 0, sizeof(sb)); 
     if (fstat(i, &sb) < 0) 
      continue; 
     // Check if "i" is a socket 
     if (!S_ISSOCK(sb.st_mode)) 
      continue; 
     // Get local address of socket with FD "i" 
     memset(&sa, 0, sizeof(sa)); 
     socklen_t sa_len = sizeof(sa); 
     getsockname(i, (struct sockaddr*) &sa, &sa_len); 
     // Check if the port matches 
     if (sa.sin_port == port) 
      return 1; // We own the port 
    } 
    return -1; // We don't own the port 
} 

PS :이 코드는 리눅스입니다하지만 너무 안드로이드/윈도우/OSX에서 작동해야 자바에 당신이 뭔가를해야합니다.

아마도 FD가 테이블을 반복하지 않아도 포트가 현재 프로세스에 의해 소유되어 있는지 확인하는 더 직접적이고 효율적인 방법이 있지만 별개의 문제입니다. HTH! Android Security Tips에서

+0

안드로이드에서'getdtablesize()'를 찾지 못했습니다. 정의 된 위치를 보여줄 수 있습니까? –

+1

'#include '을 사용하거나 직접 정의하십시오 여기에 : https://github.com/OpenWireSec/metasploit/blob/master/external/source/meterpreter/source/bionic/libc/unistd/getdtablesize.c –

+0

예! 작동합니다! 분명히 Android NDK에는 'ge tdtablesize()'를'unistd.h'에서 사용했지만 다른 구현체를 사용했기 때문에 작동합니다. –

0

당신은 당신의 ServerSocket의에 인증 자신의 어떤 종류를 구현

  • 방화벽을 사용하여 보안

    • 의이 유형을 얻을 수 있습니다. 사용자 이름과 비밀번호를 묻습니다.

    소켓은 별개의 프로세스를 제한하기 위해 설계되지 않았습니다.

  • +0

    방화벽은 네트워크상의 다른 장치로부터의 액세스를 제한하는 데 유용하지만 나는 보이지 않습니다 같은 호스트에서 실행되는 앱을 보호 할 수있는 방법. 사용자 정의 인증은 좋은 생각이며 내 문제를 해결할 것입니다.하지만 소켓 공장에 액세스 할 수 없으므로 (Android의 'WebView'와 같은) 타사 위젯을 사용자 정의 할 수는 없습니다. 'SSLContext.setDefault (...)'에 의해 설정된 것과 같은 애플리케이션 전반의 기본값 : ( –

    +0

    ) webview 문제를 해결하기 위해 JavaScriptInterface를 사용하여 원하는 인증 방식을 구현하거나 사용자 정의 프로토콜을 구현할 수 있습니다. 암호화와 같은 WebViewClient에서 캡처 : // mystuff – rupps

    1

    127.0.0.1, [1]에 바인드하여 로컬 호스트 외부의 프로세스가 보이지 않게 할 수 있습니다. 그러나 로컬 호스트의 모든 프로세스가 로컬 호스트에 연결할 수 있습니다. 그것은 그것이 무엇을위한 것입니다. 이를 특정 프로세스로 제한하려면 프로토콜에 인증 단계를 구현해야합니다.

    왜 보이지 않습니다. localhost의 다른 프로세스를 신뢰할 수 없다면 일반적으로 문제가 많습니다.

    [1] 또는 실제로 127.0.0.x 여기서 1 <= x <= 254. 200과 같이 모호한 숫자를 사용하면 어둡게 도움이 될 수 있지만 여전히 안전하지는 않습니다.

    0

    : 우리는 일부 응용 프로그램을 보았다

    민감한 IPC를 처리하기위한 로컬 호스트 네트워크 포트를 사용합니다. 이러한 인터페이스는 장치의 다른 응용 프로그램에서 액세스 할 수 있으므로이 방법을 권장하지 않습니다. 대신 서비스와 같이 인증이 가능한 경우 Android IPC 메커니즘을 사용해야합니다. (심지어 루프백을 사용하는 것보다 INADDR_ANY에 바인딩하는 것이 더 좋을 것입니다.)

    +0

    감사합니다 mikkokoo! 구글이 웹뷰를 위해 소켓 공장을 커스터마이징하는 방법을 추가하지 않았다는 것은 수치 스럽다 ... 그것은 내 문제를 해결할 뿐이다. 어쩌면 그들은 안드로이드의 미래 버전에서 그것을 할지도 모른다. –

    관련 문제