최근에 앱 개발(은 아니고 백엔드 개발)을 하면서 생각난 히든 메뉴 관련된 아이디어 몇 가지를 적어봤다.
이미 풀린 앱은 로그나 디버거로 보기 힘든데 이런 기능이 있으면 편리할 것 같다.
운영/개발 환경 전환
운영, 개발, 스테이징, 개발PC 등등 환경이 여러 개 있을 경우 환경 전환을 위해 버전을 따로 만들기는 것은 좀 귀찮다.
메뉴에서 환경을 선택할 수 있으면 매우 편하다.
디버그 UI 활성화
내부 정보들을 (예: 항목 ID, ) 추가로 표시한다. 틀리기 쉬운 문자열로 찾기 보다는 ID로 찾는게 수월하다.
내부 파라메터 변경
각종 내부 파라메터를 변경할 수 있도록 한다.
예:
- 미공개 기능 베타 테스트
- 로그 수준 조정 및 디버그 로그 전송.
- User-Agent, (서버에 전송하는) App version 등..
- 서버 점검 상태 무시
- 점검 상태를 App 시작시에만 확인하는 경우: 무시하고 API를 호출한다.
- 서버에서 항시 거부하게 되어 있는 경우: 이 상태를 통과할 수 있는 히든 파라메터를 전송한다.
- 예:
Ignore-Maintenance-Mode: 1
같은 헤더를 추가한다.
- 예:
- 강제 업데이트 무시. 위와 비슷하다.
가장 (impersonation)
가끔 테스트하다 보면 다른 유저 계정으로 작업을 해야 하는 경우도 생긴다. 전지전능한 백엔드 개발자라면 해당 계정의 인증 토큰을 생성해서 cURL 로 직접 요청하거나 다른 방법들이 많이 있지만, App으로 테스트 해야 하는 경우도 있기 마련이다.
- 해당 계정의 인증 토큰을 직접 입력할 수 있도록 한다.
- App에 대상 계정을 입력하면 가장 토큰을 발급받는 메뉴를 만든다.
- 보안을 위해 내부 사용자 인증 과정이 필요하다.
impersonation 기능은 거의 사용할 일은 없을 것 같다. (없는게 정상이다)
App 상태 덤프/로드
부분 또는 전체 APP 상태를 직렬화하여 서버로 보내거나 설정할 수 있게 한다.
변경해야 할 파라메터가 많거나, 재현이 어려운 버그, 내부 상태가 꼬여 발생한 버그 확인 시 등 유리하다.
비밀 메뉴 진입 방법
비밀 키 조합
특정 메뉴에 들어가서 특정 코드를 입력하거나 버튼을 n회 터치하면 비밀 메뉴로 진입한다.
보안 강화를 위해 추가로 암호를 입력받게 할 수도 있다.
예:
- Android 4.2+ 개발자 옵션
- Konami code. 이건 앱에 적용하기는 무리일듯 하다.
커스텀 URL scheme 사용
커스텀 URL scheme 핸들러를 만들고 내부에서만 이 링크를 공유한다.
App 플로우가 복잡한 경우 비밀 키 조합보다는 진입이 쉽고, 더 안전하다.
예:
awesomeapp://cheat/power-overwhelming # 슈퍼 히든 메뉴
awesomeapp://cheat/black-sheep-wall # 디버그 UI 활성화
...
보안
- 실수 또는 고의(?) 로 위 방법을 누설하거나
- 사용자가(?) 앱을 뜯어 암호/URL을 알아낸 경우
진입 방법이 외부로 노출될 수 있다. 이 경우에 대비해 몇 가지 보안책도 마련했다. 단 바이너리를 수정하는 경우는 논외.
해싱
암호 또는 커스텀 URL을 원본 문자열로 저장하지 않고 해싱하여(SHA256 등) 저장한다. 암호가 고정이므로 한번 유출되면 변경하기 전에는 막을 수 없다.
서버 인증
암호나 URL을 서버에서 인증받도록 한다.
“오늘의 암호는 xxxxxxx 입니다.” 라고 공지하는 것 보다 안전하게 진입 URL 링크를 내부 사이트에서 생성하는 방법이 있다.
- 원하는 비밀 메뉴를 폼에 입력한다.
- 서버에서 URL과 인증 코드를 생성한다.
- 생성된 URL을 브라우저에서 보여주거나 SMS, E-Mail로 전송한다.
- 단말에서 이 URL로 진입하면 먼저 서버로 URL을 보내 승인된 URL인지 검사한다.
- 성공시 동작을 수행한다.
예:
-
생성된 URL:
awesomeapp://cheat/power-overwhelming?auth=TDspuRqZwPKLfdET
-
검증 API 호출:
https://developer.example.com/verify-internal-menu?url=awesomeapp%3A%2F%2Fcheat%2Fpower-overwhelming%3Fauth%3DTDspuRqZwPKLfdET
-
결과:
200 OK
or401 Unauthorized
보안을 위해서 검증 API와 통신은 https만 사용하고 CA도 특정 CA로 제한하면 더 좋다.
위에서 설명한 서버 점검 상태 무시나 강제 업데이트의 경우 Ignore-Maintenance-Mode: 1
처럼 고정 값을 사용하면 위험하므로, 대신 서버에서 받은 값을 사용하고 검증하도록 한다.
PKI
서버 인증과 유사하지만, 생성은 서버에서 하되 검증 코드에 PKI를 사용하고 서버를 거치지 않는다.
히든 메뉴 검증 서버는 API 서버와는 별도로 유지하도록 하면 서버 장애나 점검과는 관련이 없으니 크게 장점이 있을지는 잘 모르겠다.
RSA 보다는 ed25519 같은 알고리즘을 사용하면 잘못 사용하기도 어렵고 서명 길이도 짧다 (64바이트).
라이브러리는 libsodium 을 사용하면 될 것 같다. 바인딩도 언어별로 있다.
추가 활용 방안
고객 지원
원격 상담으로는 도저히 답이 안 나온다. 재현도 안된다. 임원이면 더 난감하다.
App 상태를 덤프해서 티켓 번호를 지정하여 서버로 보내는 커스텀 URL scheme를 생성하여 SMS 또는 E-Mail로 전송한다.
awesomeapp://internal/cs?ticket=123456&auth=TDspuRqZwPKLfdET