Google Play 안전하지 않은 onReceivedSslError 경고 대응하기

logo-google-play-vetor

요즘 들어 구글플레이에 등록한 앱의 코드 레벨의 검증이 수행되고 있나 봅니다. 이번에는 웹뷰를 구현할때에 필히 사용되는 WebViewClient 클래스의 onReceivedSslError 의 처리가 안전하지 않다는 경고가 뜨는 사례가 발생하고 있는데요. 현재 이부분을 정상적으로 처리하지 않은 앱의 경우 업데이트가 이루어지지 않고 있습니다. 이 오류의 대상자가 되면 받는 메일의 내용은 다음과 같습니다.

애플리케이션에 WebViewClient.onReceivedSslError 핸들러가 안전하지 않은 방식으로 구현되었습니다. 특히 해당 구현은 모든 SSL 인증서 확인 오류를 무시하여 앱을 중개인 공격에 취약하게 만듭니다. 공격자는 영향을 받은 WebView의 콘텐츠를 변경하고, 전송된 데이터(예: 로그인 사용자 인증 정보)를 읽고, 자바스크립트를 사용해 앱 내부에서 코드를 실행할 수 있습니다.

SSL 인증서를 제대로 확인하려면 서버에서 제공하는 인증서가 요구사항을 충족할 때마다 코드를 변경하여 SslErrorHandler.proceed()을(를) 호출하고 그렇지 않으면 SslErrorHandler.cancel()을(를) 호출합니다. 대상 앱 및 클래스를 포함하는 이메일 알림이 개발자 계정 주소로 전송됩니다.

최대한 빨리 취약점을 해결하고 업그레이드된 APK의 버전 번호를 올리시기 바랍니다. SSL 오류 핸들러에 대한 자세한 내용은 개발자 도움말 센터의 Google 문서를 참조하시기 바랍니다. 다른 기술 관련 질문은https://www.stackoverflow.com/questions에 게시하고 ‘android-security’ 및 ‘SslErrorHandler’ 태그를 사용하세요. 이 문제에 대한 책임이 있는 타사 라이브러리를 사용하는 경우 타사에 문의하여 이 문제를 해결하시기 바랍니다.

제대로 업그레이드되었는지 확인하려면 업데이트된 버전을 개발자 콘솔에 업로드하고 5시간 후에 다시 확인하세요. 앱이 제대로 업그레이드되지 않은 경우 경고 메시지가 표시됩니다.

이러한 특정 문제가 WebView SSL을 사용하는 일부 앱에는 영향을 미치지 않을 수 있으나 모든 보안 패치를 최신 상태로 유지하는 것이 좋습니다. 사용자를 보안 위험에 노출시키는 취약점을 보유하고 있는 앱은 Google의 악의적 행위 정책 및 개발자 배포 계약의 섹션 4.4를 위반하는 것으로 간주될 수 있습니다.

게시된 모든 앱이 개발자 배포 계약 및 개발자 프로그램 정책을 준수하는지 확인하시기 바랍니다. 궁금한 점이나 우려되는 사항이 있으면 Google Play 개발자 도움말 센터를 통해 지원팀에 문의하세요.

혹은 영어 버전의 경고 메일의 내용은 다음과 같습니다.

Security alert Your application has an unsafe implementation of the WebViewClient.onReceivedSslError handler. Specifically, the implementation ignores all SSL certificate validation errors, making your app vulnerable to man-in-the-middle attacks. An attacker could change the affected WebView’s content, read transmitted data (such as login credentials), and execute code inside the app using JavaScript.

To properly handle SSL certificate validation, change your code to invoke SslErrorHandler.proceed() whenever the certificate presented by the server meets your expectations, and invoke SslErrorHandler.cancel() otherwise. An email alert containing the affected app(s) and class(es) has been sent to your developer account address.

Please address this vulnerability as soon as possible and increment the version number of the upgraded APK. For more information about the SSL error handler, please see our documentation in the Developer Help Center. For other technical questions, you can post to https://www.stackoverflow.com/questions and use the tags “android-security” and “SslErrorHandler.” If you are using a 3rd party library that’s responsible for this, please notify the 3rd party and work with them to address the issue.

To confirm that you’ve upgraded correctly, upload the updated version to the Developer Console and check back after five hours. If the app hasn’t been correctly upgraded, we will display a warning.

Please note, while these specific issues may not affect every app that uses WebView SSL, it’s best to stay up to date on all security patches. Apps with vulnerabilities that expose users to risk of compromise may be considered dangerous products in violation of the Content Policy and section 4.4 of the Developer Distribution Agreement.

Please ensure all apps published are compliant with the Developer Distribution Agreement and Content Policy. If you have questions or concerns, please contact our support team through the Google Play Developer Help Center.

문제가 되는 코드는 WebViewClient를 구현한 다음과 같은 코드입니다. SSL 오류가 발생하면 묻지도 따지지도 않고 그것을 수용하는것을 확인하실 수 있습니다.

@Override
public void onReceivedSslError(WebView view, SslErrorHandler handler, SslError error) {
  handler.proceed();
}

원래는 이곳에 이 유효하지 않은것으로 판단되는 인증서가 문제가 없는지 판단하고 문제가 없을 경우 proceed()를 호출하거나 아닌 경우 cancel()을 호출하도록 처리해 주시면 됩니다. 이 판단을 하는 부분을 어떻게 구현할지는 각 앱마다 혹은 회사마다 다르겠지만 스택오버플로우에서 좋은 예를 발견하였습니다.

invalid_ssl_certificate_theeye

위의 스크린샷은 웹브라우저에서 유효하지 않은 인증서를 가진 HTTPS 홈페이지에 진입할 때 볼 수 있는 경고입니다. 여기에 주목할 부분은 “안전하지 않음(으)로 이동”이라는 문구인데요. 안전하지 않지만 유저가 진입할지 말지를 결정할 수 있게 함으로써 브라우저의 책임을 다했다는 것일까요?

마찬가지로 Android에서도 유효하지 않은 인증서로 판단되었을 경우 유저에게 직접 물어보면 됩니다.

@Override
public void onReceivedSslError(WebView view, final SslErrorHandler handler, SslError error) {
  final AlertDialog.Builder builder = new AlertDialog.Builder(this);
  builder.setMessage(R.string.notification_error_ssl_cert_invalid);
  builder.setPositiveButton("continue", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
      handler.proceed();
    }
  });
  builder.setNegativeButton("cancel", new DialogInterface.OnClickListener() {
    @Override
    public void onClick(DialogInterface dialog, int which) {
      handler.cancel();
    }
  });
  final AlertDialog dialog = builder.create();
  dialog.show();
}

R.string.notification_error_ssl_cert_invalid 에는 유효하지 않은 사이트에 진입할것인지 물어보는 글이 들어가 있으면 되겠네요. 이와 같은 대응을 한 뒤 버전을 업그레이드 하여 구글 플레이에 등록하게 되면 5시간정도 뒤에 해당 경고가 사라지게 됩니다.

참고 : http://stackoverflow.com/questions/36050741/webview-avoid-security-alert-from-google-play-upon-implementation-of-onreceiveds