게시자: Paul Lawrence, 안드로이드 보안 엔지니어
커널은 안드로이드 보안 모델에서 중요한 역할을 합니다. 특히나 안드로이드 플랫폼 버전이 업데이트 되면서 사용자 공간의 보안이 강화되고, 시스템 서비스가 구동되는 프로세스를 분리하여 각각의 프로세스가 갖고 있는 권한을 제한하는 작업이 진행된 후에는 커널 자체가 더 많은 보안 공격의 대상이 되었습니다. 시스템 호출이 바로 공격자가 커널을 대상으로 삼는 흔한 수법입니다.
모든 안드로이드 소프트웨어는 시스템 호출(줄여서 syscall이라고 함)을 통해 Linux 커널과 통신합니다. 커널은 어플리케이션과 같은 사용자 공간 프로세스가 커널과 직접 상호 작용할 수 있도록, 디바이스별 혹은 SOC(System on a chip)별로 다양한 syscall을 제공합니다. 안드로이드에서 모든 앱은 이 방식을 통해 파일을 열거나 바인더(Binder) 메시지를 전송하는등 고유한 시스템 호출로 인덱스된 동작들을 수행합니다. 다만, syscall 중 상당수가 안드로이드에서 전혀 사용되지 않고, 공식적으로 지원되지 않습니다.
안드로이드 O는
seccomp라고 하는 Linux 기능을 활용하여, 어플리케이션이 사용되지 않는 시스템 호출에 접근하는 것을 막습니다. 앱에서 원천적으로 이러한 syscall에 접근할 수 없으므로, 잠재적으로 유해한 앱이 이러한 syscall을 악용할 수 없습니다.
seccomp 필터
안드로이드 O에는 모든 안드로이드 애플리케이션이 파생되는 프로세스인 zygote 프로세스에 설치되는 seccomp 필터가 포함되어 있습니다. 이 필터는 zygote 내부에 설치고, 다시 말해 모든 앱에 일괄 적용됩니다. 따라서 안드로이드 보안 팀은 새롭게 적용되는 seccomp 필터로 인해 기존 앱의 동작에 문제가 되지 않도록 각별히 주의를 기울이고 있습니다. seccomp 필터에서 허용하는 syscall은 다음과 같습니다.
- 바이오닉(안드로이드용 C 런타임)을 통해 노출되는 모든 syscall. 이러한 syscall은 bionic/libc/SYSCALLS.TXT에 정의되어 있습니다.
- 안드로이드 부팅을 허용하는 syscall
- 인기있는 안드로이드 앱들에서 널리 사용중인 syscall들
안드로이드 O의 seccomp 필터는 몇몇 보안 공격에 관련된 swapon/swapoff와 같은 특정 syscall과 앱에서는 사용할 필요가 없는 키 제어 syscall을 차단합니다. 결과적으로 seccomp 필터는 arm64에서 총 271개의 syscall 중 17개를 차단하고, arm에서 총 364개의 syscall 중 70개를 차단합니다.
개발자
여러분의 앱의 동작을 안드로이드 O에서 테스트 하고, 앱이 지원되지 않는 syscall을 사용하고 있는지 확인해보세요.
부적합한 syscall 검색
안드로이드 O에서 시스템은 부적합한 syscall을 사용하는 앱의 작동을 중단시킵니다. 로그 출력에 부적합한 syscall이 표시됩니다. 예를 들면 다음과 같습니다.
03-09 16:39:32.122 15107 15107 I crash_dump32: performing dump of process 14942 (target tid = 14971)
03-09 16:39:32.127 15107 15107 F DEBUG : *** *** *** *** *** *** *** *** *** *** *** *** *** *** *** ***
03-09 16:39:32.127 15107 15107 F DEBUG : Build fingerprint: 'google/sailfish/sailfish:O/OPP1.170223.013/3795621:userdebug/dev-keys'
03-09 16:39:32.127 15107 15107 F DEBUG : Revision: '0'
03-09 16:39:32.127 15107 15107 F DEBUG : ABI: 'arm'
03-09 16:39:32.127 15107 15107 F DEBUG : pid: 14942, tid: 14971, name: WorkHandler >>> com.redacted <<<
03-09 16:39:32.127 15107 15107 F DEBUG : signal 31 (SIGSYS), code 1 (SYS_SECCOMP), fault addr --------
03-09 16:39:32.127 15107 15107 F DEBUG : Cause: seccomp prevented call to disallowed system call 55
03-09 16:39:32.127 15107 15107 F DEBUG : r0 00000091 r1 00000007 r2 ccd8c008 r3 00000001
03-09 16:39:32.127 15107 15107 F DEBUG : r4 00000000 r5 00000000 r6 00000000 r7 00000037
이런 문제가 발생한 경우 개발자는 부적합한 syscall을 호출하지 않도록 앱을 수정해야합니다.
테스트 도중 seccomp 필터 켜고 꺼기
개발자는 필요한 경우, seccomp 필터 기능을 켜거나 끈 후 앱의 동작을 확인할 수 있습니다. 다음을 입력하면
adb shell setenforce 0 && adb stop && adb start
seccomp 정책이 zygote에 설치되지 않습니다. 실행 중인 프로세스에서는 seccomp 정책을 제거할 수 없으므로, 이 옵션이 적용되도록 셸을 다시 시작해야 합니다. 이 기능은 userdebug 혹은 eng 빌드로 동작하는 디바이스에서 지원됩니다.
기기 제조업체
안드로이드 O에는
//bionic/libc/seccomp
에 관련 seccomp 필터가 포함되어 있으므로 기기 제조업체가 추가 구현 작업을 수행할 필요가 없습니다. 하지만
//cts/tests/tests/security/jni/android_security_cts_SeccompTest.cpp
에 seccomp를 검사하는 CTS 테스트가 있습니다. 이 테스트는
add_key
및
keyctl
syscall이 차단되며
openat
이 허용되는지를 검사하고, 이와 더불어 호환성을 위해 존재해야 하는 몇 가지 앱 특정 syscall을 검사합니다.