Android, NDK 를 활용한 클라이언트 앱 위변조 간단하게 방지하기.
사실 앱 위변조 방지는 프로가드만 잘 적용하면 어느정도 방지할 수 있다. 하지만, 클라이언트 앱을 역컴파일 한다면 서버 API 가 노출되는 것을 쉽게 막을수도 없는일이다.
사실 이 문제에 대하여 당장 떠오르는 해결책은 NDK 를 사용하여 서버와 통신하는 것이다. 하지만 서버의 모든 API 호출을 C/C++ 로 구현하기에는 시간적 인적 비용이 부족한 많은 프로젝트에서는 거의 불가능에 가깝지 않을까 생각한다.
그래서 시간이 없는 상황에서는 다음과 같이 간단한 방법을 이용할 것을 권장한다.
코드상에서 서명 값을 가져와서 서버와 첫 접속시 이 값을 보내준다. 서버에는 앱의 서명 값이 이미 저장되어 있으며 이 것을 클라이언트로부터 받은 서명값과 비교하여 위변조된 앱인지 검출하는 것이다. 즉, 앱 빌드시 다른 인증서로 서명한 것들은 위변조로 판별하는 원리이다.
만약 위변조된 앱으로 접속했을 경우 앱에서는 경고창을 띄워주고 세션을 유지하지 않도록 해준다.
서명 값을 가져와 서버로 보내는 과정만큼은 NDK 로 구현하여 서버 API 를 노출하지 않도록 만들어야 하며, 서버로 보내는 서명 값을 공격자가 알 수 없는 값으로 변환하거나 암호화 하는 것이 더 좋을 것이다. 서명 값(인증서 지문, 이 포스팅에서는 서명 값으로 표시하겠다.) 은 APK 파일 내부의 META-INF/CERT.RSA 를 통하여 가져올 수 있기 때문이다.
너무나 당연한 이야기지만 주의할 점은 HTTP 를 사용할 경우 반드시 SSL 을 적용해야 한다. HTTPS 가 아닌 HTTP 는 공격자가 루팅된 폰이나 VPN 을 사용하여 손쉽게 패킷 전송 내용을 훔쳐볼 수 있기 때문이다.
이 것의 구현에 필요한 관련 포스팅은 아래와 같다.
NDK 에서 HTTP 통신 이용하기 : http://www.dev.re.kr/67
NDK 에서 서명 값 가져오기 : http://www.dev.re.kr/72
안드로이드 아닌 자바 코드상에서 서명 값 가져오기 : http://www.dev.re.kr/70
* 여담으로 얼마 전 같이 (동료로) 일했던 분이 앱 위변조 방지에 대한 요구사항을 위하여 서버의 API 를 직접 호출하는 부분을 C/C++ 로 짜고 빌드 하느라 삽질하고 있다는 이야기를 들었다. 시간 + 인력 빵빵한 프로젝트에서는 가능하겠지만 동시에 프로젝트 세 개를 진행하던 그분은 여러 사정 때문에 어쩔 수 없이 한 땀 한 땀 코딩하며 저녁도 못 먹고 매일매일 야근 릴레이를 펼치고 있다. 만약 그 프로젝트에서 누군가가 이런 어렵지 않은 방법을 알고 있었다면 그 분은 매일매일 지치는 야근을 피하지 않았을까 싶다.